tailwind ( uni ) === 自定义主题

目录

什么是主题变量?

[为什么是 @theme 而不是 :root](#为什么是 @theme 而不是 :root)

与工具类的关系

主题变量命名空间

默认主题变量

自定义主题

扩展默认主题

引用其他变量

问题示例

[使用 @theme inline](#使用 @theme inline)

实战应用

定义主题样式

设置attr

进行初始化

页面使用


Tailwind 是一个用于构建自定义设计的框架,不同的设计需要不同的排版、颜色、阴影、断点等。

这些底层设计决策通常称为设计令牌,在 Tailwind 项目中,你将这些值存储在主题变量中。

什么是主题变量?

主题变量是使用**@theme**指令定义的特殊 CSS 变量,会影响项目中存在哪些工具类。

例如,你可以通过定义主题变量(如 --color-mint-500)为你的项目添加新颜色:

复制代码
@import "tailwindcss";
@theme {
  --color-mint-500: oklch(0.72 0.11 178);
}

现在你可以在 HTML 中使用工具类,如 bg-mint-500text-mint-500fill-mint-500

复制代码
<div class="bg-mint-500">
  <!-- ... -->
</div>

Tailwind 还会为你的主题变量生成常规 CSS 变量,以便你可以在任意值或内联样式中引用你的设计令牌:

复制代码
<div style="background-color: var(--color-mint-500)">
  <!-- ... -->
</div>

为什么是 @theme 而不是 :root

主题变量不仅仅是 CSS 变量 - 它们还指示 Tailwind 创建可在 HTML 中使用的新工具类。

由于它们比常规 CSS 变量功能更多,Tailwind 使用特殊语法,因此定义主题变量始终是明确的。主题变量也需要在顶层定义,而不是嵌套在其他选择器或媒体查询下,使用特殊语法可以强制执行这一点。

当你想要定义一个不打算连接到工具类的变量时,使用 :root 定义常规 CSS 变量在 Tailwind 项目中仍然很有用。当你希望设计令牌直接映射到工具类时使用 @theme,并使用 :root 定义不应具有相应工具类的常规 CSS 变量。

与工具类的关系

Tailwind 中的一些工具类(如 flexobject-cover)是静态的,并且在各个项目之间始终相同。但许多其他效果是由主题变量驱动的,并且仅因你定义的主题变量而存在。

例如,--font-* 命名空间中定义的主题变量确定项目中存在的所有 font-family 工具:

复制代码
@theme {
  --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  /* ... */
}

font-sansfont-seriffont-mono 工具仅在默认情况下存在,因为 Tailwind 的默认主题定义了 --font-sans--font-serif--font-mono 主题变量。

如果定义了另一个主题变量(如 --font-poppins),则可以使用 font-poppins 工具类来配合使用:

复制代码
@import "tailwindcss";
@theme {
  --font-poppins: Poppins, sans-serif;
}

<h1 class="font-poppins">This headline will use Poppins.</h1>

你可以在这些命名空间中随意命名主题变量,并且具有相同名称的相应工具将可用于你的 HTML。

主题变量命名空间

主题变量在命名空间中定义,每个命名空间对应一个或多个工具类或变体 API。

在这些命名空间中定义新的主题变量将使新的相应工具和变体在你的项目中可用:

Namespace Utility classes
--color-* Color utilities like bg-red-500, text-sky-300, and many more
--font-* Font family utilities like font-sans
--text-* Font size utilities like text-xl
--font-weight-* Font weight utilities like font-bold
--tracking-* Letter spacing utilities like tracking-wide
--leading-* Line height utilities like leading-tight
--breakpoint-* Responsive breakpoint variants like sm:*
--container-* Container query variants like @sm:* and size utilities like max-w-md
--spacing-* Spacing and sizing utilities like px-4, max-h-16, and many more
--radius-* Border radius utilities like rounded-sm
--shadow-* Box shadow utilities like shadow-md
--inset-shadow-* Inset box shadow utilities like inset-shadow-xs
--drop-shadow-* Drop shadow filter utilities like drop-shadow-md
--blur-* Blur filter utilities like blur-md
--perspective-* Perspective utilities like perspective-near
--aspect-* Aspect ratio utilities like aspect-video
--ease-* Transition timing function utilities like ease-out
--animate-* Animation utilities like animate-spin

默认主题变量

当你在 CSS 文件顶部导入 tailwindcss 时,它包含一组默认主题变量来帮助你入门。

以下是导入 tailwindcss 时实际导入的内容:

复制代码
@layer theme, base, components, utilities;
@import "./theme.css" layer(theme);
@import "./preflight.css" layer(base);
@import "./utilities.css" layer(utilities);

theme.css 文件包含默认调色板、类型比例、阴影、字体等:

'

复制代码
@theme {
  --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  --color-red-50: oklch(0.971 0.013 17.38);
  --color-red-100: oklch(0.936 0.032 17.717);
  --color-red-200: oklch(0.885 0.062 18.334);
  /* ... */
  --shadow-2xs: 0 1px rgb(0 0 0 / 0.05);
  --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  /* ... */
}

这就是为什么像 bg-red-200font-serifshadow-sm 这样的工具开箱即用的原因 - 它们由默认主题驱动,而不是像 flex-colpointer-events-none 那样硬编码到框架中。

自定义主题

扩展默认主题

使用 @theme 定义新主题变量并扩展默认主题:

复制代码
@import "tailwindcss";
@theme {
  --font-script: Great Vibes, cursive;
}

这使得你可以在 HTML 中使用新的 font-script 工具类,就像默认的 font-sansfont-mono 工具一样:

复制代码
<p class="font-script">This will use the Great Vibes font family.</p>

引用其他变量

定义引用其他变量的主题变量时,请使用 inline 选项

复制代码
@import "tailwindcss";
@theme inline {
  --font-sans: var(--font-inter);
}

使用 inline 选项,工具类将使用主题变量值而不是引用实际主题变量:

复制代码
.font-sans {
  font-family: var(--font-inter);
}

问题示例

如果不使用 inline,你的工具类可能会解析为意外值,因为变量在 CSS 中的解析方式不同。、

CSS 变量(custom properties)有"在哪定义就在哪解析"的特点。

这意味着如果你定义了 --a: var(--b),那么浏览器在解析 --a 的时候,会立刻 尝试去读取 --b 的值,而不会等到后面才解析。

例如,此文本将回退到 sans-serif,而不是像你预期的那样使用 Inter

复制代码
<div id="parent" style="--font-sans: var(--font-inter, sans-serif);">
  <div id="child" style="--font-inter: Inter; font-family: var(--font-sans);">
    This text will use sans-serif, not Inter.
  </div>
</div>

发生这种情况的原因是 var(--font-sans) 在定义 --font-sans 的地方(在 #parent 上)得到解析,而 --font-inter 在那里没有值,因为它直到树的更深层(在 #child 上)才被定义。

  • #parent 上定义了 --font-sans:它等于 var(--font-inter, sans-serif)

  • 这时浏览器会立即解析 --font-inter 的值

  • --font-inter 是在 #child 中才定义的

  • 所以在 #parent--font-inter未定义

  • 因此 var(--font-inter, sans-serif) 只好使用后备值 sans-serif

🚨 CSS变量解析的是当前作用域已有的变量,不会往子元素查找!

使用 @theme inline

Tailwind 提供了 @theme inline 这个语法糖来帮助你避免这种问题

例如:

复制代码
@theme inline {
  --font-sans: var(--font-inter);
}

这个语法的效果是:让 Tailwind 把这个变量的值原封不动地写进最终的工具类中,而不是先计算它

编译结果如下:

复制代码
.font-sans {
  font-family: var(--font-inter);
}

这样,当 Tailwind 构建 .font-sans 工具类时,它不会试图提前计算 --font-inter,而是保留变量引用,交由运行时(浏览器)去解析。

实战应用

虽然 Tailwind 旨在满足你的大部分样式需求,但没有什么可以阻止你在需要时只编写纯 CSS:

复制代码
@theme inline {
  --font-sans: var(--font-inter);
}

这个语法的效果是:让 Tailwind 把这个变量的值原封不动地写进最终的工具类中,而不是先计算它

编译结果如下:

复制代码
.font-sans {
  font-family: var(--font-inter);
}

这样,当 Tailwind 构建 .font-sans 工具类时,它不会试图提前计算 --font-inter,而是保留变量引用,交由运行时(浏览器)去解析。

定义主题样式

复制代码
/* 主题样式 */
@theme inline {
  --color-bg: var(--color-bg);
  --color-text: var(--color-tx);
}
/* 微信小程序 */
[data-theme='wx'] {
  --color-bg: #07aa5c;
  --color-tx: #ffffff;
}

/* app */
[data-theme='app'] {
  --color-bg: #1a1a1a;
  --color-tx: #f5f5f5;
}

设置attr

复制代码
export const updateRootAttribute = (value) => {
  let mode = value || uni.getStorageSync('theme') || 'light'
  const isH5 = process.env.UNI_PLATFORM === 'h5'
  if (isH5) {
    document.documentElement.setAttribute('data-theme', mode)
    uni.setStorageSync('theme', mode)
  }
}

进行初始化

复制代码
  onShow: function () {
    var json = initUrlStr() || {}
    this.globalData = json
    console.log(json, this.globalData, 'json,页面初始化')
    updateRootAttribute(this.globalData.theme || 'wx')
  },

页面使用

bg-bg :背景颜色

text-text: 字体颜色

复制代码
    <view
      class="w-[700rpx] h-[94rpx] bg-bg m-auto mt-[50rpx] text-text leading-[94rpx] rounded-[48rpx] text-[32rpx]"
      @click="submit"
    >
      同意授权
    </view>
相关推荐
弗锐土豆4 分钟前
一个基于若依(ruoyi-vue3)的小项目部署记录
前端·vue.js·部署·springcloud·ruoyi·若依
Hilaku7 分钟前
我为什么放弃了“大厂梦”,去了一家“小公司”?
前端·javascript·面试
1undefined29 分钟前
element中的table改造成虚拟列表(不定高),并封装成hooks
前端·vue.js
浅墨momo13 分钟前
搭建第一个Shopify App
前端·程序员
然我17 分钟前
React 事件机制:从代码到原理,彻底搞懂合成事件的核心逻辑
前端·react.js·面试
Codebee17 分钟前
OneCode 组件服务通用协议栈:构建企业级低代码平台的技术基石
前端·前端框架·开源
Running_C17 分钟前
常见web攻击类型
前端·http
jackyChan17 分钟前
ES6 Proxy 性能问题,你真知道吗?🚨
前端·javascript
lichenyang45317 分钟前
快速搭建服务器,fetch请求从服务器获取数据
前端