Transition duration
Set transition duration with a bounded millisecond value or arbitrary time.
Set how long a transition takes. Duration does not choose which property changes, so pair it with a transition utility and a state change.
Quick reference
| Example class | Expected declarations |
|---|---|
duration-150 | transition-duration: 150ms; |
Example setup
Every preview explicitly uses spec: 1, reset: "none", strict mode, spacingUnit: "0.25rem", no breakpoints, and defaultTransitionTimingFunction: "ease". The buttons move only 8px on hover or focus-visible, and the longest sample is 420ms. Authored demo CSS sets transition time to zero for prefers-reduced-motion: reduce.
Examples in use
Compare two bounded timings
Both buttons move by the same small amount; duration-150 and duration-300 change only the transition time.
<div class="wind-demo-motion"><button type="button" class="wind-demo-trigger transition-transform duration-150 hover:translate-x-[8px] focus-visible:translate-x-[8px]">150ms</button><button type="button" class="wind-demo-trigger transition-transform duration-300 hover:translate-x-[8px] focus-visible:translate-x-[8px]">300ms</button></div>@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-150 {
transition-duration: 150ms;
}
.duration-300 {
transition-duration: 300ms;
}
@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-150",
"hover:translate-x-[8px]",
"focus-visible:translate-x-[8px]",
"duration-300"
]
}
}
}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 an arbitrary time
duration-[420ms] sets one custom duration while hover and focus-visible trigger an 8px vertical movement.
<div class="wind-demo-motion"><button type="button" class="wind-demo-trigger transition-transform duration-[420ms] hover:translate-y-[8px] focus-visible:translate-y-[8px]">A one-off 420ms duration</button></div>@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-\[420ms\] {
transition-duration: 420ms;
}
@media (hover: hover) {
.hover\:translate-y-\[8px\]:hover {
--zw-translate-y: 8px;
translate: var(--zw-translate-x) var(--zw-translate-y);
}
}
.focus-visible\:translate-y-\[8px\]:focus-visible {
--zw-translate-y: 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-[420ms]",
"hover:translate-y-[8px]",
"focus-visible:translate-y-[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
An integer suffix is interpreted as milliseconds from 0 through 60000, so duration-300 means 300ms and duration-0 disables interpolation. Use duration-[420ms] for a one-off CSS time. Duration has no named token scale. The default 150ms comes from transition utilities; adding duration-* overrides that value.
Related guides: Utility grammar · Variants
Catalog details
duration
| Field | Value |
|---|---|
| Catalog identifier | v1.duration |
| Class pattern | duration-<suffix> |
| Grammar | {"acceptedKinds":["integer","arbitrary"],"arbitraryProperty":"transition-duration","allowsFractionSlash":false,"allowsColorOpacity":false} |
| Accepted values | The catalog has no separate accepted-value records for this entry. |
| Token categories | No token category |
| Negative-value policy | forbidden |
| Conflict group and rank | duration (36) |
| Order rank | 0 |
| Selector shape | ownElement |
| Spec version | 1 |
| Emitter properties | transition-duration |
Accepted values
The catalog has no separate accepted-value records for this entry.
Declaration templates
| Property | Value kind | Fixed value |
|---|---|---|
transition-duration | resolved | null |
Catalog examples
| Example class | Expected declarations |
|---|---|
duration-200 | transition-duration: 200ms |