Diagnosing Bulma Modal Issues: Class Toggles, Overlay, Scroll Lock and Focus
When a Bulma modal fails to open, stays open, shows a broken overlay, lets the page scroll, or loses focus, the root cause is usually a missing or mis‑toggled .is‑active class or conflicting CSS. Follow the ordered checks to isolate and fix each symptom.
02 Oct 2026, 21:14 UTC

Problem you see in practice
Bulma’s modal is pure CSS. Visibility depends only on the presence of .is-active on the .modal root. Bulma ships no JavaScript, so opening, closing, body‑scroll lock and focus handling must be added by you. When a modal misbehaves the fault is almost always a missing class toggle, an overriding style, or a omitted side‑effect.
The useful takeaway: start by confirming the .is-active state, then inspect computed styles for the overlay and body, and finally verify that your toggle logic adds/removes the class and runs any required side‑effects.
Recognizable conditions and likely causes
| What you observe | Most common cause | Quick check |
|---|---|---|
| Click does nothing, modal stays hidden | .is-active never added to .modal | In DevTools Elements panel, the modal element lacks the is-active class |
| Overlay appears but does not cover the full viewport | Custom CSS changes .modal-background height, position or z‑index | Computed style for .modal-background shows reduced height or a low z‑index value |
| Modal stays visible after clicking the close button or backdrop | .is-active not removed on close (or trigger not reset) | The is-active class remains after the close action |
| Page scrolls behind an open modal | Body overflow not set to hidden while the modal is active | Computed style for body shows overflow: visible |
| Keyboard focus escapes the modal when tabbing | No focus‑trap script or it runs before the modal is painted | Tab moves focus to elements outside .modal-content |
Custom CSS that sets global z-index or overflow rules often interferes with Bulma’s default modal stacking and scroll lock.
Ordered checks
-
Validate markup and base classes
Open DevTools, locate the modal element. It should look like:
Check that the root has class<div class="modal" id="example-modal"> <div class="modal-background"></div> <div class="modal-content">…</div> <button class="modal-close is-large" aria-label="close"></button> </div>modaland that the background and content children exist. -
Confirm the class toggle on open and close
With the Elements panel open, click the trigger. Theis-activeclass should appear on the.modalelement only when the modal is meant to be visible. Add a temporary console log around your toggle function, e.g.:
If the class is added to the wrong element or not added at all, the modal will not show.const modal = document.getElementById('example-modal'); console.log('toggle', modal.classList.contains('is-active')); -
Inspect overlay and stacking
When the modal is active, select the.modal-backgroundand view its computed styles. It should haveposition: fixed,inset: 0(ortop/right/bottom/left: 0) and a z‑index higher than the page content (Bulma uses 4). Look for any overridden height,positionor z‑index values. -
Check body scroll lock
With the modal open, inspect the computed style ofbody. Your toggle code should setoverflow: hiddenwhile.is-activeis present and restore the previous value on close. If overflow staysvisible, the background will scroll; if it is never restored, the page remains locked after close. -
Validate focus behavior
Open the modal and press Tab. Focus should stay inside.modal-contentand return to the trigger when the modal closes. Ensure your focus‑trap script runs afteris-activeis added and the modal is painted, moving focus to the first focusable element inside.modal-contenton open and restoring it on close.
Fixes tied to findings
- Modal not opening: Make sure the click handler adds
.is-activeto the.modalroot. Verify the selector matches the actual ID or class; no state change means no visual change. - Overlay not covering viewport: Remove or scope any custom CSS that alters
.modal-backgroundheight,positionor z‑index. Restore Bulma’s defaults and re‑apply custom styling with a more specific selector (e.g.#example-modal .modal-background). - Modal remains visible after close: Ensure the close handler removes
.is-activefrom the modal and also removes any body‑scroll‑lock class or inline style you added. Check both the backdrop click and the close‑button paths. - Background scrolls: Add logic that stores the original
body.style.overflowvalue, sets it tohiddenon open, and restores it on close. Use a counter if multiple modals can be open simultaneously. - Focus trap broken: Initialise the trap after the modal receives
.is-activeand is visible. On open, move focus to the first focusable element inside.modal-content; on close, return focus to the trigger element.
Limitations and practical verification
Bulma supplies only the styles. Scroll lock, focus management and ARIA attributes are your responsibility. The steps above assume a standard Bulma modal structure and a custom toggle script.
To confirm a fix, repeat the three verification points: (1) presence of .is-active in the Elements panel, (2) computed styles for .modal-background (full viewport, correct z‑index) and body (overflow hidden while open), and (3) manual keyboard navigation to ensure focus stays trapped. Do not rely on visual appearance alone; inspect the computed values.
Escalation criteria
- Custom CSS overrides persist after scoping attempts and the overlay or stacking cannot be restored without breaking other components.
- Multiple modals interact and class toggles conflict, causing intermittent stuck states.
- Focus‑trap behavior differs across browsers and your current library does not support the required timing.
In those cases, isolate the modal in a minimal test page that loads only Bulma CSS and your toggle code to determine whether the issue stems from framework interaction or application logic.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.