Skip to content
On this page

Variants

Variants allow you to apply some variations to your existing rules, like the hover: variant from Tailwind.

Example

ts
variants: [
  // hover:
  (matcher) => {
    if (!matcher.startsWith('hover:'))
      return matcher
    return {
      // slice `hover:` prefix and passed to the next variants and rules
      matcher: matcher.slice(6),
      selector: s => `${s}:hover`,
    }
  }
],
rules: [
  [/^m-(\d)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
]
variants: [
  // hover:
  (matcher) => {
    if (!matcher.startsWith('hover:'))
      return matcher
    return {
      // slice `hover:` prefix and passed to the next variants and rules
      matcher: matcher.slice(6),
      selector: s => `${s}:hover`,
    }
  }
],
rules: [
  [/^m-(\d)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
]
  • matcher controls when the variant is enabled. If the return value is a string, it will be used as the selector for matching the rules.
  • selector provides the availability of customizing the generated CSS selector.

Under the hood

Let's have a tour of what happened when matching for hover:m-2:

  • hover:m-2 is extracted from users usages
  • hover:m-2 send to all variants for matching
  • hover:m-2 is matched by our variant and returns m-2
  • the result m-2 will be used for the next round of variants matching
  • if no other variant is matched, m-2 will then goes to match the rules
  • our first rule get matched and generates .m-2 { margin: 0.5rem; }
  • finally, we apply our variants' transformation to the generated CSS. In this case, we prepended :hover to the selector hook

As a result, the following CSS will be generated:

css
.hover\:m-2:hover { margin: 0.5rem; }
.hover\:m-2:hover { margin: 0.5rem; }

With this, we could have m-2 applied only when users hover over the element.

Going further

The variant system is very powerful and can’t be covered fully in this guide, you can check the default preset’s implementation to see more advanced usages.

Released under the MIT License.