ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

从 neat-annotations 学现代 CSS 新特性:light-dark()、oklch 与 @property 彩虹动画实战

从 neat-annotations 学现代 CSS 新特性:light-dark()、oklch 与 @property 彩虹动画实战

【免费下载链接】neat-annotations

Hand-drawn CSS annotations for inline content

项目地址:https://gitcode.com/gh_mirrors/ne/neat-annotations
点击查看免费下载

neat-annotations 是一个纯 CSS 实现的手绘风格网页注释库,没有 JavaScript、没有构建步骤,一个自包含的样式文件就能给文字加上手绘箭头和手写标签。读它的源码 neat-annotations.css,就像上一节现代 CSS 入门课:light-dark()让颜色自动适配明暗主题,oklch()让人眼友好的色彩运算成为可能,@property更是解锁了 CSS 变量彩虹动画。本文带你从这些实战代码里,快速学会这三样最常用的 CSS 新特性。

认识 neat-annotations:纯 CSS 的手绘注释

neat-annotations 的用法简单到只有一行 HTML:给要强调的文字加一个ann类,再写上data-note属性,箭头和标签就会自动出现。

<span class="ann ann-n ann-amber" />

它内置了 8 个方向(ann-n、ann-e、ann-s……像指南针一样命名)和 6 种颜色(ann-amber、ann-rainbow等),每个方向、每种颜色背后,都是现代 CSS 新特性的经典用法。

light-dark() 实战:一行代码适配明暗双主题

传统做法是用媒体查询prefers-color-scheme: dark重写一遍颜色,繁琐还容易漏。light-dark(浅色值, 深色值)直接根据系统主题取值,一处声明、自动切换。

neat-annotations 里到处是这种写法。默认灰色的定义(neat-annotations.css):

--ann-color: light-dark(#898584, #b8b8bd);

浅色主题下箭头是#898584,深色主题下自动换成更亮的#b8b8bd,无需任何额外规则。六种内置颜色全部用它一行搞定(neat-annotations.css):

.ann-blue { --ann-color: light-dark(#3b72c4, #78a9ef); } .ann-green { --ann-color: light-dark(#2f8f5b, #67c792); } .ann-rainbow { /* 下面讲 */ }

小技巧:light-dark()还能嵌套在自定义属性里。你想用任意颜色时,直接在元素上写style="--ann-color: light-dark(#111, #f5f5f7)",就拥有了自适应的自定义配色。

oklch 色彩空间:让高亮色"跟随"文字颜色

oklch()是一种感知均匀的颜色空间:用亮度(L)、色彩度(C)、色相(H)三个直觉化的参数描述颜色,比 RGB 更适合"基于某个颜色派生另一个颜色"的场景。

neat-annotations 的高亮背景色就展示了两种玩法(neat-annotations.css):

--ann-mark: light-dark( color-mix(in oklch, var(--ann-color) 10%, transparent), oklch(from var(--ann-color) l calc(c * 1.35) h / 24%) );
  • color-mix(in oklch, ...):把文字颜色按 10% 混入透明色,得到柔和的"荧光笔"底色。混入的通道指定oklch,混合结果才自然不灰暗。
  • oklch(from var(--ann-color) l calc(c * 1.35) h / 24%):from关键字从现有颜色中提取 L、C、H,再调整——亮度沿用、色彩度提高 35%、色相不变、透明度 24%。深色主题下的高亮色就这样"从文字颜色里长出来"。

.ann-amber还配了一段注释说明为什么琥珀色的高亮要用亮黄色#ffb000而不是文字本身的橙色——这正是感知色彩空间带来的调参直觉(neat-annotations.css)。

@property 彩虹动画:让 CSS 变量真正动起来

ann-rainbow是最出彩的效果:箭头和标签的颜色沿着整个色轮缓缓流转。它的实现只用了三段代码,却是 CSS 动画的新范式。

第一步:声明变量的类型(neat-annotations.css)

@property --ann-rainbow-hue { syntax: "<angle>"; inherits: false; initial-value: 350deg; }

没有@property时,CSS 变量只是"文本替换",浏览器不知道350deg到710deg之间的值应该怎样插值,动画根本跑不起来。@property告诉浏览器:这个变量是角度,于是插值、动画全部生效。

第二步:用变量驱动颜色(neat-annotations.css)

.ann-rainbow { --ann-color: oklch(0.65 0.28 var(--ann-rainbow-hue, 350deg)); }

这里把 oklch 的色相参数交给变量。色相是连续的角度,转动它就能在色轮上平滑滑动——这是 RGB 变量做不到的。

第三步:关键帧只转色相,外加无障碍保护(neat-annotations.css)

@keyframes ann-rainbow-cycle { to { --ann-rainbow-hue: 710deg; } } @media (prefers-reduced-motion: no-preference) { .ann-rainbow { animation: ann-rainbow-cycle 3s linear infinite; } }

从 350deg 转到 710deg(整整一圈),动画无限循环,3 秒一个周期。prefers-reduced-motion媒体查询则保证:用户系统若开启了"减弱动态效果",动画自动关闭——细节见分晓。

顺带收下的其他 CSS 新特性

这个 160 多行的小文件还有不少值得偷师的地方:

  • mask+ 内联 SVG 数据 URI:箭头不是图片文件,而是用mask: var(--_ann-arrow-mask)把一段 base64 风格的 SVG 路径"蒙版"成任意颜色(neat-annotations.css),换个变量就换支"笔"。
  • forced-colors: active:Windows 高对比度模式下的兜底规则,把箭头换成系统CanvasText颜色(neat-annotations.css)。
  • 属性选择器控制显隐:.ann:not([data-note])让没有标签的纯高亮写法成立,纯 CSS 就能做"条件渲染"。
  • 完整功能清单与自定义变量说明见 README.md。

动手试试:3 步跑起来

  1. 获取源码:git clone https://gitcode.com/gh_mirrors/ne/neat-annotations,或直接用仓库里的 neat-annotations.css。
  2. 在自己的 HTML 中引入:<link rel="stylesheet" href="neat-annotations.css">。
  3. 挑一段文字包上<span class="ann ann-n ann-rainbow">

【免费下载链接】neat-annotations

Hand-drawn CSS annotations for inline content

项目地址:https://gitcode.com/gh_mirrors/ne/neat-annotations
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进