applyVariant() — tailwindcss Function Reference
Architecture documentation for the applyVariant() function in compile.ts from the tailwindcss codebase.
Entity Profile
Dependency Diagram
graph TD 666b100e_8313_09d0_334c_b0fc7e6b9d54["applyVariant()"] 70b7448d_fd76_0d4b_e635_18f49f8ba1d6["compileAstNodes()"] 70b7448d_fd76_0d4b_e635_18f49f8ba1d6 -->|calls| 666b100e_8313_09d0_334c_b0fc7e6b9d54 2df8f550_5e83_c7f0_edc4_d97e1a7195fc["getVariants()"] 2df8f550_5e83_c7f0_edc4_d97e1a7195fc -->|calls| 666b100e_8313_09d0_334c_b0fc7e6b9d54 101ae1c2_eee3_3589_2aa3_922a6a429d4f["substituteAtVariant()"] 101ae1c2_eee3_3589_2aa3_922a6a429d4f -->|calls| 666b100e_8313_09d0_334c_b0fc7e6b9d54 f4f92a3d_c13e_a751_8402_451ffa4c772f["rule()"] 666b100e_8313_09d0_334c_b0fc7e6b9d54 -->|calls| f4f92a3d_c13e_a751_8402_451ffa4c772f c35acfc6_964d_737e_6ecc_275e6f10293a["atRule()"] 666b100e_8313_09d0_334c_b0fc7e6b9d54 -->|calls| c35acfc6_964d_737e_6ecc_275e6f10293a a32bba76_f60d_883f_1ff1_276a0bb9db9f["walk()"] 666b100e_8313_09d0_334c_b0fc7e6b9d54 -->|calls| a32bba76_f60d_883f_1ff1_276a0bb9db9f 143002c2_0d0e_8f60_a309_097512cbff95["get()"] 666b100e_8313_09d0_334c_b0fc7e6b9d54 -->|calls| 143002c2_0d0e_8f60_a309_097512cbff95 style 666b100e_8313_09d0_334c_b0fc7e6b9d54 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
packages/tailwindcss/src/compile.ts lines 177–258
export function applyVariant(
node: Rule,
variant: Variant,
variants: Variants,
depth: number = 0,
): null | void {
if (variant.kind === 'arbitrary') {
// Relative selectors are not valid as an entire arbitrary variant, only as
// an arbitrary variant that is part of another compound variant.
//
// E.g. `[>img]:flex` is not valid, but `has-[>img]:flex` is
if (variant.relative && depth === 0) return null
node.nodes = [rule(variant.selector, node.nodes)]
return
}
// SAFETY: At this point it is safe to use TypeScript's non-null assertion
// operator because if the `candidate.root` didn't exist, `parseCandidate`
// would have returned `null` and we would have returned early resulting in
// not hitting this code path.
let { applyFn } = variants.get(variant.root)!
if (variant.kind === 'compound') {
// Some variants traverse the AST to mutate the nodes. E.g.: `group-*` wants
// to prefix every selector of the variant it's compounding with `.group`.
//
// E.g.:
// ```
// group-hover:[&_p]:flex
// ```
//
// Should only prefix the `group-hover` part with `.group`, and not the `&_p` part.
//
// To solve this, we provide an isolated placeholder node to the variant.
// The variant can now apply its logic to the isolated node without
// affecting the original node.
let isolatedNode = atRule('@slot')
let result = applyVariant(isolatedNode, variant.variant, variants, depth + 1)
if (result === null) return null
if (variant.root === 'not' && isolatedNode.nodes.length > 1) {
// The `not` variant cannot negate sibling rules / at-rules because these
// are an OR relationship. Doing so would require transforming sibling
// nodes into nesting while negating them. This isn't possible with the
// current implementation of the `not` variant or with how variants are
// applied in general (on a per-node basis).
return null
}
for (let child of isolatedNode.nodes) {
// Only some variants wrap children in rules. For example, the `force`
// variant is a noop on the AST. And the `has` variant modifies the
// selector rather than the children.
//
// This means `child` may be a declaration and we don't want to apply the
// variant to it. This also means the entire variant as a whole is not
// applicable to the rule and should generate nothing.
if (child.kind !== 'rule' && child.kind !== 'at-rule') return null
let result = applyFn(child, variant)
if (result === null) return null
}
// Replace the placeholder node with the actual node
{
walk(isolatedNode.nodes, (child) => {
if ((child.kind === 'rule' || child.kind === 'at-rule') && child.nodes.length <= 0) {
child.nodes = node.nodes
return WalkAction.Skip
}
})
node.nodes = isolatedNode.nodes
}
return
}
// All other variants
let result = applyFn(node, variant)
if (result === null) return null
}
Domain
Subdomains
Source
Frequently Asked Questions
What does applyVariant() do?
applyVariant() is a function in the tailwindcss codebase.
What does applyVariant() call?
applyVariant() calls 4 function(s): atRule, get, rule, walk.
What calls applyVariant()?
applyVariant() is called by 3 function(s): compileAstNodes, getVariants, substituteAtVariant.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free