CSS & Animations

Style elements with Tailwind classes, CSS animations, and time-driven CSS custom properties.

Tailwind

Tailwind is configured in all scaffolded compositions. Use utility classes directly on any element:

<ef-timegroup duration="5s" class="w-[1920px] h-[1080px] bg-gradient-to-br from-indigo-900 to-purple-900 flex items-center justify-center">
  <ef-text class="text-white text-8xl font-bold tracking-tight drop-shadow-lg">
    Styled with Tailwind
  </ef-text>
</ef-timegroup>

CSS animations

Standard @keyframes and the animation property work as expected. The renderer steps through frames deterministically so animations are frame-accurate.

animation-fill-mode: both

Prefer to use animation-fill-mode: both (the both keyword in the shorthand). Without it, elements snap to their pre/post-animation state at frame boundaries, causing visible flicker.

Per-segment stagger (ef-text)

When ef-text uses split, each segment gets CSS variables for coordinated animations:

VariableDescription
--ef-stagger-offsetCalculated delay for this segment — use as animation-delay
--ef-indexInteger index (0, 1, 2 …)
--ef-seedDeterministic random 0–1 per segment
<ef-timegroup duration="5s" class="w-[1920px] h-[1080px] bg-slate-900 flex items-center justify-center">
  <ef-text split="word" stagger="100ms" class="text-white text-7xl font-bold text-center max-w-4xl leading-tight">
    Words reveal one by one
  </ef-text>
  <style>
    @keyframes wordReveal {
      from { clip-path: inset(0 100% 0 0); opacity: 0.3; }
      to   { clip-path: inset(0 0% 0 0);   opacity: 1; }
    }
    ef-text-segment {
      display: inline-block;
      animation: wordReveal 0.4s ease-out both;
      animation-delay: var(--ef-stagger-offset);
    }
  </style>
</ef-timegroup>

Use --ef-seed for random variation:

<ef-timegroup duration="5s" class="w-[1920px] h-[1080px] bg-black flex items-center justify-center">
  <ef-text split="char" stagger="50ms" class="text-white text-9xl font-black tracking-widest">
    RANDOM
  </ef-text>
  <style>
    ef-text-segment {
      display: inline-block;
      animation: charIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
      animation-delay: var(--ef-stagger-offset);
      color: hsl(calc(var(--ef-seed) * 280deg + 200deg) 80% 70%);
    }
    @keyframes charIn {
      from {
        transform: translateY(calc(var(--ef-seed) * 60px - 30px)) rotate(calc(var(--ef-seed) * 40deg - 20deg));
        opacity: 0;
      }
      to { transform: translateY(0) rotate(0deg); opacity: 1; }
    }
  </style>
</ef-timegroup>

Time-driven CSS variables

Editframe sets CSS custom properties on every element during rendering and preview. Use them to drive animations directly from the timeline without JavaScript.

VariableDescription
--ef-progressCurrent progress as 0–1 (multiply by 100% when needed)
--ef-durationTotal duration as a CSS time (e.g. 10s)
--ef-transition-durationOverlap duration (only set when parent has overlap)
--ef-transition-out-startWhen the outgoing fade-out should start (duration - overlap)
<ef-timegroup duration="4s" class="w-[1920px] h-[1080px] bg-black flex flex-col items-center justify-center gap-8">
  <ef-text class="text-white text-5xl font-bold">Timeline progress</ef-text>
  <!-- Progress bar driven by --ef-progress, no JavaScript -->
  <div style="
    width: 60%;
    height: 8px;
    background: rgba(255,255,255,0.15);
    border-radius: 4px;
    overflow: hidden;
  ">
    <div style="
      height: 100%;
      background: #818cf8;
      width: calc(var(--ef-progress) * 100%);
    "></div>
  </div>
</ef-timegroup>

Crossfade between scenes

<ef-timegroup mode="sequence" overlap="1.5s" class="w-[1920px] h-[1080px]">
  <ef-timegroup mode="fixed" duration="4s" class="absolute w-full h-full bg-indigo-900 flex items-center justify-center"
    style="animation: var(--ef-transition-duration) fade-out var(--ef-transition-out-start) both;">
    <ef-text class="text-white text-7xl font-bold">Fades Out</ef-text>
  </ef-timegroup>
  <ef-timegroup mode="fixed" duration="4s" class="absolute w-full h-full bg-rose-900 flex items-center justify-center"
    style="animation: var(--ef-transition-duration) fade-in 0s both;">
    <ef-text class="text-white text-7xl font-bold">Fades In</ef-text>
  </ef-timegroup>
  <style>
    @keyframes fade-in  { from { opacity: 0; } to { opacity: 1; } }
    @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
  </style>
</ef-timegroup>

The --ef-transition-duration and --ef-transition-out-start variables are set automatically based on the parent's overlap value — you don't compute them manually.