Documentation Index Fetch the complete documentation index at: https://mintlify.com/finsweet/attributes/llms.txt
Use this file to discover all available pages before exploring further.
The fs-smartlightbox attribute solves common CSS stacking issues with Webflow lightboxes by temporarily moving the lightbox element to be a direct child of <body>. This prevents problems with z-index, position: fixed, and transform properties on parent elements.
The Problem
Webflow lightboxes can break when parent elements have:
Custom z-index values that create new stacking contexts
transform properties that affect fixed positioning
Overflow properties that clip the lightbox
Complex nested positioning that interferes with the lightbox overlay
The Solution
When a lightbox opens, the attribute:
Removes the lightbox element from its current position in the DOM
Appends it as a direct child of <body>
Restores it to its original position when closed
This ensures the lightbox is always rendered above all other content without CSS conflicts.
Installation
< script src = "https://cdn.jsdelivr.net/npm/@finsweet/attributes-smartlightbox@1/smartlightbox.js" ></ script >
Elements
Open Trigger
Defines the button or element that opens the lightbox:
< button fs-smartlightbox-element = "trigger-open" > Open Lightbox </ button >
Close Trigger
Defines the button or element that closes the lightbox:
< button fs-smartlightbox-element = "trigger-close" > Close </ button >
Toggle Trigger
Defines a trigger that toggles between open and close states:
< button fs-smartlightbox-element = "trigger-toggle" > Toggle Lightbox </ button >
Lightbox Element
Defines the element with position: fixed that will be moved:
< div fs-smartlightbox-element = "lightbox" class = "lightbox-wrapper" >
<!-- Lightbox content -->
</ div >
If the lightbox element is not specified, the attribute will use the closest parent of the trigger-open element that needs to be moved.
Basic Usage
Simple Lightbox
< div class = "lightbox-container" >
<!-- Open button -->
< button fs-smartlightbox-element = "trigger-open" class = "open-btn" >
View Gallery
</ button >
<!-- Lightbox with fixed positioning -->
< div fs-smartlightbox-element = "lightbox" class = "lightbox-overlay" >
< div class = "lightbox-content" >
< button fs-smartlightbox-element = "trigger-close" class = "close-btn" >
Close
</ button >
< img src = "image.jpg" alt = "Gallery image" >
</ div >
</ div >
</ div >
.lightbox-overlay {
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 vw ;
height : 100 vh ;
background : rgba ( 0 , 0 , 0 , 0.8 );
display : none ;
}
.lightbox-overlay.active {
display : flex ;
align-items : center ;
justify-content : center ;
}
< div >
< button fs-smartlightbox-element = "trigger-toggle" class = "toggle-btn" >
< span class = "open-text" > Open </ span >
< span class = "close-text" style = "display: none;" > Close </ span >
</ button >
< div fs-smartlightbox-element = "lightbox" class = "lightbox" >
<!-- Lightbox content -->
</ div >
</ div >
Configuration
Wait Setting
Add a delay (in milliseconds) before the open or close action:
< button
fs-smartlightbox-element = "trigger-open"
fs-smartlightbox-wait = "300"
>
Open Lightbox
</ button >
This is useful for:
Coordinating with CSS transitions
Allowing animations to complete
Creating smooth state changes
Delayed Open
Delayed Close
< button
fs-smartlightbox-element = "trigger-open"
fs-smartlightbox-wait = "200"
>
Open
</ button >
Advanced Examples
Multiple Lightboxes with Instances
<!-- First lightbox -->
< div >
< button
fs-smartlightbox-element = "trigger-open"
fs-smartlightbox = "gallery-1"
>
Gallery 1
</ button >
< div
fs-smartlightbox-element = "lightbox"
fs-smartlightbox = "gallery-1"
class = "lightbox"
>
< button fs-smartlightbox-element = "trigger-close" fs-smartlightbox = "gallery-1" >
Close
</ button >
<!-- Gallery 1 content -->
</ div >
</ div >
<!-- Second lightbox -->
< div >
< button
fs-smartlightbox-element = "trigger-open"
fs-smartlightbox = "gallery-2"
>
Gallery 2
</ button >
< div
fs-smartlightbox-element = "lightbox"
fs-smartlightbox = "gallery-2"
class = "lightbox"
>
< button fs-smartlightbox-element = "trigger-close" fs-smartlightbox = "gallery-2" >
Close
</ button >
<!-- Gallery 2 content -->
</ div >
</ div >
Video Lightbox
< div class = "video-container" >
< button
fs-smartlightbox-element = "trigger-open"
class = "play-btn"
>
Play Video
</ button >
< div fs-smartlightbox-element = "lightbox" class = "video-lightbox" >
< div class = "video-wrapper" >
< button
fs-smartlightbox-element = "trigger-close"
fs-smartlightbox-wait = "300"
class = "close-btn"
>
×
</ button >
< video controls autoplay >
< source src = "video.mp4" type = "video/mp4" >
</ video >
</ div >
</ div >
</ div >
< div >
< button fs-smartlightbox-element = "trigger-open" class = "cta-btn" >
Sign Up
</ button >
< div fs-smartlightbox-element = "lightbox" class = "form-lightbox" >
< div class = "form-container" >
< button fs-smartlightbox-element = "trigger-close" class = "close-btn" >
Cancel
</ button >
< form class = "signup-form" >
< h2 > Create Account </ h2 >
< input type = "email" placeholder = "Email" >
< input type = "password" placeholder = "Password" >
< button type = "submit" > Sign Up </ button >
</ form >
</ div >
</ div >
</ div >
How It Works
DOM Manipulation
When the open trigger is clicked:
// Store the original parent and position
const { parentElement } = element ;
const elementIndex = [ ... parentElement . children ]. indexOf ( element );
// Move to body
window . setTimeout (() => {
document . body . appendChild ( element );
}, timeout );
When the close trigger is clicked:
// Restore to original position
parentElement . insertBefore ( element , parentElement . children [ elementIndex ]);
Position Restoration
The attribute preserves the exact DOM position by:
Storing a reference to the parent element
Recording the element’s index among siblings
Inserting it back at the same index when closing
This ensures that the lightbox returns to its exact original position in the DOM tree, maintaining all relationships with surrounding elements.
Best Practices
Use Fixed Positioning
The lightbox element should have position: fixed:
.lightbox {
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 vw ;
height : 100 vh ;
z-index : 9999 ;
}
Add Transitions
Coordinate the fs-smartlightbox-wait value with CSS transitions:
.lightbox {
opacity : 0 ;
transition : opacity 0.3 s ease ;
}
.lightbox.active {
opacity : 1 ;
}
< button
fs-smartlightbox-element = "trigger-open"
fs-smartlightbox-wait = "300"
>
Open
</ button >
Prevent Body Scroll
Add custom JavaScript to prevent scrolling when the lightbox is open:
const openTrigger = document . querySelector ( '[fs-smartlightbox-element="trigger-open"]' );
const closeTrigger = document . querySelector ( '[fs-smartlightbox-element="trigger-close"]' );
openTrigger . addEventListener ( 'click' , () => {
document . body . style . overflow = 'hidden' ;
});
closeTrigger . addEventListener ( 'click' , () => {
document . body . style . overflow = '' ;
});
Background Click to Close
< div
fs-smartlightbox-element = "lightbox"
fs-smartlightbox-element = "trigger-close"
class = "lightbox-overlay"
>
< div class = "lightbox-content" onclick = " event . stopPropagation ()" >
<!-- Content here - clicks won't close -->
</ div >
</ div >
Troubleshooting
Lightbox Not Moving
Verify the lightbox element is correctly specified
Check that triggers have the correct element attributes
Ensure the lightbox has position: fixed
CSS Transitions Not Working
Add fs-smartlightbox-wait to match your transition duration
Ensure transitions are applied to the lightbox element
Check that class names are toggled correctly
Multiple Instances Conflicting
Use unique instance names: fs-smartlightbox="unique-name"
Ensure all related elements share the same instance value
Avoid nesting lightboxes within each other