` will generate:
```css
.hover\:m2:hover,
.m-2 {
margin: 0.5rem;
}
```
Instead of two separate rules:
```css
.hover\:m2:hover {
margin: 0.5rem;
}
.m-2 {
margin: 0.5rem;
}
```
---
---
url: https://unocss.dev/config/variants.md
description: Variants allow you to apply some variations to your existing rules.
---
# Variants
[Variants](https://windicss.org/utilities/general/variants.html) allow you to apply some variations to your existing rules, like the `hover:` variant from Tailwind CSS.
## 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` })],
]
```
* `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; }
```
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](https://github.com/unocss/unocss/tree/main/packages-presets/preset-mini/src/_variants) to see more advanced usages.
---
---
url: https://unocss.dev/config/shortcuts.md
description: >-
The shortcuts functionality that UnoCSS provides is similar to Windi CSS's
one.
---
# Shortcuts
Shortcuts let you combine multiple rules into a single shorthand, inspired by [Windi CSS's](https://windicss.org/features/shortcuts.html).
## Usage
```ts
shortcuts: {
// shortcuts to multiple utilities
'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
'btn-green': 'text-white bg-green-500 hover:bg-green-700',
// single utility alias
'red': 'text-red-100',
}
```
In addition to the plain mapping, UnoCSS also allows you to define dynamic shortcuts.
Similar to [Rules](/config/rules), a dynamic shortcut is the combination of a matcher `RegExp` and a handler function.
```ts
shortcuts: [
// you could still have object style
{
btn: 'py-2 px-4 font-semibold rounded-lg shadow-md',
},
// dynamic shortcuts
[/^btn-(.*)$/, ([, c]) => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`],
]
```
With this, we could use `btn-green` and `btn-red` to generate the following CSS:
```css
.btn-green {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
--un-bg-opacity: 1;
background-color: rgb(74 222 128 / var(--un-bg-opacity));
border-radius: 0.5rem;
--un-text-opacity: 1;
color: rgb(220 252 231 / var(--un-text-opacity));
}
.btn-red {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
--un-bg-opacity: 1;
background-color: rgb(248 113 113 / var(--un-bg-opacity));
border-radius: 0.5rem;
--un-text-opacity: 1;
color: rgb(254 226 226 / var(--un-text-opacity));
}
```
---
---
url: https://unocss.dev/config/theme.md
description: >-
UnoCSS also supports the theming system that you might be familiar with in
Tailwind CSS / Windi CSS.
---
# Theme
UnoCSS also supports the theming system that you might be familiar with in Tailwind CSS / Windi CSS. At the user level, you can specify the `theme` property in your config, and it will be deep-merged to the default theme.
## Usage
```ts
theme: {
// ...
colors: {
veryCool: '#0000ff', // class="text-very-cool"
brand: {
primary: 'hsl(var(--hue, 217) 78% 51%)', //class="bg-brand-primary"
DEFAULT: '#942192' //class="bg-brand"
},
},
}
```
::: tip
During the parsing process, `theme` will always exist in `context`.
:::
### Usage in `rules`
To consume the theme in rules:
```ts
rules: [
[/^text-(.*)$/, ([, c], { theme }) => {
if (theme.colors[c])
return { color: theme.colors[c] }
}],
]
```
### Usage in `variants`
To consume the theme in variants:
```ts
variants: [
{
name: 'variant-name',
match(matcher, { theme }) {
// ...
},
},
]
```
### Usage in `shortcuts`
To consume the theme in dynamic shortcuts:
```ts
shortcuts: [
[/^badge-(.*)$/, ([, c], { theme }) => {
if (Object.keys(theme.colors).includes(c))
return `bg-${c}4:10 text-${c}5 rounded`
}],
]
```
## Breakpoints
::: warning
When a custom `breakpoints` object is provided the default will be overridden instead of merging.
:::
With the following example, you will be able to only use the `sm:` and `md:` breakpoint variants:
```ts
theme: {
// ...
breakpoints: {
sm: '320px',
md: '640px',
},
}
```
::: tip
In `presetWind4` the key was changed changed to `breakpoint`.
For the `presetWind4` theme docs see https://unocss.dev/presets/wind4#theme.
:::
If you want to inherit the `original` theme breakpoints, you can use the `extendTheme`:
```ts
extendTheme: (theme) => {
return {
...theme,
breakpoints: {
...theme.breakpoints,
sm: '320px',
md: '640px',
},
}
}
```
::: info
`verticalBreakpoints` is same as `breakpoints` but for vertical layout.
:::
In addition we will sort screen points by size (same unit). For screen points in different units, in order to avoid errors, please use unified units in the configuration.
```ts
theme: {
// ...
breakpoints: {
sm: '320px',
// Because uno does not support comparison sorting of different unit sizes, please convert to the same unit.
// md: '40rem',
md: `${40 * 16}px`,
lg: '960px',
},
}
```
## ExtendTheme
`ExtendTheme` allows you to edit the **deeply merged theme** to get the complete theme object.
Custom functions mutate the theme object.
```ts
extendTheme: (theme) => {
theme.colors.veryCool = '#0000ff' // class="text-very-cool"
theme.colors.brand = {
primary: 'hsl(var(--hue, 217) 78% 51%)', // class="bg-brand-primary"
}
}
```
It's also possible to return a new theme object to completely replace the original one.
```ts
extendTheme: (theme) => {
return {
...theme,
colors: {
...theme.colors,
veryCool: '#0000ff', // class="text-very-cool"
brand: {
primary: 'hsl(var(--hue, 217) 78% 51%)', // class="bg-brand-primary"
},
},
}
}
```
---
---
url: https://unocss.dev/config/extractors.md
---
# Extractors
Extractors are used to extract the usage of utilities from your source code.
```ts [uno.config.ts]
import { defineConfig } from 'unocss'
export default defineConfig({
extractors: [
// your extractors
],
})
```
By default [extractorSplit](https://github.com/unocss/unocss/blob/main/packages-engine/core/src/extractors/split.ts) will always be applied, which splits the source code into tokens and directly feed to the engine.
To override the default extractors, you can use `extractorDefault` option.
```ts [uno.config.ts]
import { defineConfig } from 'unocss'
export default defineConfig({
extractors: [
// your extractors
],
// disable the default extractor
extractorDefault: false,
// override the default extractor with your own
extractorDefault: myExtractor,
})
```
For example, please check the implementation of [pug extractor](https://github.com/unocss/unocss/blob/main/packages-presets/extractor-pug/src/index.ts) or the [attributify extractor](https://github.com/unocss/unocss/blob/main/packages-presets/preset-attributify/src/extractor.ts).
---
---
url: https://unocss.dev/config/preflights.md
description: >-
You can inject raw CSS as preflights from the configuration. The resolved
theme is available to customize the CSS.
---
# Preflights
You can inject raw CSS as preflights from the configuration. The resolved `theme` is available to customize the CSS.
```ts
preflights: [
{
getCSS: ({ theme }) => `
* {
color: ${theme.colors.gray?.[700] ?? '#333'};
padding: 0;
margin: 0;
}
`,
},
]
```
---
---
url: https://unocss.dev/config/safelist.md
---
# Safelist
Safelist is an important option in UnoCSS configuration that allows you to specify a set of utility classes that should always be included in the generated CSS, regardless of whether these classes are detected in your source code.
## Basic Usage
### String Array
The simplest usage is to provide a string array containing the class names you want to preserve:
```ts
// uno.config.ts
export default defineConfig({
safelist: [
'p-1',
'p-2',
'p-3',
'text-center',
'bg-red-500'
]
})
```
### Function Form
Safelist can also contain functions that are called during build time and can dynamically return class names:
```ts
// uno.config.ts
export default defineConfig({
safelist: [
// Static class names
'p-1',
'p-2',
// Dynamic function
context => ['m-1', 'm-2', 'm-3'],
(context) => {
// Generate class names based on theme
const colors = Object.keys(context.theme.colors || {})
return colors.map(color => `bg-${color}-500`)
}
]
})
```
### Mixed Usage
You can mix strings and functions in the same safelist configuration:
```ts
// uno.config.ts
export default defineConfig({
safelist: [
// Static class names
'prose',
'bg-orange-300',
// Dynamic generation
() => ['flex', 'grid', 'block'],
// Conditional dynamic generation
(context) => {
if (process.env.NODE_ENV === 'development') {
return ['debug-border', 'debug-grid']
}
return []
}
]
})
```
## Return Value Types
Safelist functions can return the following types of values:
* `Arrayable
` - String or string array
```ts
safelist: [
// Return string array
() => ['class1', 'class2', 'class3'],
// Return single string
() => 'single-class',
// Return nested array (will be flattened)
() => [['nested1', 'nested2'], 'normal3']
]
```
## Practical Use Cases
### Dynamically Generated Class Names
When you have dynamically generated class names that might not be detected by static analysis:
```ts
safelist: [
// Dynamic color classes
() => {
const dynamicColors = ['primary', 'secondary', 'accent']
return dynamicColors.flatMap(color => [
`bg-${color}`,
`text-${color}`,
`border-${color}`
])
},
// Dynamic size classes
() => {
return Array.from({ length: 12 }, (_, i) => `gap-${i + 1}`)
}
]
```
### Third-party Component Library Support
Provide necessary class names for third-party component libraries:
```ts
safelist: [
// Reserved class names for component library
'prose',
'prose-sm',
'prose-lg',
// Dynamically generate component variants
() => {
const variants = ['primary', 'secondary', 'danger', 'success']
const sizes = ['sm', 'md', 'lg']
return variants.flatMap(variant =>
sizes.map(size => `btn-${variant}-${size}`)
)
}
]
```
## Relationship with Other Configurations
### Difference from blocklist
* **safelist**: Ensures specified class names are always included
* **blocklist**: Ensures specified class names are always excluded
```ts
export default defineConfig({
safelist: ['always-include'],
blocklist: ['never-include']
})
```
### Relationship with Generation Options
When generating CSS, you can control whether to include safelist through `GenerateOptions`:
```ts
const { css } = await uno.generate('', {
safelist: true // Include class names from safelist
})
```
---
---
url: https://unocss.dev/config/layers.md
description: UnoCSS allows you to define the layers as you want.
---
# Layers
The order of CSS will affect their priorities. While the engine will [retain the order of rules](/config/rules#ordering), sometimes you may want to group some utilities to have explicit control of their order.
## Usage
Unlike Tailwind CSS which offers three fixed layers (`base`, `components`, `utilities`), UnoCSS allows you to define the layers as you want. To set the layer, you can pass the metadata as the third item of your rules:
```ts
rules: [
[/^m-(\d)$/, ([, d]) => ({ margin: `${d / 4}rem` }), { layer: 'utilities' }],
// when you omit the layer, it will be `default`
['btn', { padding: '4px' }],
]
```
This will generate:
```css
/* layer: default */
.btn { padding: 4px; }
/* layer: utilities */
.m-2 { margin: 0.5rem; }
```
Layer also can be set on each preflight:
```ts
preflights: [
{
layer: 'my-layer',
getCSS: async () => (await fetch('my-style.css')).text(),
},
]
```
## Ordering
You can control the order of layers by:
```ts
layers: {
'components': -1,
'default': 1,
'utilities': 2,
'my-layer': 3,
}
```
Layers without specified order will be sorted alphabetically.
When you want to have your custom CSS between layers, you can update your entry module:
```ts
// 'uno:[layer-name].css'
import 'uno:components.css'
// layers that are not 'components' and 'utilities' will fallback to here
import 'uno.css'
// your own CSS
import './my-custom.css'
// "utilities" layer will have the highest priority
import 'uno:utilities.css'
```
## CSS Cascade Layers
You can output CSS Cascade Layers by:
```ts
outputToCssLayers: true
```
You can change the CSS Layer names with:
```ts
outputToCssLayers: {
cssLayerName: (layer) => {
// The default layer will be output to the "utilities" CSS layer.
if (layer === 'default')
return 'utilities'
// The shortcuts layer will be output to the "shortcuts" sublayer the of "utilities" CSS layer.
if (layer === 'shortcuts')
return 'utilities.shortcuts'
// All other layers will just use their name as the CSS layer name.
}
}
```
## Output All CSS Layers
UnoCSS outputs all used CSS layers by default. If you want to force output all defined CSS layers, you can set the `allLayers` option:
```ts
outputToCssLayers: {
allLayers: true,
}
```
It will output all defined CSS layers, even if they are not used.
```css
@layer theme, preflights, unused-layer, default;
/* generated CSS */
```
## Layers using variants
Layers can be created using variants.
`uno-layer-:` can be used to create a UnoCSS layer.
```html
text
```
```css
/* layer: my-layer */
.uno-layer-my-layer\:text-xl{ font-size:1.25rem; line-height:1.75rem; }
```
`layer-:` can be used to create a CSS @layer.
```html
text
```
```css
/* layer: default */
@layer my-layer{ .layer-my-layer\:text-xl{ font-size:1.25rem; line-height:1.75rem; } }
```
---
---
url: https://unocss.dev/config/presets.md
---
# Presets
Presets are partial configurations that will be merged into the main configuration.
When authoring a preset, we usually export a constructor function that you could ask for some preset-specific options. For example:
```ts [my-preset.ts]
import { definePreset, Preset } from 'unocss'
export default definePreset((options?: MyPresetOptions) => {
return {
name: 'my-preset',
rules: [
// ...
],
variants: [
// ...
],
// it supports most of the configuration you could have in the root config
}
})
```
Then the user can use it like this:
```ts [uno.config.ts]
import { defineConfig } from 'unocss'
import myPreset from './my-preset'
export default defineConfig({
presets: [
myPreset({ /* preset options */ }),
],
})
```
You can check [official presets](/presets/) and [community presets](/presets/community) for more examples.
---
---
url: https://unocss.dev/config/transformers.md
---
# Transformers
Provides a unified interface to transform source code in order to support conventions.
```ts [my-transformer.ts]
import { SourceCodeTransformer } from 'unocss'
import { createFilter } from 'unplugin-utils'
export default function myTransformers(options: MyOptions = {}): SourceCodeTransformer {
return {
name: 'my-transformer',
enforce: 'pre', // enforce before other transformers
idFilter(id) {
// only transform .tsx and .jsx files
return id.match(/\.[tj]sx$/)
},
async transform(code, id, { uno }) {
// code is a MagicString instance
code.appendRight(0, '/* my transformer */')
},
}
}
```
You can check [official transformers](/presets/#transformers) for more examples.
---
---
url: https://unocss.dev/config/processors.md
---
# Processors
Processors are hooks that transform generated CSS. Unlike [transformers](/config/transformers), which modify source code before extraction, processors run after UnoCSS has generated its CSS layers.
## Define a processor
A processor receives the CSS for one layer and returns the CSS that should replace it. Both synchronous and asynchronous results are supported.
```ts [uno.config.ts]
import type { CSSProcessor } from '@unocss/core'
import { defineConfig } from 'unocss'
const banner: CSSProcessor = {
name: 'add-banner',
order: 10,
process(css, { layer, envMode }) {
if (envMode !== 'build')
return css
return `/* generated layer: ${layer} */\n${css}`
},
}
export default defineConfig({
processors: [banner],
})
```
## Processing flow
For every non-empty CSS layer, UnoCSS performs these steps:
1. Generate the raw layer CSS, including preflights and any enabled CSS layer wrapper or layer marker.
2. Sort processors by `order` in ascending order.
3. Pass the layer through each processor sequentially. The output of one processor becomes the input of the next.
4. Cache the processed layer and expose it through `getLayer()`, `getLayers()`, and `css`.
Different layers may be processed concurrently. A processor should avoid relying on mutable state shared between layers.
When `setLayer()` changes a layer, its callback receives the raw, unprocessed CSS. UnoCSS then runs the updated CSS through the complete processor chain again. This prevents processors from being applied repeatedly to their own previous output.
```text
generated layer
-> processor 1
-> processor 2
-> processed layer output
```
If a processor throws an error, generation fails and the error is passed to the caller.
## Context
The second argument passed to `process()` is a `CSSProcessorContext`:
```ts
interface CSSProcessorContext {
layer: string
theme: Theme
envMode: 'dev' | 'build'
}
```
* `layer` is the name of the current generated layer.
* `theme` is the resolved UnoCSS theme.
* `envMode` indicates whether UnoCSS is generating CSS for development or production builds.
## Processor order
Processors with a lower `order` run first. Processors without an explicit order use `0`.
```ts
processors: [
{ name: 'minify', order: 20, process: minify },
{ name: 'prefix', order: 10, process: addPrefixes },
]
```
In this example, `prefix` runs before `minify`.
Processors declared by presets and the user configuration are merged. The processor `name` identifies it when duplicate processors are removed.
## Official processors
* [Lightning CSS processor](/processors/lightningcss)
---
---
url: https://unocss.dev/config/autocomplete.md
---
# Autocomplete
Autocomplete can be customized for UnoCSS's intelligent suggestions in playground and the [VS Code extension](/integrations/vscode).
```ts
autocomplete: {
templates: [
// theme inferring
'bg-$color/',
// short hands
'text-',
// logic OR groups
'(b|border)-(solid|dashed|dotted|double|hidden|none)',
// constants
'w-half',
],
shorthands: {
// equal to `opacity: "(0|10|20|30|40|50|60|70|90|100)"`
'opacity': Array.from({ length: 11 }, (_, i) => i * 10),
'font-size': '(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)',
// override built-in short hands
'num': '(0|1|2|3|4|5|6|7|8|9)',
},
extractors: [
// ...extractors
],
}
```
* `templates` uses a simple DSL to specify the autocomplete suggestions.
* `shorthands` is a map of shorthand names to their templates. If it's a `Array`, it will be a logic OR group.
* `extractors` to pickup possible classes and transform class-name style suggestions to the correct format. For example, you could check how we implement the [attributify autocomplete extractor](https://github.com/unocss/unocss/blob/main/packages-presets/preset-attributify/src/autocomplete.ts)
* For additional help, please refer to [here](/tools/autocomplete).
---
---
url: https://unocss.dev/presets/community.md
---
# Community
We warmly welcome everyone to join and help build the [UnoCSS community](https://github.com/unocss-community). You can use and share UnoCSS-related resources in [Awesome UnoCSS](https://github.com/unocss-community/awesome-unocss).
---
---
url: https://unocss.dev/guide/packages.md
description: 'UnoCSS Packages: available packages and what''s included and enabled in unocss.'
---
# Packages
UnoCSS is a monorepo that contains multiple packages. This page lists all the packages and what's included in `unocss` package:
| Package | Description | Included in `unocss` | Enabled |
| -------------------------------------------------------------------- | ------------------------------------------------- | -------------------- | ------- |
| [@unocss/core](/tools/core) | The core library without preset | ✅ | - |
| [@unocss/cli](/integrations/cli) | Command line interface for UnoCSS | ✅ | - |
| [@unocss/preset-mini](/presets/mini) | The minimal but essential rules and variants | ✅ | ✅ |
| [@unocss/preset-wind3](/presets/wind3) | Tailwind CSS / Windi CSS compact preset | ✅ | ✅ |
| [@unocss/preset-wind4](/presets/wind4) | Tailwind4 CSS compact preset | ✅ | ✅ |
| [@unocss/preset-attributify](/presets/attributify) | Enables Attributify Mode for other rules | ✅ | No |
| [@unocss/preset-tagify](/presets/tagify) | Enables Tagify Mode for other rules | ✅ | No |
| [@unocss/preset-icons](/presets/icons) | Pure CSS Icons solution powered by Iconify | ✅ | No |
| [@unocss/preset-web-fonts](/presets/web-fonts) | Web fonts (Google Fonts, etc.) support | ✅ | No |
| [@unocss/preset-typography](/presets/typography) | The typography preset | ✅ | No |
| [@unocss/preset-rem-to-px](/presets/rem-to-px) | Coverts rem to px for utils | No | No |
| [@unocss/preset-legacy-compat](/presets/legacy-compat) | Collections of legacy compatibility utilities | No | No |
| [@unocss/transformer-variant-group](/transformers/variant-group) | Transformer for Windi CSS's variant group feature | ✅ | No |
| [@unocss/transformer-directives](/transformers/directives) | Transformer for CSS directives like `@apply` | ✅ | No |
| [@unocss/transformer-compile-class](/transformers/compile-class) | Compile group of classes into one class | ✅ | No |
| [@unocss/transformer-attributify-jsx](/transformers/attributify-jsx) | Support valueless attributify in JSX/TSX | ✅ | No |
| [@unocss/extractor-pug](/extractors/pug) | Extractor for Pug | No | - |
| [@unocss/extractor-svelte](/extractors/svelte) | Extractor for Svelte | No | - |
| [@unocss/processor-lightningcss](/processors/lightningcss) | Process generated CSS with Lightning CSS | No | No |
| [@unocss/autocomplete](/tools/autocomplete) | Utils for autocomplete | No | - |
| [@unocss/config](/guide/config-file) | Configuration file loader | ✅ | - |
| [@unocss/reset](/guide/style-reset) | Collection of common CSS resets | ✅ | No |
| [@unocss/vite](/integrations/vite) | The Vite plugins | ✅ | - |
| [@unocss/inspector](/tools/inspector) | The inspector UI for UnoCSS | ✅ | - |
| [@unocss/astro](/integrations/astro) | The Astro integration | ✅ | - |
| [@unocss/webpack](/integrations/webpack) | The Webpack plugin | No | - |
| [@unocss/nuxt](/integrations/nuxt) | The Nuxt Module | No | - |
| [@unocss/svelte-scoped](/integrations/svelte-scoped) | Svelte Scoped Vite plugin + Preprocessor | No | - |
| [@unocss/next](/integrations/next) | The Next.js plugin | No | - |
| [@unocss/runtime](/integrations/runtime) | CSS-in-JS Runtime for UnoCSS | No | - |
| [@unocss/eslint-plugin](/integrations/eslint) | ESLint plugin | No | - |
| [@unocss/eslint-config](/integrations/eslint) | ESLint config | No | - |
| [@unocss/postcss](/integrations/postcss) | The PostCSS plugin | No | - |
| [VS Code Extension](/integrations/vscode) | UnoCSS for VS Code | - | - |