tailwindlabs/tailwindcss · error · Error
You cannot use `@apply` inside `@keyframes`.
Error message
You cannot use `@apply` inside `@keyframes`.
What it means
During `@apply` substitution, the AST walker specially handles `@keyframes` rules and forbids any `@apply` at-rule nested inside them. `@keyframes` defines keyframe stops (percentages / `from` / `to`), which cannot themselves receive utility declarations, so applying utilities there is semantically invalid. The walker skips the keyframes subtree after checking, throwing on the first offending `@apply`.
Source
Thrown at packages/tailwindcss/src/apply.ts:36
// Track all nodes containing `@apply`
let parents = new Set<AstNode>()
// Track all the dependencies of an `AstNode`
let dependencies = new DefaultMap<AstNode, Set<string>>(() => new Set<string>())
// Track all `@utility` definitions by its root (name)
let definitions = new DefaultMap(() => new Set<AstNode>())
// Collect all new `@utility` definitions and all `@apply` rules first
walk([root], (node, ctx) => {
if (node.kind !== 'at-rule') return
// Do not allow `@apply` rules inside `@keyframes` rules.
if (node.name === '@keyframes') {
walk(node.nodes, (child) => {
if (child.kind === 'at-rule' && child.name === '@apply') {
throw new Error(`You cannot use \`@apply\` inside \`@keyframes\`.`)
}
})
return WalkAction.Skip
}
// `@utility` defines a utility, which is important information in order to
// do a correct topological sort later on.
if (node.name === '@utility') {
let name = node.params.replace(/-\*$/, '')
definitions.get(name).add(node)
// In case `@apply` rules are used inside `@utility` rules.
walk(node.nodes, (child) => {
if (child.kind !== 'at-rule' || child.name !== '@apply') return
parents.add(node)
for (let dependency of resolveApplyDependencies(child, designSystem)) {View on GitHub (pinned to 16e94cbf7f)
Solutions
- Replace the `@apply` inside `@keyframes` with the literal CSS property (e.g. `opacity: 0`).
- Define the utility styles in the element/animation target and let `@keyframes` only set raw property values.
Example fix
/* before */
@keyframes fade {
from { @apply opacity-0; }
to { @apply opacity-100; }
}
/* after */
@keyframes fade {
from { opacity: 0; }
to { opacity: 1; }
} Defensive patterns
Strategy: validation
Validate before calling
import postcss from 'postcss'
function assertNoApplyInKeyframes(css: string) {
const root = postcss.parse(css)
root.walkAtRules('keyframes', kf => {
kf.walkAtRules('apply', () => {
throw new Error(`@apply is forbidden inside @keyframes at line ${kf.source?.start?.line}`)
})
})
} Prevention
- Keep @keyframes blocks to raw property values only.
- Replace any @apply inside keyframes with literal CSS before building.
- Lint for @apply nested under @keyframes in CI.
When it happens
Trigger: CSS like `@keyframes fade { from { @apply opacity-0; } }`. The `@keyframes` branch at apply.ts:33 walks its children, finds an `@apply` at-rule, and throws at apply.ts:36.
Common situations: Trying to animate using utility values inside `@keyframes`, or copy-pasting utility-based rules into a keyframes block during a refactor.
Related errors
- You cannot use `@apply` with both mixins and utilities. Plea
- You cannot `@apply` the `${candidate}` utility here because
- Circular dependency detected: ${toCss([node])} Relies on:
- The rule `@apply ${list}` must not have a body.
- Cannot apply unprefixed utility class `${candidate}`. Did yo
AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12).
Data as JSON: /api/errors/8242164cdd28bad8.
Report an issue: GitHub.