十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Yeti Tokens 完全指南:掌握 `--yeti-*` 公开令牌,零构建地定制整个设计系统

Yeti Tokens 完全指南:掌握 `--yeti-*` 公开令牌,零构建地定制整个设计系统 Yeti Tokens 完全指南掌握--yeti-*公开令牌零构建地定制整个设计系统【免费下载链接】yetiA CSS-first, native, zero-build layout and styling framework for web designers.项目地址: https://gitcode.com/gh_mirrors/fo/yetiYeti 是一个 CSS-first、零构建的布局与样式框架它的主题化 API完全由一组名为--yeti-group-name的公开 CSS 自定义属性tokens构成。本文以 docs/tokens.md 为骨架逐组拆解全部公开令牌的默认值、语义与底层实现并给出可直接套用的覆盖示例读完后你将能够不修改任何组件 CSS仅凭在:root上设置几行令牌就完成字体比例、色彩体系、圆角、阴影与组件皮肤的全面定制。公开令牌Yeti 的主题化 APIYeti 的主题机制非常纯粹设置令牌而不是编辑 CSS。每一个公开令牌都是一个自定义属性命名规则为--yeti-group-name例如--yeti-space-md属于 space 组、--yeti-color-primary属于 color 组。完整清单由 bin/gen-docs.js 从 src/tokens/tokens.json 自动生成到 docs/tokens.md因此文档中的每个条目都与源码一一对应。尺寸命名统一采用xs sm md lg xl 2xl 3xl七级阶梯其中md是基准步长step 0。这个命名约定贯穿所有使用尺寸的组--yeti-space-lg、--yeti-text-lg、--yeti-radius-lg中的lg都是指同一步长含义始终一致。/* 在任何元素上覆盖公开令牌所有读取它的组件都会随之变化 */ :root { --yeti-hue-primary: 160; --yeti-ratio: 1.25; --yeti-font-sans: Inter, system-ui, sans-serif; }覆盖规则很简单在你的样式表中、在 Yeti 的 CSS 之后加载这段声明即可因为同样的自定义属性后声明者胜出。公开与内部的边界Yeti 内部还定义了 48 个--_yeti-*令牌下划线前缀例如--_yeti-step-0、--_yeti-t。它们从公开令牌推导而来可能在 minor 版本之间变化请始终覆盖公开令牌而非内部令牌。Scale 组一条流体比例尺驱动全部尺寸Scale 组是整个系统的心脏。它的核心思想是所有尺寸字号、间距、圆角都是同一条几何比例尺上的一个步长。Token默认值说明--yeti-baseunset仅覆盖用将 body 字号在所有视口下固定为一个值设置后同时覆盖--yeti-base-min与--yeti-base-max--yeti-ratiounset仅覆盖用将比例尺比率在所有视口下固定为一个值设置后同时覆盖--yeti-ratio-min与--yeti-ratio-max--yeti-base-min1rem窄视口下的正文文字大小--yeti-base-max1.125rem宽视口下的正文文字大小--yeti-ratio-min1.2窄视口下的比例尺比率小三度--yeti-ratio-max1.333宽视口下的比例尺比率纯四度--yeti-viewport-min320px窄端数值生效的视口宽度--yeti-viewport-max1280px宽端数值生效的视口宽度默认情况下 base 与 ratio 都是**流体fluid**的base 从--yeti-viewport-min320px处的--yeti-base-min平滑增长到--yeti-viewport-max1280px处的--yeti-base-maxratio 同理。这意味着宽屏下标题会比正文打开得更开。而--yeti-base/--yeti-ratio这两个总开关可以把对应的一对值钉死在单值上彻底关闭流动性。底层实现插值、除法与幂打开 src/tokens/scale.css 可以看到这条比例尺的真实实现。它先用一个内部变量--_yeti-t表示插值进度0 表示处于窄视口1 表示处于宽视口--_yeti-t: clamp(0, tan(atan2(100vw - var(--yeti-viewport-min), var(--yeti-viewport-max) - var(--yeti-viewport-min))), 1); --_yeti-base: calc(var(--yeti-base-min) (var(--yeti-base-max) - var(--yeti-base-min)) * var(--_yeti-t)); --_yeti-ratio: calc(var(--yeti-ratio-min) (var(--yeti-ratio-max) - var(--yeti-ratio-min)) * var(--_yeti-t));源码注释解释了tan(atan2(a, b))这个看似绕弯的技巧它等价于a / b的纯数值除法是 Baseline 2025 兼容级别上在calc()里对两个长度做除法的唯一方式。之后每个步长按几何级数递推--_yeti-step-0: var(--_yeti-base); --_yeti-step-1: calc(var(--_yeti-base) * var(--_yeti-ratio)); --_yeti-step-2: calc(var(--_yeti-base) * pow(var(--_yeti-ratio), 2)); /* ...直到 step 5供 display 字号使用 */同时还有-static取窄视口值不参与流体与-max宽视口端值供流体内间距成对插值两套内部派生值。空间、文字、圆角三组全部读取这些 step 变量这就是改一个 base 全身跟着变的原理。Space 组与字号成正比的内距体系Space 组直接映射比例尺步长因此间距天然与字体大小成比例——页面放大字号间距同步放大视觉节奏始终一致。Token默认值说明--yeti-space-none0无间距data-gapnone背后的值--yeti-space-xsstep -2发丝级间隙--yeti-space-smstep -1紧凑间隙--yeti-space-mdstep 0默认间隙等于正文文字大小--yeti-space-lgstep 1舒适间隙--yeti-space-xlstep 2区块级间隙--yeti-space-2xlstep 3页面级间隙--yeti-space-3xlstep 4Hero 级间隙--yeti-space-{xs…3xl}-static对应步长的窄视口值非流体版本用于绝不能缩放的特殊间隙-static系列值得一提它是每个步长的窄视口取值见 src/tokens/space.css 中var(--_yeti-step--2-static)等引用。当页面放大时普通 space 令牌会跟着放大而-static保持钉死适合分隔线、图标间距这类必须恒定的场景。:root { --yeti-space-md: 1.25rem; /* 把默认间隙改大 */ --yeti-space-2xl-static: 4rem; /* 钉死一个非流体大间距 */ }Radius 组相对 base 的圆角比例Radius 也与比例尺挂钩但用的是base 的倍数而非独立步长Token默认值说明--yeti-radius-sm0.25 × base小圆角输入框、代码、徽章--yeti-radius-md0.5 × base中圆角卡片、对话框--yeti-radius-lg1 × base大圆角hero 面板--yeti-radius-full9999px胶囊或圆形源码中的定义验证了这一点calc(0.25 * var(--_yeti-base))、calc(0.5 * var(--_yeti-base))、var(--_yeti-base)。由于都基于流体 base圆角在窄屏到宽屏间也会轻微变化与整体比例保持一致。把--yeti-radius-md改成1rem就能立刻让卡片变圆这也是内置主题 soft 的做法见下文。Width 组面向内容的容器度量Width 组是唯一一组不读比例尺的尺寸它们以rem为单位跟随访问者的根字号因为容器阈值关乎内容容纳量而非排版比例。Token默认值说明--yeti-width-xs16rem最小容器度量grid 的默认最小列宽--yeti-width-sm24remsidebar 的默认宽度--yeti-width-md32remcolumns 布局的默认阈值--yeti-width-lg48rem窄页面列--yeti-width-xl64remcenter 布局的默认最大宽度--yeti-width-2xl80rem宽页面列src/tokens/space.css 的头部注释明确写道Widths are container measures in rem: they follow the visitors root size, not the scale, because a threshold is about content, not type. 调整这些值会直接影响 grid、sidebar、columns、center 等布局组件的行为阈值。Text 组字号、行高与行长Text 组的字号与 Space 组共用同一套步长——md即正文字号Token默认值说明--yeti-text-xsstep -2说明文字与小字--yeti-text-smstep -1小号文字h6--yeti-text-mdstep 0正文加粗时即 h5--yeti-text-lgstep 1引导段h4--yeti-text-xlstep 2h3--yeti-text-2xlstep 3h2--yeti-text-3xlstep 4h1--yeti-text-displaystep 5Display 级字体大于任何标题--yeti-leading-md1em 0.5 × base正文行高body 字号下约为 1.5随字号增大而收紧--yeti-leading-tight1.15标题行高--yeti-measure65ch散文的最大行长--yeti-leading-md的实现值得注意见 src/tokens/type.csscalc(1em 0.5 * var(--_yeti-base))——一倍的 em 加上半个 base。由于追加的是固定半个 base字号越大行高倍数越紧凑这比固定倍数更符合排版直觉。Font 组不捆绑字体的字体栈Yeti不内置任何 Web 字体只提供两个系统字体栈Token默认值说明--yeti-font-sanssystem-ui, sans-serif默认文本字体覆盖它来使用你自己的字体--yeti-font-monoui-monospace, monospace代码字体:root { --yeti-font-sans: Inter, system-ui, sans-serif; --yeti-font-mono: JetBrains Mono, ui-monospace, monospace; }字体文件的加载方式完全由你决定font-face、link或任何方案Yeti 只负责消费这两个令牌。Hue 组oklch 色相输入一个色度Hue 组是 Yeti 色彩体系的输入端。它只接受色相角度oklch 度数与一个全局色度所有颜色角色都由它们实时推导见 src/tokens/color.cssToken默认值说明--yeti-hue-primary250品牌色相oklch 度数250 是蓝色。所有主色都由此派生--yeti-hue-secondary300次要色相300 是紫色--yeti-hue-success145成功色相145 是绿色--yeti-hue-warning80警告色相80 是琥珀色--yeti-hue-alert25告警色相25 是红色--yeti-hue-neutralvar(--yeti-hue-primary)微弱染色表面、文字与边框的色相默认跟随主色相--yeti-chroma0.15强调色饱和度。调低可获得更平静的调色板0.2 及以上在非常饱和的色相上可能被裁剪在源码中这 7 个输入都通过property注册为number语法并给出初始值——这样一旦有人把色相错写成颜色名会回退到初始值而不是让所有派生颜色集体失效。色相与颜色的区别--yeti-hue-*是你设置的东西--yeti-color-*是 Yeti 从色相推导出来的结果浅色与深色双份。正因如此它们分属不同组。色相、色度与比例尺输入只在:root上生效Yeti 在那里完成所有推导而强制颜色方案、覆盖派生颜色则可以作用于任意元素——想让某个区块换一种强调色就在那个区块上覆盖派生色而不是改色相。:root { --yeti-hue-primary: 160; } /* 全局品牌色整体变绿 */ .card--accent { --yeti-color-primary: #0a7; } /* 局部仅此区块覆盖派生色 */Color 组从色相推导的完整角色系统Color 组是色彩推导的输出端每个语义角色都有一套完整的色阶。以 primary 为例同一色相衍生出 5 级 1 个对比文字色Token默认值说明--yeti-color-primary主色相的 ladder base品牌色按钮、链接、焦点--yeti-color-primary-subtleladder subtle染色背景表面悬停、选中--yeti-color-primary-softladder soft主色相下的边框与分隔线--yeti-color-primary-strongladder strong主色的悬停与激活态--yeti-color-primary-textladder text普通表面上主色相的文字--yeti-on-primary浅色模式近白深色模式近黑放在--yeti-color-primary上的文字secondary、success、warning、alert 四组角色完全同构base/subtle/soft/strong/text --yeti-on-*neutral 角色用于data-variantneutral的按钮与徽章。除此之外还有页面级角色Token默认值浅色/深色说明--yeti-color-surfaceL 0.99 / 0.13页面背景--yeti-color-surface-raisedL 0.97 / 0.17卡片、代码块等浮于页面之上的元素--yeti-color-surface-sunkenL 0.94 / 0.10凹陷容器与内嵌区域--yeti-color-textL 0.15 / 0.93正文文字--yeti-color-text-mutedL 0.45 / 0.70次要文字说明、帮助、元数据--yeti-color-borderL 0.88 / 0.30默认边框与分隔线--yeti-color-border-strongL 0.75 / 0.40强调边框聚焦输入框、引用块--yeti-color-focusvar(--yeti-color-primary)焦点环颜色底层实现固定亮度阶梯 light-dark()src/tokens/color.css 揭示了推导机制每个角色沿一条固定的亮度阶梯浅色/深色各一套取亮度值与输入色相、色度组合成 oklch 颜色/* 亮度阶梯subtle 0.95/0.25, soft 0.85/0.35, base 0.52/0.70, strong 0.42/0.80, text 0.35/0.85 */ --yeti-color-primary: light-dark( oklch(var(--_yeti-l-base-light) var(--yeti-chroma) var(--yeti-hue-primary)), oklch(var(--_yeti-l-base-dark) var(--yeti-chroma) var(--yeti-hue-primary)) );每个角色只用light-dark()声明一次浅色与深色互为镜像。:root上声明了color-scheme: light dark因此默认跟随访问者偏好在任意祖先上设置color-scheme: light即可强制切换其下所有内容。中性色使用极低色度0.02页面角色surface/text/border同样取自中性色相所以改动--yeti-hue-neutral会整体改变页面的冷暖基调。每种色相的 hex 等效值以注释形式标注在 src/tokens/color.css 中方便与已知的十六进制色值对照。Motion 组一次媒体查询、全局动画偏好Token默认值说明--yeti-duration-fast150ms快速过渡悬停与聚焦。prefers-reduced-motion下坍缩为 0.01ms--yeti-duration-base250ms标准过渡开合。prefers-reduced-motion下坍缩--yeti-easecubic-bezier(0.2, 0, 0, 1)默认缓动快出、缓入src/tokens/motion.css 展示了一个巧妙的做法所有组件都过渡到这两个 duration 令牌上因此在同一个media (prefers-reduced-motion: reduce)块里把它们改成0.01ms全站的减少动态效果偏好一次生效。组件皮肤组Button、Badge、Card、Field、Table、Seam组件级令牌是各组件的皮肤表面见 src/tokens/components.css默认值全部引用全局令牌因此主题只需改一行即可改变组件形态。Layout 与全局杂项Token默认值说明--yeti-cover-height100dvhcover 布局或充满式 stack 的最小块尺寸设为auto则仅与内容等高--yeti-border-width1px组件绘制的所有边框宽度--yeti-weight-normal400正文字重--yeti-weight-strong600标签、标题、按钮字重Shadow 组见 src/tokens/surface.cssToken默认值说明--yeti-shadow-color浅色下黑 14%深色下黑 55%所有阴影的绘制颜色主题改偏移量时不会丢失明暗切换--yeti-shadow-sm0 1px 2px上述颜色浮起的卡片--yeti-shadow-md0 4px 12px同色悬浮表面菜单与对话框Control 组Token默认值说明--yeti-control-size2.5remdata-sizemd时按钮或输入框的最小块尺寸--yeti-control-radiusvar(--yeti-radius-sm)输入框圆角--yeti-control-bordervar(--yeti-color-border)输入框静止时边框--yeti-control-surfacevar(--yeti-color-surface)输入框背景--yeti-control-chevron中灰 chevron内联 SVG data URLselect 的 chevron 图像主题可自行提供例如为深色控件提供更亮的版本--yeti-opacity-muted0.6禁用或忙碌控件的不透明度Button / Badge / Card / Field / Table / Seam 组Token默认值说明--yeti-button-radiusvar(--yeti-radius-md)按钮圆角--yeti-button-weightvar(--yeti-weight-strong)按钮文字字重--yeti-button-padding2内边距以该尺寸的 space 步长为倍数--yeti-badge-radiusvar(--yeti-radius-full)徽章圆角full 即胶囊形--yeti-badge-weightvar(--yeti-weight-strong)徽章文字字重--yeti-card-radiusvar(--yeti-radius-md)卡片圆角--yeti-card-paddingvar(--yeti-space-md)卡片内边距--yeti-card-gapvar(--yeti-space-sm)卡片各部件间距--yeti-card-bordervar(--yeti-color-border)卡片边框raised 时为透明--yeti-card-surfacevar(--yeti-color-surface-raised)卡片背景--yeti-field-gapvar(--yeti-space-xs)字段标签、控件、提示间的间距--yeti-table-stripevar(--yeti-color-surface-sunken)data-striped时偶数行填充--yeti-table-bordervar(--yeti-color-border)行与单元格边框--yeti-seam-size尺寸 space 步长的两倍仅覆盖用切割深度设置它可为所有尺寸固定深度--yeti-seam-size与 scale 组的两个总开关一样属于仅覆盖用令牌Yeti 本身不声明它在 src/tokens/tokens.json 中标记为declared: false但你可以在主题中主动设置来固定其行为。实战写一个自己的主题文件所谓主题就是把所有令牌覆盖放进一个独立 CSS 文件只包含:root选择器与--yeti-*属性在yeti.css之后加载link relstylesheet href/css/yeti.css link relstylesheet href/css/themes/my-theme.css仓库自带两个可运行的主题示例src/themes/soft.css 与 src/themes/sharp.css它们展示了少量令牌如何带来截然不同的观感。soft 主题圆润温暖胶囊按钮、宽松卡片:root { --yeti-hue-primary: 30; --yeti-hue-secondary: 340; --yeti-chroma: 0.12; --yeti-ratio-max: 1.4; --yeti-radius-md: 1rem; --yeti-radius-lg: 1.5rem; --yeti-button-radius: var(--yeti-radius-full); --yeti-button-weight: var(--yeti-weight-normal); --yeti-badge-radius: var(--yeti-radius-full); --yeti-card-radius: var(--yeti-radius-lg); --yeti-card-padding: var(--yeti-space-lg); --yeti-card-border: var(--yeti-color-primary-subtle); --yeti-shadow-sm: 0 2px 8px var(--yeti-shadow-color); --yeti-control-radius: var(--yeti-radius-md); }sharp 主题方正硬朗等宽字体、直角、厚边框:root { --yeti-font-sans: var(--yeti-font-mono); --yeti-base-max: 1rem; --yeti-ratio-max: 1.2; --yeti-chroma: 0.05; --yeti-radius-sm: 0; --yeti-radius-md: 0; --yeti-radius-lg: 0; --yeti-radius-full: 0; --yeti-border-width: 2px; --yeti-weight-strong: 700; --yeti-color-border: var(--yeti-color-text); --yeti-control-border: var(--yeti-color-text); --yeti-card-surface: var(--yeti-color-surface); --yeti-shadow-sm: 4px 4px 0 var(--yeti-color-text); --yeti-table-border: var(--yeti-color-text); }主题的数据而非代码属性主题文件不允许出现任何非:root选择器也不允许设置不被识别的令牌——验证器会拒绝设置了 class、元素或未知令牌的主题。这一点保证了主题是可移植的数据而非代码升级到新版 Yeti 时只要公开令牌名称不变你的主题原样可用而--_yeti-*内部令牌因为可能在 minor 版本间变化正是被排除在主题 API 之外的原因。主题改变的是组件的外观从不改变你书写标记的方式——设置--yeti-button-radius与使用data-variant、data-size是正交的。结合 docs/guides/theming.md 中关于 oklch 值阅读、深浅色切换与比例尺的说明你可以用这套令牌体系完成从换一个强调色到整站换皮的全部工作全程不写一行组件 CSS。【免费下载链接】yetiA CSS-first, native, zero-build layout and styling framework for web designers.项目地址: https://gitcode.com/gh_mirrors/fo/yeti创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表