Advanced · Generic tween

Name the properties, not the effect.

Fifteen properties, two directions. Compiled to real CSS keyframes.

Monochrome teal portrait in a curved sculptural hat

data-kui="tween-from y:64px rotate:-7deg scale:0.88 opacity:0 1100ms expo-out on:load"

Arbitrary values. Still not JavaScript.

A block with only a to step gets its from from the element itself.

press
click the block
data-kui="tween x:96px rotate:12deg scale:1.12 900ms on:click"

1 you write

<div data-kui="tween
  x:96px
  rotate:12deg
  scale:1.12
  900ms on:click">

2 the compiler writes — live

3 the browser interpolates

@keyframes kui-tween-to-translate {
  to {
    translate:
      var(--kui-tween-x, 0)
      var(--kui-tween-y, 0)
      var(--kui-tween-z, 0);
  }
}
/* no `from` step */

Fifteen properties, seven groups

One keyframe block per group, not per property.

translate · x y z

x
data-kui="tween-from x:-160px 900ms expo-out"
y
data-kui="tween-from y:120 900ms expo-out" — bare number, implied px
z
data-kui="tween-from z:-560px 1100ms expo-out"

rotate · rotate — about z only

rotate
data-kui="tween-from rotate:-180deg 1000ms expo-out"
rotate:45
data-kui="tween-from rotate:45 1000ms bounce" — bare number, implied deg

scale · scale scale-x scale-y

scale
data-kui="tween-from scale:0.2 900ms bounce"
scale-x
data-kui="tween-from scale-x:0.1 900ms expo-out"
scale-y
data-kui="tween-from scale:1.6 scale-y:0.1 900ms expo-out"

opacity · opacity

opacity
data-kui="tween-from opacity:0 1000ms"

filter · blur brightness saturate grayscale

Beauty portrait with white curls, cobalt lips and blue fur gloves framing the face
data-kui="tween-from blur:24px 1100ms"
Close profile portrait lit entirely in orange, round tinted glasses and a glossy jacket
data-kui="tween-from brightness:0.05 1100ms"
Profile portrait wearing stacked gold cube earrings against a warm neutral backdrop
data-kui="tween-from saturate:6 1100ms"
Beauty portrait with a yellow bob wig, yellow eyeshadow, and freckles against a yellow backdrop
data-kui="tween-from grayscale:1 1100ms"

color · color background · background-color

colour
data-kui="tween-from color:#e4f222 1200ms"
bg
data-kui="tween-from background-color:#e4f222 1200ms"

A property is written whole — an axis you don't name returns to its initial value.

To, and from

Same values, opposite ends — GSAP's .to()/.from() pair, in CSS.

to
click the block
data-kui="tween x:120px opacity:0.15 rotate:24deg 700ms on:click" — ends where you wrote
from
click the block
data-kui="tween-from x:120px opacity:0.15 rotate:24deg 700ms on:click" — starts where you wrote
compose
data-kui="tween-from scale:0.5 900ms, fade-in 900ms" — disjoint channels compose

Channels come off your attribute. tween-from scale:0.5 composes with fade-in; tween-from y:120px collides with it, because fade-in owns translate too.

What we won't animate, and why

widthheighttopleft

All four animate layout. The tween declares perfClass: 'paint'.

Instead: flip-reorder, accordion-height, grid-to-list

rotate-xrotate-y

CSS's rotate takes one axis at a time, and perspective lives in the transform shorthand — a different channel.

Instead: flip-in-x, flip-in-y

skew

Same shorthand problem — and there is no skew property to write.

Instead: the named effects that own the shorthand

tween

Any named property, A to B.

FLIP

Moves it because the layout changed.

motion-path

Moves it along a curve you draw.

Animating into and out of the DOM

Six names that animate a display: none element. Manual by construction — open one.

fade-openOpacity only.
data-kui="fade-open" — 240ms ease-out
pop-openOpacity and scale.
data-kui="pop-open" — 240ms, scale 0.92
scale-openScale, no fade.
data-kui="scale-open" — 240ms, scale 0.92
drop-openSettles down from above.
data-kui="drop-open" — 240ms, distance 8px
slide-open-upArrives travelling upward.
data-kui="slide-open-up" — 240ms, distance 16px
slide-open-downThe mirror.
data-kui="slide-open-down" — 240ms, distance 16px

the same three, turned up

distance:20pxAgainst the 8px default.
data-kui="drop-open distance:20px 320ms"
scale:0.8Against the 0.92 default.
data-kui="scale-open scale:0.8 320ms"
700ms bouncePositional timing.
data-kui="pop-open scale:0.7 700ms bounce"

three ways to drive one — [data-open] above, plus these two

Native popoverNo page JavaScript.
data-kui="pop-open 320ms" on a [popover] — driven by :popover-open
Native <dialog>Driven by [open].
data-kui="slide-open-up 320ms" on a <dialog> — driven by [open]

A form control is just an element

on:focus/blur is a trigger pair — the second half reverses the first.

data-kui="tween scale:1.03 brightness:1.08 220ms on:focus/blur" — tab into the first field
tween on a <select>, a checkbox and a range — hover, click, hover
Every field cascades in
data-kui="cascade:70ms" on the fieldset, data-kui="tween-from y:24px opacity:0 600ms" on each control

Purpose-built form effects also ship — label-float input-underline-grow focus-ring-grow checkbox-draw radio-fill range-fill toggle-morph strength-meter validate-check validate-shake step-progress submit-to-spinner-to-check