Skip to main content

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:
  1. Removes the lightbox element from its current position in the DOM
  2. Appends it as a direct child of <body>
  3. 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>
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: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.8);
  display: none;
}

.lightbox-overlay.active {
  display: flex;
  align-items: center;
  justify-content: center;
}

With Toggle Button

<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
<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>

Form Lightbox

<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: 100vw;
  height: 100vh;
  z-index: 9999;
}

Add Transitions

Coordinate the fs-smartlightbox-wait value with CSS transitions:
.lightbox {
  opacity: 0;
  transition: opacity 0.3s 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

  • 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