mcpField
C
css-native

css-native

github.com/athevon设计与 UI6981.0k 次安装3 周前更新
代码仓库

关于 css-native

css-native 是一项使用原生 CSS 构建网页动画和视觉效果的创意编码技能。它涵盖滚动驱动效果、View Transitions、弹出层定位等技术,并说明何时可能适合改用库。

主要功能

  1. 01滚动驱动的 CSS 动画
  2. 02用于页面切换的 View Transitions
  3. 03原生进入与退出转场
  4. 04弹出层锚点定位
  5. 05CSS 与动画库的选择指导

适用场景

  1. 01为页面添加滚动联动显现效果
  2. 02为隐藏状态打开的对话框添加动画
  3. 03定位并动画化提示框
  4. 04选择 CSS 或动画库

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/athevon/genjutsu --skill css-native

安装后在 Claude Code 中输入/css-native确认已加载。

详细介绍

版本敏感。 以下每个 API 名称、SDK 门槛和浏览器支持声明,均已于 2026-09-08 根据一手来源核实。核实了哪些内容以及核实时间,见 _jutsu/VERSIONS.md。如果这个日期已经很久远,请在依据版本号采取行动前重新核实。

CSS 原生功能 - 零依赖动画与视觉技巧

何时使用 CSS 原生功能,何时使用库

情况决策
页面上的动画少于 3 个CSS 原生功能
滚动驱动的显现/视差效果CSS 原生功能(animation-timeline);始终放在 @supports (animation-timeline: scroll()) 内,并确保内容默认可见——Firefox 尚无正式版支持
从 display: none 进入/退出CSS 原生功能(@starting-style + transition-behavior: allow-discrete)
工具提示/弹出层定位CSS 原生功能(锚点定位)
页面过渡(MPA 或 SPA)CSS 原生功能(视图过渡 API)
复杂的多步骤时间线(5 个以上补间)GSAP
动态列表中的交错动画(数量未知)CSS 原生功能(animation-delay: calc(sibling-index() * 60ms));自 2026 年 8 月起达到 Baseline。只有在交错动画必须在运行时中断或重新排序时,才考虑使用库
可中断的物理弹簧动画Framer Motion
SVG 形状之间的变形GSAP MorphSVG

经验法则:如果能用一个 @keyframes + 一个 animation-timeline 表达,就继续使用 CSS。需要命令式控制、序列协调或运行时值时,就改用库。


滚动驱动动画

滚动进度时间线

根据容器的滚动位置生成动画。

.progress-bar {
  animation: grow-width linear both;
  animation-timeline: scroll(root block);
}

@keyframes grow-width {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
  • scroll(<scroller> <axis>) - scroller:nearest | root | self,axis:block | inline | x | y
  • 默认值:scroll(nearest block)
视图进度时间线

当元素进入/离开滚动视口时生成动画。

.reveal {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(2rem); }
  to   { opacity: 1; transform: translateY(0); }
}
animation-range

控制时间线中驱动动画的区段。

/* Named ranges: cover | contain | entry | exit | entry-crossing | exit-crossing */
animation-range: entry 0% entry 100%;    /* animate during entry only */
animation-range: contain 0% contain 100%; /* animate while fully visible */
animation-range: entry 25% exit 75%;      /* custom start/end */

使用 滚动驱动动画工具 交互式查看各个范围。


视图过渡 API

同文档(SPA)
document.startViewTransition(() => {
  // Update the DOM synchronously
  updateContent();
});
/* Control the transition animation */
::view-transition-old(root) {
  animation: fade-out 200ms ease-out;
}
::view-transition-new(root) {
  animation: fade-in 300ms ease-in;
}

/* Named transitions for specific elements */
.hero-image { view-transition-name: hero; }

::view-transition-group(hero) {
  animation-duration: 400ms;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
跨文档(MPA)
/* Both pages need this */
@view-transition { navigation: auto; }

/* Outgoing page */
.card { view-transition-name: card-detail; }

/* Incoming page */
.detail-hero { view-transition-name: card-detail; }
view-transition-class(分组样式)
.card { view-transition-class: card; }

::view-transition-group(*.card) {
  animation-duration: 350ms;
  animation-timing-function: var(--ease-spring);
}

@starting-style

从 display: none 开始的原生进入动画——无需使用 JS 变通方法控制时序。

.dialog {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 300ms ease, transform 300ms ease,
              display 300ms allow-discrete;

  @starting-style {
    opacity: 0;
    transform: translateY(-1rem);
  }
}

.dialog[hidden] {
  opacity: 0;
  transform: translateY(-1rem);
  display: none;
}

关键规则:

  • transition-behavior: allow-discrete(或在 transition 中使用简写 allow-discrete)可启用对 display 和 overlay 的过渡
  • @starting-style 块定义元素首次渲染时的「起始」状态
  • 与 [popover] 和 <dialog> 搭配,可创建无需任何 JS 动画代码的原生模态框

锚点定位

相对于触发元素定位工具提示、弹出层和浮动 UI 的 CSS 原生方式。

.trigger {
  anchor-name: --my-trigger;
}

.tooltip {
  position: fixed;
  position-anchor: --my-trigger;
  position-area: top center;
  margin-bottom: 0.5rem;

  /* Fallback if no space on top */
  position-try-fallbacks: --bottom;
}

@position-try --bottom {
  position-area: bottom center;
  margin-top: 0.5rem;
}

与 @starting-style 搭配,为工具提示添加动画:

.tooltip[popover]:popover-open {
  opacity: 1;
  transform: scale(1);
  transition: opacity 150ms ease, transform 150ms ease,
              display 150ms allow-discrete, overlay 150ms allow-discrete;

  @starting-style {
    opacity: 0;
    transform: scale(0.96);
  }
}

容器查询 + 上下文动画

根据组件的容器尺寸而非视口调整动画。

.card-container {
  container-type: inline-size;
  container-name: card;
}

@container card (min-width: 400px) {
  .card-content {
    animation: slide-in-right 400ms var(--ease-out-expo);
  }
}

@container card (max-width: 399px) {
  .card-content {
    animation: fade-in 300ms ease;
  }
}

关键帧中的容器相对单位:

@keyframes slide-in-right {
  from { transform: translateX(10cqw); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

高级视觉技巧

clip-path 过渡
.reveal {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 600ms cubic-bezier(0.77, 0, 0.175, 1);
}
.reveal.visible {
  clip-path: inset(0 0 0 0);
}

形状变形:在 circle()、ellipse()、polygon()、inset() 之间过渡,只要函数类型和点数一致即可。

backdrop-filter
.glass {
  background: oklch(0.98 0.01 250 / 0.6);
  backdrop-filter: blur(12px) saturate(1.8);
  -webkit-backdrop-filter: blur(12px) saturate(1.8); /* Safari */
}
mix-blend-mode
.overlay-text {
  mix-blend-mode: difference;
  color: white; /* inverts over any background */
}
网格渐变(近似实现)
.mesh {
  background:
    radial-gradient(at 20% 30%, oklch(0.7 0.2 310) 0%, transparent 50%),
    radial-gradient(at 80% 60%, oklch(0.6 0.18 250) 0%, transparent 50%),
    radial-gradient(at 50% 80%, oklch(0.75 0.15 170) 0%, transparent 50%),
    oklch(0.15 0.02 280);
}
conic-gradient 效果
.spinner {
  background: conic-gradient(from 0deg, transparent 0%, oklch(0.7 0.15 250) 100%);
  border-radius: 50%;
  mask: radial-gradient(farthest-side, transparent calc(100% - 4px), black calc(100% - 4px));
  animation: spin 1s linear infinite;
}

不要这样做

不佳做法良好做法原因
transition: all 300mstransition: opacity 300ms, transform 300msall 会在每次属性变化时触发过渡,导致意外动画,并阻止浏览器优化
为 width、height、top、left 设置动画为 transform、opacity、clip-path、filter 设置动画触发布局的属性会在每一帧强制重排,而仅触发合成的属性则由 GPU 处理
使用没有回退方案的滚动驱动动画@supports (animation-timeline: scroll()) { ... }Firefox 的正式发布渠道完全不支持(仅 Nightly 支持,且需启用 layout.css.scroll-driven-animations.enabled),Safari 直到 26 才推出此功能——约六分之一的访客看不到任何效果
使用 @starting-style,但不设置 transition-behavior始终为 display/overlay 配合使用 allow-discrete如果不这样做,display: none 的过渡会完全跳过
使用锚点定位,但不设置 position-try-fallbacks始终定义回退位置如果首选位置没有空间,元素会被裁剪出视口
在滚动驱动动画中使用 animation-fill-mode: forwards滚动驱动动画使用 bothforwards 可能会将元素锁定在最终状态,即使用户向回滚动也是如此

深入了解

需求参考资料
滚动驱动动画、View Transitions、@starting-style、锚点定位和容器查询的浏览器支持表、回退模式及渐进增强策略(以及无障碍和性能说明)references/modern-css.md

评论

支持 Markdown