IPhone Keyboard block Bootstrap 5 Bottom Canvas
Describe the issue
I'm building a Vue 3 project with Bootstrap 5, and I've implemented a dynamic bottom canvas (offcanvas) where users can add and interact with content. However, on iPhones, when the keyboard pops up (e.g., during form input), it blocks the bottom canvas, preventing the content from being displayed or accessed properly.
I've tried using CSS solutions like position: fixed;, bottom: 0;, and overflow: auto;, but they didn't resolve the issue. The problem seems specific to iOS handling of fixed-position elements when the keyboard is active.
Has anyone faced a similar issue with iOS keyboards and dynamic bottom canvases? Any suggestions or workarounds would be greatly appreciated!
my code
<template>
<TransitionGroup
enter-active-class="animate__animated animate__slideInUp animate__faster"
leave-active-class="animate__animated animate__slideOutDown"
:duration="45"
>
<div
v-for="(modal, index) in modalStore.modals"
:key="index"
:class="['offcanvas', 'offcanvas-bottom', { show: modal.isOpen }]"
data-bs-backdrop="false"
tabindex="-1"
aria-labelledby="offcanvasBottomLabel"
:style="{ height: modal.height }"
>
<!-- Modal Header -->
<!-- <div class="offcanvas-header" v-if="modal.props.title">
<h5 class="offcanvas-title">{{ modal.props.title }}</h5>
</div> -->
<!-- Modal Body -->
<component :is="modal.component" v-bind="modal.props"></component>
<!-- Modal Footer (conditionally rendered) -->
<div class="offcanvas-footer" v-if="modal.showFooter == true">
<div class="d-grid">
<button
type="button"
class="modal-close-btn"
@click="closeModal(modal.name)"
aria-label="Close"
>
<i class="fa-solid fa-chevron-down"></i>
</button>
</div>
</div>
</div>
</TransitionGroup>
<!-- Conditionally Render Backdrop -->
<div
v-if="modalStore.modals.length > 0"
class="offcanvas-backdrop fade show"
@click="handleBackdropClick"
></div>
</template>
<script>
import { useModalStore } from "../../../libs/store/modalStore";
export default {
setup() {
const modalStore = useModalStore();
const closeModal = (name) => {
modalStore.closeModal(name);
};
// Backdrop click handler
const handleBackdropClick = () => {
// Get the most recent modal (top-most on the stack)
const currentModal = modalStore.modals[modalStore.modals.length - 1];
// Close the modal if `closeOverlay` is not explicitly false
if (currentModal.props.closeOverlay !== false) {
closeModal(currentModal.name);
}
};
return {
modalStore,
closeModal,
handleBackdropClick,
};
},
};
</script>
i try adding this to script but still didnt work
const adjustModalForIOSKeyboard = () => {
const modalElement = document.querySelector(".offcanvas-bottom");
if (!modalElement) return;
const onKeyboardShow = (event) => {
// Get the keyboard height from the event (iOS provides it)
const keyboardHeight = event?.keyboardHeight || 300; // Fallback height
// Adjust modal height to avoid being blocked by the keyboard
modalElement.style.height = `calc(100vh - ${keyboardHeight}px)`;
};
const onKeyboardHide = () => {
// Reset modal height when the keyboard is hidden
modalElement.style.height = "100%";
};
// Listen to iOS-specific keyboard events
window.addEventListener("keyboardDidShow", onKeyboardShow);
window.addEventListener("keyboardDidHide", onKeyboardHide);
// Fallback for other platforms: focus events
document.body.addEventListener("focusin", onKeyboardShow); // Simulates `keyboardDidShow`
document.body.addEventListener("focusout", onKeyboardHide); // Simulates `keyboardDidHide`
};
onMounted(() => {
adjustModalForIOSKeyboard();
});
onUnmounted(() => {
// Cleanup event listeners
window.removeEventListener("keyboardDidShow", adjustModalForIOSKeyboard);
window.removeEventListener("keyboardDidHide", adjustModalForIOSKeyboard);
});