Animations & Transitions

Add smooth entrance effects and prevent flash of unstyled content

Animation attributes help you create polished, professional interfaces with smooth transitions when content loads or changes.

dbind_cloak

Purpose: Hide elements until DBindly finishes processing them, preventing "flash of unstyled content" (FOUC).

Syntax:

<element dbind_cloak>
  <!-- Content hidden until processed -->
</element>

How It Works

  1. CSS rule hides all [dbind_cloak] elements by default
  2. DBindly processes the element (binds data, applies conditions)
  3. DBindly removes the dbind_cloak attribute
  4. Element becomes visible with correct content

Setup

Add this CSS rule to your stylesheet (usually in <head>):

<style>
  [dbind_cloak] {
    display: none !important;
  }
</style>

Or for a fade-in effect:

<style>
  [dbind_cloak] {
    opacity: 0;
    transition: opacity 0.3s ease;
  }
</style>

Basic Usage

<!-- Hide until data is bound -->
<div dbind_cloak>
  <h1 dbind_data="title"></h1>
  <p dbind_data="description"></p>
</div>
 
<!-- Hide conditional elements until processed -->
<span dbind_cloak dbind_show="isActive">Active</span>

Use Cases

1. Prevent Template Flash

Without cloak:

User sees: {{name}} - {{email}}
Then sees: John Doe - john@example.com

With cloak:

User sees nothing, then: John Doe - john@example.com
<div class="user-profile" dbind_cloak>
  <h2 dbind_data="name"></h2>
  <p dbind_data="email"></p>
</div>

2. Conditional Content

Prevent wrong content from flashing:

<div class="auth-status" dbind_cloak>
  <div dbind_show="isLoggedIn">
    Welcome, <span dbind_data="userName"></span>!
  </div>
  <div dbind_show="isGuest">
    Please log in
  </div>
</div>

3. Entire Page/Section

<main dbind_cloak dbind_collection="pageData">
  <header>
    <h1 dbind_data="data.title"></h1>
  </header>
  <article dbind_html="data.content"></article>
  <footer>
    <span dbind_data="data.author"></span>
  </footer>
</main>

4. Navigation with Active States

<nav dbind_cloak>
  <a href="/" dbind_class="homeActiveClass">Home</a>
  <a href="/products" dbind_class="productsActiveClass">Products</a>
  <a href="/about" dbind_class="aboutActiveClass">About</a>
</nav>

Combining with Loading

<div class="content-section" dbind_collection="items">
  <!-- Skeleton shown immediately (no cloak) -->
  <div class="skeleton" dbind_loading="show">
    <div class="skeleton-line"></div>
    <div class="skeleton-line"></div>
  </div>
 
  <!-- Actual content cloaked until data ready -->
  <div dbind_cloak dbind_loading="hide" dbind_repeat="data">
    <div class="item" dbind_data="name"></div>
  </div>
</div>

dbind_transition

Purpose: Apply entrance animations when elements appear or when content changes.

Syntax:

<element dbind_transition="animationType"></element>
<element dbind_transition="animationType:duration"></element>
<element dbind_transition="animationType:duration:delay"></element>

Transition Types

TypeEffectBest For
fadeOpacity fade inText, overlays
slide-upSlide up while fadingCards, list items
slide-downSlide down while fadingDropdowns, notifications
slide-leftSlide from right to leftNavigation, panels
slide-rightSlide from left to rightSide panels
scaleScale up while fadingModals, popups
scale-downScale down while fadingAlerts
blurBlur to clearImages, backgrounds

Parameters

ParameterDefaultDescription
Duration300msAnimation duration
Delay0msDelay before animation starts
<!-- Default: fade, 300ms, no delay -->
<div dbind_transition="fade"></div>
 
<!-- Custom duration -->
<div dbind_transition="slide-up:500"></div>
 
<!-- Duration and delay -->
<div dbind_transition="scale:400:100"></div>

Basic Usage

<!-- Simple fade in -->
<div dbind_transition="fade" dbind_collection="content">
  <h1 dbind_data="data.title"></h1>
</div>
 
<!-- Slide up effect -->
<div dbind_repeat="items" dbind_transition="slide-up">
  <div class="card" dbind_data="name"></div>
</div>

Use Cases

1. Staggered List Animation

<div class="product-grid">
  <div
    dbind_repeat="products"
    dbind_transition="slide-up:300:{{_index * 50}}"
    class="product-card"
  >
    <img dbind_src="image" dbind_alt="name">
    <h3 dbind_data="name"></h3>
    <p dbind_data="price" dbind_format="currency:USD"></p>
  </div>
</div>

This creates a cascading effect where each card animates in sequence.

2. Modal Popup

<!-- Modal backdrop -->
<div
  class="modal-backdrop"
  dbind_show="modalOpen"
  dbind_transition="fade:200"
>
</div>
 
<!-- Modal content -->
<div
  class="modal"
  dbind_show="modalOpen"
  dbind_transition="scale:300:100"
  role="dialog"
  aria-modal="true"
>
  <h2 dbind_data="modalTitle"></h2>
  <div dbind_html="modalContent"></div>
  <button dbind_click="closeModal">Close</button>
</div>

3. Notification Toast

<div class="toast-container">
  <div
    class="toast"
    dbind_show="showToast"
    dbind_transition="slide-down:300"
    dbind_class="toastClass"
    role="alert"
  >
    <span class="toast-icon" dbind_data="toastIcon"></span>
    <span dbind_data="toastMessage"></span>
    <button dbind_click="dismissToast">×</button>
  </div>
</div>

4. Accordion Content

<div class="accordion">
  <div dbind_repeat="sections" class="accordion-item">
    <button
      class="accordion-header"
      dbind_click="toggleSection:{{_index}}"
      dbind_aria-expanded="isOpen"
    >
      <span dbind_data="title"></span>
    </button>
    <div
      class="accordion-content"
      dbind_show="isOpen"
      dbind_transition="slide-down:250"
    >
      <p dbind_data="content"></p>
    </div>
  </div>
</div>

5. Tab Content Switch

<div class="tabs">
  <div role="tablist" class="tab-list">
    <button role="tab" dbind_click="setTab:1">Tab 1</button>
    <button role="tab" dbind_click="setTab:2">Tab 2</button>
    <button role="tab" dbind_click="setTab:3">Tab 3</button>
  </div>
 
  <div dbind_if="activeTab==1" dbind_transition="fade:200" class="tab-panel">
    <h3>Tab 1 Content</h3>
    <p>Content for the first tab.</p>
  </div>
 
  <div dbind_if="activeTab==2" dbind_transition="fade:200" class="tab-panel">
    <h3>Tab 2 Content</h3>
    <p>Content for the second tab.</p>
  </div>
 
  <div dbind_if="activeTab==3" dbind_transition="fade:200" class="tab-panel">
    <h3>Tab 3 Content</h3>
    <p>Content for the third tab.</p>
  </div>
</div>

6. Image Gallery Lightbox

<div
  class="lightbox"
  dbind_show="lightboxOpen"
  dbind_transition="fade:300"
>
  <div class="lightbox-backdrop" dbind_click="closeLightbox"></div>
  <div class="lightbox-content" dbind_transition="scale:400:100">
    <img dbind_src="currentImage" dbind_alt="currentImageAlt">
    <button class="prev" dbind_click="prevImage"></button>
    <button class="next" dbind_click="nextImage"></button>
    <button class="close" dbind_click="closeLightbox">×</button>
  </div>
</div>

7. Dropdown Menu

<div class="dropdown">
  <button
    class="dropdown-trigger"
    dbind_click="toggleDropdown"
    dbind_aria-expanded="isOpen"
  >
    Select Option
  </button>
  <ul
    class="dropdown-menu"
    dbind_show="isOpen"
    dbind_transition="slide-down:200"
    role="listbox"
  >
    <li dbind_repeat="options" role="option" dbind_click="selectOption:{{value}}">
      <span dbind_data="label"></span>
    </li>
  </ul>
</div>

Custom CSS Transitions

You can create custom transitions using CSS:

<style>
  .custom-bounce {
    animation: bounceIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  }
 
  @keyframes bounceIn {
    0% {
      opacity: 0;
      transform: scale(0.3);
    }
    50% {
      opacity: 1;
      transform: scale(1.05);
    }
    70% {
      transform: scale(0.9);
    }
    100% {
      transform: scale(1);
    }
  }
</style>
 
<div dbind_show="showModal" class="custom-bounce">
  Modal content
</div>

Transition Classes Pattern

<style>
  .card-enter {
    opacity: 0;
    transform: translateY(20px);
  }
 
  .card-enter-active {
    opacity: 1;
    transform: translateY(0);
    transition: all 0.3s ease-out;
  }
</style>
 
<div
  dbind_repeat="cards"
  class="card"
  dbind_transition-class="card-enter"
>
  <span dbind_data="title"></span>
</div>

Animation with Loading States

Combine animations with loading for polished UX:

<div class="content-section" dbind_collection="items">
  <!-- Skeleton - no animation (immediate) -->
  <div class="skeleton-list" dbind_loading="show">
    <div class="skeleton-item"></div>
    <div class="skeleton-item"></div>
    <div class="skeleton-item"></div>
  </div>
 
  <!-- Content - animated entrance -->
  <div class="item-list" dbind_loading="hide">
    <div
      dbind_repeat="data"
      dbind_transition="slide-up:300:{{_index * 75}}"
      class="item-card"
    >
      <img dbind_src="image" dbind_alt="name">
      <h3 dbind_data="name"></h3>
    </div>
  </div>
 
  <!-- Empty state - fade in -->
  <div
    class="empty-state"
    dbind_empty="data"
    dbind_transition="fade:400"
    dbind_loading="hide"
  >
    <p>No items found</p>
  </div>
</div>

Respecting Reduced Motion

Always respect user preferences for reduced motion:

/* Base animations */
.animated {
  animation: fadeIn 0.3s ease;
}
 
/* Disable for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
  .animated,
  [dbind_transition] {
    animation: none !important;
    transition: none !important;
  }
}

DBindly automatically respects the prefers-reduced-motion media query and will skip animations for users who have enabled this preference.


Complete Example: Animated Dashboard

<!DOCTYPE html>
<html>
<head>
  <style>
    [dbind_cloak] { display: none !important; }
 
    .dashboard {
      padding: 24px;
      max-width: 1200px;
      margin: 0 auto;
    }
 
    .stats-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 20px;
      margin-bottom: 32px;
    }
 
    .stat-card {
      background: white;
      border-radius: 12px;
      padding: 24px;
      box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    }
 
    .activity-list {
      background: white;
      border-radius: 12px;
      padding: 24px;
    }
 
    .activity-item {
      display: flex;
      gap: 16px;
      padding: 16px 0;
      border-bottom: 1px solid #e5e7eb;
    }
 
    .activity-item:last-child {
      border-bottom: none;
    }
 
    .avatar {
      width: 40px;
      height: 40px;
      border-radius: 50%;
    }
 
    /* Reduced motion support */
    @media (prefers-reduced-motion: reduce) {
      [dbind_transition] {
        animation: none !important;
        transition: none !important;
      }
    }
  </style>
</head>
<body>
  <div class="dashboard" dbind_cloak dbind_collection="dashboard">
    <!-- Header -->
    <header dbind_transition="fade:300">
      <h1>Dashboard</h1>
      <p>Welcome back, <span dbind_data="data.userName"></span></p>
    </header>
 
    <!-- Stats Grid -->
    <section class="stats-grid">
      <div class="stat-card" dbind_transition="slide-up:300:0">
        <span class="stat-label">Total Users</span>
        <span class="stat-value" dbind_data="data.stats.users" dbind_format="compact"></span>
        <span class="stat-change positive" dbind_show="data.stats.usersGrowth > 0">
          +<span dbind_data="data.stats.usersGrowth" dbind_format="percent:1"></span>
        </span>
      </div>
 
      <div class="stat-card" dbind_transition="slide-up:300:75">
        <span class="stat-label">Revenue</span>
        <span class="stat-value" dbind_data="data.stats.revenue" dbind_format="currency:USD"></span>
        <span class="stat-change positive" dbind_show="data.stats.revenueGrowth > 0">
          +<span dbind_data="data.stats.revenueGrowth" dbind_format="percent:1"></span>
        </span>
      </div>
 
      <div class="stat-card" dbind_transition="slide-up:300:150">
        <span class="stat-label">Orders</span>
        <span class="stat-value" dbind_data="data.stats.orders" dbind_format="number"></span>
      </div>
 
      <div class="stat-card" dbind_transition="slide-up:300:225">
        <span class="stat-label">Conversion</span>
        <span class="stat-value" dbind_data="data.stats.conversion" dbind_format="percent:1"></span>
      </div>
    </section>
 
    <!-- Recent Activity -->
    <section class="activity-section" dbind_transition="fade:400:300">
      <h2>Recent Activity</h2>
 
      <div class="activity-list">
        <div
          dbind_repeat="data.activities"
          dbind_transition="slide-up:250:{{_index * 50}}"
          class="activity-item"
        >
          <img dbind_src="user.avatar" dbind_alt="user.name" class="avatar">
          <div class="activity-content">
            <p>
              <strong dbind_data="user.name"></strong>
              <span dbind_data="action"></span>
            </p>
            <time dbind_data="timestamp" dbind_format="date:relative"></time>
          </div>
        </div>
 
        <div class="empty-activity" dbind_empty="data.activities" dbind_transition="fade:300">
          <p>No recent activity</p>
        </div>
      </div>
    </section>
 
    <!-- Notification Toast -->
    <div
      class="toast"
      dbind_show="showToast"
      dbind_transition="slide-down:300"
      role="alert"
      dbind_live="polite"
    >
      <span dbind_data="toastMessage"></span>
      <button dbind_click="dismissToast">×</button>
    </div>
  </div>
 
  <script src="https://api.dbindly.com/dbindly.min.js"></script>
  <script>
    DBindly.init({
      apiUrl: 'https://api.dbindly.com',
      apiKey: 'pk_live_your_api_key'
    });
  </script>
</body>
</html>

Animation Performance Tips

1. Use Transform and Opacity

These properties are GPU-accelerated:

/* Good: GPU accelerated */
.animate {
  transform: translateY(20px);
  opacity: 0;
}
 
/* Avoid: Causes layout recalculation */
.animate {
  margin-top: 20px;
  height: 0;
}

2. Limit Animated Elements

Don't animate hundreds of elements at once:

<!-- Good: Limit visible animations -->
<div dbind_repeat="items" dbind_limit="10" dbind_transition="fade:200">
  <div class="item" dbind_data="name"></div>
</div>

3. Use will-change Sparingly

Only use for elements that will animate:

.modal {
  will-change: transform, opacity;
}

4. Avoid Animation During Scroll

Use intersection observers for scroll-triggered animations.


Next Steps