Configuration
Rules
Rules are responsible for generating CSS declarations for a given class name.
Cheat Sheet
defineConfig({
rules: [
// Static CSS declaration rule
['hidden', { display: 'none' }],
// Dynamic CSS declaration rule
['m-(\\d+)', (match) => ({ margin: `${match[1] / 4}rem` })],
// Static CSS property rule
// .table-auto { table-layout: auto }
// .table-fixed { table-layout: fixed }
['table-(auto|fixed)', 'tableLayout'],
// Static alias rule
// shortcut to multiple utilities
['card', 'py-2 px-4 font-semibold rounded-lg shadow-md'],
// Dynamic alias rule
['card-', ({ $$ }) => `bg-${$$}-400 text-${$$}-100 py-2 px-4 rounded-lg`],
// Single utility alias — need to use `~(...)` as it would be otherwise recognized as a CSS property
['red', '~(text-red-100)'],
// Static alias rule using apply
['btn-green', '@(bg-green-500 hover:bg-green-700 text-white)'],
// Dynamic alias rule using apply
['btn-', ({ $$ }) => `@(bg-${$$}-400 text-${$$}-100 py-2 px-4 rounded-lg)`],
// Static rule with css helper
[
'target-new-tab',
css`
target-name: new;
target-new: tab;
`,
],
// Dynamic rule with css helper
[
'target-new-(tab|window)',
({ 1: $1 }) => css`
target-name: new;
target-new: ${$1};
`,
],
// Style rule
// `box?color=coral` -> `.box\\?color\\=coral{background-color:coral}`
// `box?rounded` -> `.box\\?rounded{border-radius:0.25rem}`
// `box?color=coral&rounded` -> `.box\\?color\\=coral\\&rounded{background-color:coral;border-radius:0.25rem}`
// `box?color=purple&rounded=md` -> `.box\\?color\\=purple\\&rounded\\=md{background-color:purple;border-radius:0.375rem}`
[
'box\\?(.+)',
style({
props: {
color: {
coral: css({
backgroundColor: 'coral',
}),
purple: css`
background-color: purple;
`,
},
rounded: {
'': 'rounded',
md: 'rounded-md',
},
},
}),
],
],
})
The rules
option is an array of rule declarations. A rule declaration consist of pattern and an resolver. When twind encounters a class name that matches the pattern it will call the resolver function with the match and the current context. The order of the rules is important for cases where several rules match — first matching with a result wins.
The pattern is a regular expression or a regular expression like string that is used to match the utility name. If a string is used it will be converted to a regular expression using new RegExp(string)
. Therefore special regular expression characters like .
or ?
need to be escaped. There are some additional rules for the string to regular expression conversion:
- the string will always treated as a starts with eg prefixing it with
^
- if it contains
$
or ends with a-
the remaining string will be available in the match object as$$
- if it does not contains
$
or end with a-
it will be treated as a ends with eg suffixing it with$
For example:
underline
->/^underline$/
matchingunderline
text-
->/^text-/
matchingtext-<...>
ring($|-)
->/^ring($|-)/
matchingring
andring-<...>
The API for defining rules is heavily inspired by unocss.
Twind ensures that the styles are in generated in a predictable order.
More about Twinds implicit style ordering
Please note that the order in the generated CSS is in reverse because the last declaration wins.
- dark - Flag for dark mode rules.
- layer - similar to the
@layer
CSS at-rule- overrides: for utilities that should be applied last. used by
css
helper - utilities: for small, single-purpose classes - default layer for all rules
- aliases: for shortcut and apply rules. used by
shortcut
andapply
helpers - components: is for class-based styles that you want to be able to override with utilities. used by
style
helper - base: for things like reset rules or default styles applied to plain HTML elements. used by
injectGlobal
helper - defaults: for css properties defaults
- overrides: for utilities that should be applied last. used by
- screens: a responsive variation of a rule - Flag for screen variants. They may not always have a
min-width
to be detected by Responsive below. - responsive: Based on extracted
min-width
value - at-rules - Based on the count of special chars (
-:,
) within the at-rule. - Pseudo and group variants - Ensures predictable order of pseudo classes.
- number of declarations - Allows single declaration styles to overwrite styles from multi declaration styles.
- greatest precedence of properties - Ensure shorthand properties are inserted before longhand properties; eg longhand override shorthand
- name comparison
Static Property Rules
Static property rules are used to map a class name to a CSS property. The following example creates a table-
utility that can be parametrized with auto
or fixed
.
rules: [
['table-(auto|fixed)', 'tableLayout'],
],
The corresponding CSS declarations will be generated as follows:
.table-auto {
table-layout: auto;
}
.table-fixed {
table-layout: fixed;
}
Static Rules
Static rules are mapping a class name to an CSS declaration object.
rules: [
['m-1', { margin: '0.25rem' }],
],
Dynamic Rules
Dynamic Rules allow to generate CSS declarations based on the match. The following example creates a margin utility that can be parametrized with a number eg m-0
, m-1
, ...
rules: [
// using string pattern
['m-(\\d+)', (match) => ({ margin: `${match[1] / 4}rem` })],
// using regular expression
[/^m-(\d+)$/, (match) => ({ margin: `${match[1] / 4}rem` })],
],
The first argument of the resolver function is the match result. It provides several useful properties:
$_: string
— the input string0: string
— the matched string1: string
…9: string
— the matched groups$$: string
— the substring following the most recent matchdark: boolean
—true
if the current context is dark mode
The second argument is the context. It provides several useful properties to help you write your rules. The most important ones is theme
which is a function to access the current theme.
The resolver function can return:
- a CSS declaration object
- a falsy value to skip the rule and try other rules
- a string of class names eg a Dynamic Alias Rule
Static Alias Rules
Alias rules are the simplest type of rules. They are used to create a shortcut for multiple utilities. The following example creates a card
utility that is a shortcut for py-2 px-4 font-semibold rounded-lg shadow-md
.
rules: [
['card', 'py-2 px-4 font-semibold rounded-lg shadow-md'],
],
Dynamic Alias Rules
Dynamic alias rules are similar to static alias rules but allow to use the matched value in the generated class names. This is useful when you want to generate a set of classes based on a given value. The following example creates a card-
utility that can be parametrized with a color eg card-blue
.
rules: [
['card-', ({ $$ }) => `bg-${$$}-400 text-${$$}-100 py-2 px-4 rounded-lg`],
],
Style Rules
Style rules are used to complex styles based on the style
helper. They must have prefix and its parameters are passed as a query string. The following example creates a box
utility that can be parametrized with a color
eg box?color=blue
and rounded
.
rules: [
// `box?color=coral` -> `.box\\?color\\=coral{background-color:coral}`
// `box?rounded` -> `.box\\?rounded{border-radius:0.25rem}`
// `box?color=coral&rounded` -> `.box\\?color\\=coral\\&rounded{background-color:coral;border-radius:0.25rem}`
// `box?color=purple&rounded=md` -> `.box\\?color\\=purple\\&rounded\\=md{background-color:purple;border-radius:0.375rem}`
[
'box\\?(.+)',
style({
props: {
color: {
coral: css({
backgroundColor: 'coral',
}),
purple: css`
background-color: purple;
`,
},
rounded: {
'': 'rounded',
md: 'rounded-md',
},
},
}),
],
// label?prop=value&other=propValue
// if the style does not require a property
['label(\\?.+)?', style(/* ... */)],
// if the style requires at least one property
['label\\?(.+)', style(/* ... */)],
]
Further Reading
There are some more options and helpers available to create rules. You can find more examples in the official presets: