Skip to content

规则

🌐 Rules

规则定义了工具类及其生成的 CSS。UnoCSS 有许多内置规则,同时也允许轻松添加自定义规则。

🌐 Rules define utility classes and the resulting CSS. UnoCSS has many built-in rules but also allows for easily adding custom rules.

静态规则

🌐 Static rules

以此为例:

🌐 With this example:

ts
rules: [
  ['m-1', { margin: '0.25rem' }],
]

每当在用户的代码库中检测到 m-1 时,将生成以下 CSS:

🌐 The following CSS will be generated whenever m-1 is detected in users' codebase:

css
.m-1 {
  margin: 0.25rem;
}

注意:主体语法遵循 CSS 属性语法,例如使用 font-weight 而不是 fontWeight。如果属性名称中有连字符 -,则应使用引号。

ts
rules: [
  ['font-bold', { 'font-weight': 700 }],
]

动态规则

🌐 Dynamic rules

为了让它更智能,将匹配器改为 RegExp,并将主体改为一个函数:

🌐 To make it smarter, change the matcher to a RegExp and the body to a function:

ts
rules: [
  [/^m-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
  // You can get rich context information from the second argument, such as `theme`, `symbols`, etc.
  [/^p-(\d+)$/, (match, ctx) => ({ padding: `${match[1] / 4}rem` })],
]

body 函数的第一个参数是 RegExp 匹配结果,可以对其进行解构以获取匹配的分组。

🌐 The first argument of the body function is the RegExp match result that can be destructured to get the matched groups.

例如,使用以下用法:

🌐 For example, with the following usage:

html
<div class="m-100">
  <button class="m-3">
    <icon class="p-5" />
    My Button
  </button>
</div>

将会生成相应的 CSS:

🌐 the corresponding CSS will be generated:

css
.m-100 { margin: 25rem; }
.m-3 { margin: 0.75rem; }
.p-5 { padding: 1.25rem; }

恭喜!现在你拥有了自己强大的原子 CSS 工具。尽情享用吧!

🌐 Congratulations! Now you've got your own powerful atomic CSS utilities. Enjoy!

CSS 规则回退

🌐 CSS Rules Fallback

在某些情况下,你可能希望利用 CSS 规则回退以使用新的 CSS 功能,同时也能够回退以支持旧浏览器,你可以选择将具有相同键的规则作为 CSS 表示返回一个二维数组。例如:

🌐 In cases you might want to leverage CSS rules fallback to use new CSS features while also able to fallback to support old browsers, you can optionally return a 2D-array as the CSS representation for rules with the same keys. For example:

ts
rules: [
  [/^h-(\d+)dvh$/, ([_, d]) => {
    return [
      ['height', `${d}vh`],
      ['height', `${d}dvh`],
    ]
  }],
]

这将使 h-100dvh 生成:

🌐 Which will make h-100dvh generates:

css
.h-100dvh { height: 100vh; height: 100dvh; }

特殊符号

🌐 Special symbols

自 v0.61 起,UnoCSS 支持使用特殊符号来为生成的 CSS 定义附加的元信息。你可以通过 @unocss/coresymbols 对象或动态规则匹配函数的第二个参数来访问这些符号。

🌐 Since v0.61, UnoCSS supports special symbols to define additional meta information for your generated CSS. You can access the symbols from the symbols object from @unocss/core or the second argument of the dynamic rule matcher function.

例如:

🌐 For example:

ts
import { symbols } from '@unocss/core'

rules: [
  ['grid', {
    [symbols.parent]: '@supports (display: grid)',
    display: 'grid',
  }],
]
ts
rules: [
  [/^grid$/, ([, d], { symbols }) => {
    return {
      [symbols.parent]: '@supports (display: grid)',
      display: 'grid',
    }
  }],
]

将生成:

🌐 Will generate:

css
@supports (display: grid) {
  .grid {
    display: grid;
  }
}

TIP

如果你确切知道规则是如何生成的,我们建议使用静态规则来提升 UnoCSS 的性能。

可用符号

🌐 Available symbols

SymbolsDescription
symbols.parentThe parent wrapper of the generated CSS rule (e.g., @supports, @media, etc.)
symbols.selectorA function to modify the selector of the generated CSS rule (see example below)
symbols.layerSets the UnoCSS layer of the generated CSS rule (can be string, function, or regex match)
symbols.variantsAn array of variant handlers applied to the current CSS object
symbols.shortcutsNoMergeBoolean to disable merging of the current rule in shortcuts
symbols.noMergeBoolean to disable merging of the current rule
symbols.sortNumber to overwrite sorting order of the current CSS object
symbols.bodyFully control the body of the generated CSS rule (see #4889)

多选择器规则

🌐 Multi-selector rules

自 v0.61 起,UnoCSS 通过 JavaScript 生成器函数 支持多选择器。并且可以从一条规则生成多条 CSS 规则。

🌐 Since v0.61, UnoCSS supports multi-selector via JavaScript Generator functions. And generates multiple CSS rules from a single rule.

例如:

🌐 For example:

ts
rules: [
  ['button-red', [
    { background: 'red' },
    {
      [symbols.selector]: selector => `${selector}:hover`,
      // https://web.nodejs.cn/en-US/docs/Web/CSS/color_value/color-mix
      background: `color-mix(in srgb, red 90%, black)`
    },
  ]],
]
ts
rules: [
  [/^button-(.*)$/, function* ([, color], { symbols }) {
    yield {
      background: color
    }
    yield {
      [symbols.selector]: selector => `${selector}:hover`,
      // https://web.nodejs.cn/en-US/docs/Web/CSS/color_value/color-mix
      background: `color-mix(in srgb, ${color} 90%, black)`
    }
  }],
]

将生成多个 CSS 规则:

🌐 Will generate multiple CSS rules:

css
.button-red {
  background: red;
}
.button-red:hover {
  background: color-mix(in srgb, red 90%, black);
}

完全受控的规则

🌐 Fully controlled rules

TIP

这是一项高级功能,在大多数情况下不需要它。

当你真的需要一些不被 Dynamic RulesVariants 组合所涵盖的高级规则时,UnoCSS 也提供了一种方法,让你可以完全控制 CSS 的生成。

🌐 When you really need some advanced rules that aren't covered by the combination of Dynamic Rules and Variants, UnoCSS also provides a way to give you full control to generate the CSS.

它允许你从动态规则的主体函数返回一个字符串,该字符串将直接传递给生成的 CSS(这也意味着你需要自己处理诸如 CSS 转义、变体应用、CSS 构建等问题)。

🌐 It allows you to return a string from the dynamic rule's body function which will be directly passed to the generated CSS (this also means you need to take care of things like CSS escaping, variant applying, CSS constructing, and so on).

uno.config.ts
ts
import { defineConfig, toEscapedSelector as e } from 'unocss'

export default defineConfig({
  rules: [
    [/^custom-(.+)$/, ([, name], { rawSelector, currentSelector, variantHandlers, theme }) => {
      // discard mismatched rules
      if (name.includes('something'))
        return

      // if you want, you can disable the variants for this rule
      if (variantHandlers.length)
        return
      const selector = e(rawSelector)
      // return a string instead of an object
      return `
${selector} {
  font-size: ${theme.fontSize.sm};
}
/* you can have multiple rules */
${selector}::after {
  content: 'after';
}
.foo > ${selector} {
  color: red;
}
/* or media queries */
@media (min-width: ${theme.breakpoints.sm}) {
  ${selector} {
    font-size: ${theme.fontSize.sm};
  }
}
`
    }],
  ],
})

WARNING

上述方法可以完全控制生成的 CSS,但无法通过 variants 扩展,从而失去了其变体带来的灵活性。

例如 hover:custom-xxx -> hover 变体不起作用。

🌐 e.g. hover:custom-xxx -> The hover variant won't work.

所以,如果你想在享受变体便利的同时完全自定义输出,你可以考虑使用 symbols.body 来实现这一点。

🌐 So if you want to fully customize the output while still enjoying the convenience of variants, you can consider using symbols.body to achieve this.

ts
import { symbols } from '@unocss/core'

rules: [
  ['custom-red', {
    // symbols.body doesn't need `{}` wrapping the styles
    [symbols.body]: `
      font-size: 1rem;
      &::after {
        content: 'after';
      }
      & > .bar {
        color: red;
      }
    `,
    [symbols.selector]: selector => `:is(${selector})`,
  }]
]
ts
rules: [
  [/^custom-(.+)$/, ([_, c], { symbols }) => {
    return {
      [symbols.body]: `
        font-size: 1rem;
        &::after {
          content: 'after';
        }
        & > .bar {
          color: ${c};
        }
      `,
      [symbols.selector]: selector => `:is(${selector})`,
    }
  }]
]

将从 hover:custom-red 生成完整的 CSS 规则:

🌐 Will generate fully CSS rules from hover:custom-red:

css
:is(.hover\:custom-red):hover {
  font-size: 1rem;
  &::after {
    content: 'after';
  }
  & > .bar {
    color: red;
  }
}

排序

🌐 Ordering

UnoCSS 会尊重你在生成的 CSS 中定义规则的顺序。后定义的规则优先级更高。

🌐 UnoCSS respects the order of the rules you defined in the generated CSS. Latter ones come with higher priority.

在使用动态规则时,它可能会匹配多个标记。默认情况下,单个动态规则下匹配的输出将在组内按字母顺序排序。

🌐 When using dynamic rules, it may match multiple tokens. By default, the output of those matched under a single dynamic rule will be sorted alphabetically within the group.

规则合并

🌐 Rules merging

默认情况下,UnoCSS 会将 CSS 规则与同一正文合并,以最小化 CSS 大小。

🌐 By default, UnoCSS will merge CSS rules with the same body to minimize the CSS size.

例如,<div class="m-2 hover:m2"> 将生成:

🌐 For example, <div class="m-2 hover:m2"> 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;
}