Home / Function/ applyVariant() — tailwindcss Function Reference

applyVariant() — tailwindcss Function Reference

Architecture documentation for the applyVariant() function in compile.ts from the tailwindcss codebase.

Function typescript OxideEngine Scanner calls 4 called by 3

Entity Profile

Dependency Diagram

graph TD
  adc16be1_fc13_4928_7caf_2acb3a5e9877["applyVariant()"]
  214bac69_e516_bea4_67fa_4e9e092ced3b["compile.ts"]
  adc16be1_fc13_4928_7caf_2acb3a5e9877 -->|defined in| 214bac69_e516_bea4_67fa_4e9e092ced3b
  e57db502_ed4e_4f14_1b2a_b25af3c0477d["compileAstNodes()"]
  e57db502_ed4e_4f14_1b2a_b25af3c0477d -->|calls| adc16be1_fc13_4928_7caf_2acb3a5e9877
  07f1b2bc_24ef_8001_336d_024bfd71a55c["getVariants()"]
  07f1b2bc_24ef_8001_336d_024bfd71a55c -->|calls| adc16be1_fc13_4928_7caf_2acb3a5e9877
  0ec6110b_085e_e69b_cc4a_37d966dc5ace["substituteAtVariant()"]
  0ec6110b_085e_e69b_cc4a_37d966dc5ace -->|calls| adc16be1_fc13_4928_7caf_2acb3a5e9877
  f9b19679_c1f0_28d6_4d1a_31a10c52e42d["atRule()"]
  adc16be1_fc13_4928_7caf_2acb3a5e9877 -->|calls| f9b19679_c1f0_28d6_4d1a_31a10c52e42d
  ed78da58_8727_ad98_120c_61f35cea357a["walk()"]
  adc16be1_fc13_4928_7caf_2acb3a5e9877 -->|calls| ed78da58_8727_ad98_120c_61f35cea357a
  66319c06_7c38_f9ea_4bf0_2a0e18bac1a4["rule()"]
  adc16be1_fc13_4928_7caf_2acb3a5e9877 -->|calls| 66319c06_7c38_f9ea_4bf0_2a0e18bac1a4
  826fa88e_aa5d_5bf5_f2c6_9a0302d5b02f["get()"]
  adc16be1_fc13_4928_7caf_2acb3a5e9877 -->|calls| 826fa88e_aa5d_5bf5_f2c6_9a0302d5b02f
  style adc16be1_fc13_4928_7caf_2acb3a5e9877 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

Frequently Asked Questions

What does applyVariant() do?
applyVariant() is a function in the tailwindcss codebase, defined in packages/tailwindcss/src/compile.ts.
Where is applyVariant() defined?
applyVariant() is defined in packages/tailwindcss/src/compile.ts at line 177.
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