zfb
GitHub repository

Type to search...

to open search from anywhere

Easing

Set transition timing with a configured easing token or arbitrary timing function.

Choose the pace of a transition: how it accelerates and slows between its starting and ending values.

Quick reference

Example classExpected declarations
ease-gentletransition-timing-function: var(--zw-ease-gentle);
Example setup

Every preview explicitly uses spec: 1, reset: "none", strict mode, spacingUnit: "0.25rem", no breakpoints, and defaultTransitionTimingFunction: "ease". The named example adds tokens.easings.gentle as cubic-bezier(0.2, 0, 0, 1); the other uses a direct CSS timing function. Both use a 300ms transition and move only 8px on hover or focus-visible. Authored demo CSS removes transition time for reduced-motion users.

Examples in use

Name a reusable timing curve

The preview config defines tokens.easings.gentle, then ease-gentle selects that curve for the 300ms movement.

Name a reusable timing curve
HTML
<div class="wind-demo-motion"><button type="button" class="wind-demo-trigger transition-transform duration-300 ease-gentle hover:translate-x-[8px] focus-visible:translate-x-[8px]">Configured gentle curve</button></div>
CSS
@layer zw-reset, zw-tokens, zfb-hi, base, components;
@layer zw-tokens {
  :root {
    --zw-ease-gentle: cubic-bezier(.2, 0, 0, 1);
    --zw-spacing-unit: .25rem;
  }
}
@property --zw-translate-x {
  syntax: "<length-percentage>";
  inherits: false;
  initial-value: 0px;
}
@property --zw-translate-y {
  syntax: "<length-percentage>";
  inherits: false;
  initial-value: 0px;
}
.wind-demo-motion {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  max-width: 38rem;
  color: #24364b;
  font: 15px / 1.5 system-ui, sans-serif;
}

.wind-demo-motion button {
  min-width: 9rem;
  border: 1px solid #526477;
  border-radius: .35rem;
  background: #eef3f8;
  color: inherit;
  padding: .65rem .9rem;
  font: inherit;
  text-align: left;
}

.wind-demo-motion button:focus-visible {
  outline: 3px solid #1670b8;
  outline-offset: 3px;
}

.wind-demo-motion .wind-demo-trigger {
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  .wind-demo-motion .wind-demo-trigger {
    transition-duration: 0s !important;
  }
}
.transition-transform {
  transition-property: transform,translate,rotate,scale;
  transition-duration: 150ms;
  transition-timing-function: ease;
}
.duration-300 {
  transition-duration: 300ms;
}
.ease-gentle {
  transition-timing-function: var(--zw-ease-gentle);
}
@media (hover: hover) {
  .hover\:translate-x-\[8px\]:hover {
    --zw-translate-x: 8px;
    translate: var(--zw-translate-x) var(--zw-translate-y);
  }
}
.focus-visible\:translate-x-\[8px\]:focus-visible {
  --zw-translate-x: 8px;
  translate: var(--zw-translate-x) var(--zw-translate-y);
}
Configuration for this example
{
  "wind": {
    "spec": 1,
    "reset": "none",
    "strict": true,
    "tokens": {
      "spacingUnit": "0.25rem",
      "easings": {
        "gentle": "cubic-bezier(0.2, 0, 0, 1)"
      }
    },
    "breakpoints": {},
    "defaultTransitionTimingFunction": "ease",
    "authoredClasses": {
      "wind-demo-motion": true,
      "wind-demo-trigger": true
    },
    "safelist": {
      "docs-preview": [
        "transition-transform",
        "duration-300",
        "ease-gentle",
        "hover:translate-x-[8px]",
        "focus-visible:translate-x-[8px]"
      ]
    }
  }
}
Authored demonstration CSS
.wind-demo-motion { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; max-width: 38rem; color: #24364b; font: 15px/1.5 system-ui, sans-serif; }
.wind-demo-motion button { min-width: 9rem; border: 1px solid #526477; border-radius: 0.35rem; background: #eef3f8; color: inherit; padding: 0.65rem 0.9rem; font: inherit; text-align: left; }
.wind-demo-motion button:focus-visible { outline: 3px solid #1670b8; outline-offset: 3px; }
.wind-demo-motion .wind-demo-trigger { cursor: pointer; }
@media (prefers-reduced-motion: reduce) { .wind-demo-motion .wind-demo-trigger { transition-duration: 0s !important; } }

Use a one-off timing function

ease-[steps(3,end)] creates three visible steps; the same button movement can be inspected with hover or keyboard focus.

Use a one-off timing function
HTML
<div class="wind-demo-motion"><button type="button" class="wind-demo-trigger transition-transform duration-300 ease-[steps(3,end)] hover:translate-x-[8px] focus-visible:translate-x-[8px]">Three deliberate steps</button></div>
CSS
@layer zw-reset, zw-tokens, zfb-hi, base, components;
@layer zw-tokens {
  :root {
    --zw-spacing-unit: .25rem;
  }
}
@property --zw-translate-x {
  syntax: "<length-percentage>";
  inherits: false;
  initial-value: 0px;
}
@property --zw-translate-y {
  syntax: "<length-percentage>";
  inherits: false;
  initial-value: 0px;
}
.wind-demo-motion {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  max-width: 38rem;
  color: #24364b;
  font: 15px / 1.5 system-ui, sans-serif;
}

.wind-demo-motion button {
  min-width: 9rem;
  border: 1px solid #526477;
  border-radius: .35rem;
  background: #eef3f8;
  color: inherit;
  padding: .65rem .9rem;
  font: inherit;
  text-align: left;
}

.wind-demo-motion button:focus-visible {
  outline: 3px solid #1670b8;
  outline-offset: 3px;
}

.wind-demo-motion .wind-demo-trigger {
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  .wind-demo-motion .wind-demo-trigger {
    transition-duration: 0s !important;
  }
}
.transition-transform {
  transition-property: transform,translate,rotate,scale;
  transition-duration: 150ms;
  transition-timing-function: ease;
}
.duration-300 {
  transition-duration: 300ms;
}
.ease-\[steps\(3\,end\)\] {
  transition-timing-function: steps(3,end);
}
@media (hover: hover) {
  .hover\:translate-x-\[8px\]:hover {
    --zw-translate-x: 8px;
    translate: var(--zw-translate-x) var(--zw-translate-y);
  }
}
.focus-visible\:translate-x-\[8px\]:focus-visible {
  --zw-translate-x: 8px;
  translate: var(--zw-translate-x) var(--zw-translate-y);
}
Configuration for this example
{
  "wind": {
    "spec": 1,
    "reset": "none",
    "strict": true,
    "tokens": {
      "spacingUnit": "0.25rem"
    },
    "breakpoints": {},
    "defaultTransitionTimingFunction": "ease",
    "authoredClasses": {
      "wind-demo-motion": true,
      "wind-demo-trigger": true
    },
    "safelist": {
      "docs-preview": [
        "transition-transform",
        "duration-300",
        "ease-[steps(3,end)]",
        "hover:translate-x-[8px]",
        "focus-visible:translate-x-[8px]"
      ]
    }
  }
}
Authored demonstration CSS
.wind-demo-motion { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; max-width: 38rem; color: #24364b; font: 15px/1.5 system-ui, sans-serif; }
.wind-demo-motion button { min-width: 9rem; border: 1px solid #526477; border-radius: 0.35rem; background: #eef3f8; color: inherit; padding: 0.65rem 0.9rem; font: inherit; text-align: left; }
.wind-demo-motion button:focus-visible { outline: 3px solid #1670b8; outline-offset: 3px; }
.wind-demo-motion .wind-demo-trigger { cursor: pointer; }
@media (prefers-reduced-motion: reduce) { .wind-demo-motion .wind-demo-trigger { transition-duration: 0s !important; } }

Custom and named values

There are no built-in named easing tokens. Configure tokens.easings and refer to an entry with ease-<name>, as in ease-gentle. Arbitrary forms such as ease-[steps(3,end)] accept one CSS timing function. wind.defaultTransitionTimingFunction takes a CSS keyword or function, not a token name; an explicit ease-* utility overrides it in the same variant bucket.

Related guides: Utility grammar · Variants

Catalog details

ease

FieldValue
Catalog identifierv1.ease
Class patternease-<suffix>
Grammar{"acceptedKinds":["token","arbitrary"],"arbitraryProperty":"transition-timing-function","allowsFractionSlash":false,"allowsColorOpacity":false}
Accepted valuesThe catalog has no separate accepted-value records for this entry.
Token categorieseasings
Negative-value policyforbidden
Conflict group and rankeasing (37)
Order rank0
Selector shapeownElement
Spec version1
Emitter propertiestransition-timing-function

Accepted values

The catalog has no separate accepted-value records for this entry.

Declaration templates

PropertyValue kindFixed value
transition-timing-functionresolvednull

Catalog examples

Example classExpected declarations
ease-[ease-in]transition-timing-function: ease-in

Revision History

CreatedUpdated