本页出处
设计风格资料库
内容来自 luckymaomi 的 UI 风格库(复刻版),以 MIT 许可 提供。本站镜像收录,仅作学习参考;这一页的原始地址是 原站页面。
← 回到导览访问原站仓库
返回风格库
视觉风格expressive

动力学排印

Kinetic Typography

文字即界面的动态排印风格。墨黑舞台上,可变字体的字重与字宽成为动画本体:逐字登场、字重呼吸、滚动速度拉伸字宽。一切动效只属于文字,唯一的信号橙负责指路。

动力学排印视觉预览
主色#0B0B0C
次色#F4F1EB
强调色 1#FF4D00
强调色 2#141416
强调色 3#8A857B

AI 实现规则

你是一个动力学排印(Kinetic Typography)风格的前端开发专家。生成的所有代码必须严格遵守以下约束:

## 绝对禁止

- 动画 top/left/width/height/margin 等布局属性(只许 transform、opacity、font-variation-settings)
- 一屏同时多个主导动效(编舞规则:一次只有一个主角在动)
- 用图片/插画抢文字的戏
- 超过一个强调色;把信号橙铺成大面积背景
- opacity-only 平淡淡入(必须遮罩上升)
- 超过 1.2s 的动画、linear 缓动
- 忽略 prefers-reduced-motion

## 必须遵守

### 舞台
- 背景 #0B0B0C(近黑墨),抬升面 #141416
- 文字 #F4F1EB(暖骨白),次要 rgba(244,241,235,0.55)
- 唯一强调 #FF4D00(信号橙):主 CTA、关键词、悬停反馈

### 可变字体引擎
加载双轴可变字体(推荐 Anybody):
<link rel="stylesheet" href="https://fonts.loli.net/css2?family=Anybody:wdth,wght@50..150,100..900&display=swap" />
标题字族: font-family: "Anybody", Archivo, ui-sans-serif, sans-serif

### 遮罩入场(招牌动效)
<span class="overflow-hidden block">
  <span class="inline-block animate-[kt-rise_0.9s_cubic-bezier(0.22,1,0.36,1)_both]" style="animation-delay: 40ms 递增">文字</span>
</span>
@keyframes kt-rise { from { transform: translateY(110%); } to { transform: translateY(0); } }

### 字重呼吸
@keyframes kt-breathe { from { font-variation-settings: "wght" 300; } to { font-variation-settings: "wght" 800; } }
用在一个关键词上,2.4s ease-in-out infinite alternate

### 滚动速度拉伸字宽(进阶,JS)
rAF 循环里测滚动速度,映射到 wdth 100→150,弹性回落:
let last = scrollY, vel = 0;
function tick() {
  vel = vel * 0.9 + Math.abs(scrollY - last) * 0.1; last = scrollY;
  el.style.fontVariationSettings = `"wght" 700, "wdth" ${Math.min(150, 100 + vel * 2)}`;
  requestAnimationFrame(tick);
}

### GSAP 配方(可选,项目已有 gsap 时优先)
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { SplitText } from "gsap/SplitText";
gsap.registerPlugin(ScrollTrigger, SplitText);
const split = SplitText.create(".headline", { type: "chars" });
gsap.from(split.chars, { yPercent: 110, stagger: 0.04, duration: 0.9, ease: "expo.out",
  scrollTrigger: { trigger: ".headline", start: "top 80%" } });

### 跑马灯
内容复制两份放进 track,track 动画 translateX(-50%) linear infinite 24s,hover 暂停

### 字号系统
- 标签: 11-12px,uppercase,letter-spacing 0.2-0.3em
- 正文: 15-16px,行高 1.6
- 标题: clamp(3rem, 10vw, 9rem),letter-spacing -0.02em,行高 0.95

### 缓动与节奏
- 唯一缓动: cubic-bezier(0.22,1,0.36,1)(expo-out)
- 入场 0.7-0.9s;hover 反馈 0.3-0.5s;stagger 逐字 30-50ms、逐行 80-120ms

### 无障碍
@media (prefers-reduced-motion: reduce) 下:所有动画 animation: none,元素停在终态,信息零丢失

## 自检

1. 背景是墨黑、文字是骨白、唯一橙色强调?
2. 标题走遮罩上升 + stagger,不是平淡 fade?
3. 动的只有 transform/opacity/font-variation-settings?
4. 一屏只有一个主导动效?
5. 有 prefers-reduced-motion 降级?
6. 缓动统一 expo-out?

组件预览与实现

uppercase tracking-[0.15em] font-semibold rounded-none transition-all duration-500 ease-[cubic-bezier(0.22,1,0.36,1)] active:scale-[0.98] bg-[#FF4D00] text-[#0B0B0C] hover:bg-[#F4F1EB] hover:-translate-y-0.5
button

Button

Ink button with signal-orange fill wipe and weight shift on hover

<button className="group relative overflow-hidden
  px-7 py-3.5
  bg-transparent border border-[#F4F1EB]/25
  text-[#F4F1EB] uppercase tracking-[0.15em] text-sm font-semibold
  transition-all duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]
  hover:border-[#FF4D00] hover:text-[#0B0B0C]
  active:scale-[0.98]
">
  <span className="absolute inset-0 bg-[#FF4D00] translate-y-full group-hover:translate-y-0 transition-transform duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]" />
  <span className="relative z-10">Enter Motion</span>
</button>
card

Card

Numbered type card whose headline gains weight on hover

<article className="group border border-[#F4F1EB]/15 py-8 px-1
  transition-colors duration-500 hover:border-[#FF4D00]
">
  <span className="block font-mono text-xs text-[#F4F1EB]/40 mb-4">01</span>
  <h3 className="text-3xl md:text-4xl text-[#F4F1EB] tracking-tight leading-none mb-3
    [font-variation-settings:'wght'_450]
    group-hover:[font-variation-settings:'wght'_800]
    transition-[font-variation-settings] duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]
  ">
    Weight Is Volume
  </h3>
  <p className="text-[#F4F1EB]/55 text-sm max-w-sm leading-relaxed">
    The headline speaks louder as you approach. No color change, no shadow — just mass.
  </p>
</article>
input

Input

Underline field whose baseline sweeps in signal orange on focus

<label className="group block">
  <span className="block font-mono text-[11px] uppercase tracking-[0.25em] text-[#F4F1EB]/45 mb-2
    group-focus-within:text-[#FF4D00] transition-colors duration-300">
    Your Name
  </span>
  <div className="relative">
    <input type="text" placeholder="Type here"
      className="w-full bg-transparent py-3 text-xl text-[#F4F1EB] placeholder-[#F4F1EB]/25
        border border-[#F4F1EB]/20 focus:outline-none" />
    <span className="absolute bottom-0 left-0 h-px w-full bg-[#FF4D00] origin-left scale-x-0
      group-focus-within:scale-x-100 transition-transform duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]" />
  </div>
</label>
nav

Navigation

Wordmark nav; links grow an orange underline sweep on hover

<nav className="fixed top-0 left-0 right-0 z-50 bg-[#0B0B0C]/90 backdrop-blur-sm border border-[#F4F1EB]/10">
  <div className="max-w-6xl mx-auto px-6 h-16 flex items-center justify-between">
    <a href="/" className="text-[#F4F1EB] font-extrabold tracking-tight text-lg">
      KINETIC<span className="text-[#FF4D00]">*</span>
    </a>
    <div className="flex items-center gap-7">
      <a href="#work" className="group relative text-sm text-[#F4F1EB]/60 hover:text-[#F4F1EB] uppercase tracking-[0.15em] transition-colors duration-300">
        Work
        <span className="absolute -bottom-1 left-0 h-px w-full bg-[#FF4D00] origin-left scale-x-0 group-hover:scale-x-100 transition-transform duration-400 ease-[cubic-bezier(0.22,1,0.36,1)]" />
      </a>
    </div>
  </div>
</nav>
hero

Hero

Giant staggered mask-rise headline with one breathing accent word

<section className="min-h-screen bg-[#0B0B0C] flex items-center px-6 overflow-hidden">
  <style>{`
    @keyframes kt-rise { from { transform: translateY(110%); } to { transform: translateY(0); } }
    @keyframes kt-breathe {
      from { font-variation-settings: "wght" 300; }
      to { font-variation-settings: "wght" 800; }
    }
    .kt-line { overflow: hidden; }
    .kt-line > span { display: inline-block; animation: kt-rise 0.9s cubic-bezier(0.22,1,0.36,1) both; }
    .kt-breathe { animation: kt-breathe 2.4s ease-in-out infinite alternate; }
    @media (prefers-reduced-motion: reduce) {
      .kt-line > span { animation: none; }
      .kt-breathe { animation: none; font-variation-settings: "wght" 700; }
    }
  `}</style>
  <h1 className="text-[#F4F1EB] tracking-tight leading-[0.95] text-[clamp(3rem,10vw,9rem)] font-bold">
    <span className="kt-line block"><span style={{ animationDelay: "0s" }}>Words</span></span>
    <span className="kt-line block"><span style={{ animationDelay: "0.08s" }}>in <em className="not-italic text-[#FF4D00] kt-breathe">motion</em></span></span>
  </h1>
</section>

交互展示

适用范围与设计理念

应用场景

creativemarketingportfolio

视觉关键词

kinetic typographyvariable fontmotionstaggermarqueetype-driven动态排印可变字体文字动画

动力学排印的信条:文字不是排上去的,是登场的。当文字本身成为唯一主角,动效就不再是装饰,而是语气——字重是音量,字宽是呼吸,入场节奏是断句。

核心理念:

- 文字即界面:没有插图、没有图标堆砌,信息层级全部由字号、字重、字宽的巨大反差承担(12px 的注释与 12vw 的标题同屏)

- 可变字体是引擎:动画的不是位置和颜色,而是 font-variation-settings 的 wght 与 wdth 轴——这是别的风格做不到的原生动效

- 编舞规则:一屏只允许一个主导动效。逐字入场时别的元素安静;跑马灯滚动时标题静止

- 遮罩入场:文字从 overflow 遮罩下方升起(translateY 110% → 0),像幕布后走出的演员,绝不用平淡的 fade

- 唯一信号色:信号橙 #FF4D00 只用于主 CTA、关键词高亮和悬停反馈,永不铺底

- 动效即物理:expo-out 缓动(cubic-bezier(0.22,1,0.36,1)),快启动慢落定;stagger 30-50ms 制造波浪

设计原则:

- 性能红线:只动 transform / opacity / font-variation-settings,绝不动 top/left/width 触发重排

- 无障碍红线:prefers-reduced-motion 下所有动画降级为静态终态,信息零丢失

- 交互反馈:hover 字重加粗或下划线扫入,active 缩放 0.98,focus 有可见轮廓

- 响应式:标题用 clamp() 流式缩放,移动端 stagger 间隔减半保持利落

应该这样做

  • 背景用近黑墨色 #0B0B0C,文字用暖骨白 #F4F1EB,制造高对比舞台感
  • 加载可变字体(如 Anybody,wght 100-900 + wdth 50-150 双轴)作为展示字体
  • 标题入场用遮罩上升:外层 overflow-hidden,内层 translateY(110%) 动画到 0,逐字/逐词 stagger 30-50ms
  • 缓动统一用 expo-out:cubic-bezier(0.22,1,0.36,1),时长 0.7-0.9s
  • 用 font-variation-settings 动画字重(呼吸 300-800)与字宽(滚动速度联动 100-150)
  • 字号反差拉满:标签 11-12px 大写宽字距 + 标题 clamp(3rem,10vw,9rem) tracking-tight
  • 跑马灯用 CSS 无缝循环(内容复制两份 + translateX -50%),hover 暂停
  • 信号橙 #FF4D00 只出现在主 CTA、关键词与悬停态
  • 所有动画都写 prefers-reduced-motion 降级到静态终态

避免这样做

  • 禁止动画 top/left/width/height 等布局属性(重排卡顿)——只许 transform/opacity/font-variation-settings
  • 禁止一屏同时跑多个主导动效(编舞规则:一次一个主角)
  • 禁止用图片或插画抢文字的戏(本风格里图像最多是背景纹理)
  • 禁止超过一个强调色,禁止把信号橙铺成大面积底色
  • 禁止平淡的 opacity-only 淡入代替遮罩上升
  • 禁止超过 1.2s 的拖沓动画与 linear 缓动
  • 禁止忽略 prefers-reduced-motion

全局 CSS

/* Kinetic Typography Global Styles */

:root {
  --kt-ink: #0B0B0C;
  --kt-ink-raised: #141416;
  --kt-bone: #F4F1EB;
  --kt-signal: #FF4D00;
  --kt-muted: rgba(244, 241, 235, 0.55);
  --kt-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --kt-duration: 0.9s;
  --kt-stagger: 40ms;
}

/* Mask-rise entrance: wrap each line in .kt-line, put text in a child span */
.kt-line {
  overflow: hidden;
  display: block;
}
.kt-line > span {
  display: inline-block;
  transform: translateY(110%);
  animation: kt-rise var(--kt-duration) var(--kt-ease) both;
}

@keyframes kt-rise {
  to { transform: translateY(0); }
}

/* Variable-font weight breathing */
@keyframes kt-breathe {
  from { font-variation-settings: "wght" 300; }
  to { font-variation-settings: "wght" 800; }
}
.kt-breathe { animation: kt-breathe 2.4s ease-in-out infinite alternate; }

/* Seamless marquee: duplicate the strip content twice inside .kt-marquee-track */
.kt-marquee { overflow: hidden; white-space: nowrap; }
.kt-marquee-track {
  display: inline-flex;
  animation: kt-marquee 24s linear infinite;
}
.kt-marquee:hover .kt-marquee-track { animation-play-state: paused; }
@keyframes kt-marquee {
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .kt-line > span { animation: none; transform: none; }
  .kt-breathe { animation: none; font-variation-settings: "wght" 700; }
  .kt-marquee-track { animation: none; }
}

布局、色板与 Tokens

主色#0B0B0C
次色#F4F1EB
强调色 1#FF4D00
强调色 2#141416
强调色 3#8A857B
{
  "border": {
    "width": "border",
    "color": "border-[#F4F1EB]/20",
    "radius": "rounded-none",
    "style": "border-solid"
  },
  "shadow": {
    "sm": "shadow-none",
    "md": "shadow-none",
    "lg": "shadow-none",
    "none": "shadow-none",
    "hover": "hover:shadow-none",
    "focus": "focus:shadow-[0_0_0_2px_rgba(255,77,0,0.4)]",
    "colored": {}
  },
  "interaction": {
    "transition": "transition-all duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]",
    "active": "active:scale-[0.98]",
    "hoverOpacity": "hover:text-[#F4F1EB]"
  },
  "typography": {
    "heading": "font-bold text-[#F4F1EB] tracking-tight leading-[0.95]",
    "body": "text-[#F4F1EB]/70",
    "mono": "font-mono text-[#F4F1EB]/50 uppercase tracking-[0.25em]",
    "sizes": {
      "hero": "text-[clamp(3rem,10vw,9rem)]",
      "h1": "text-5xl md:text-7xl",
      "h2": "text-3xl md:text-5xl",
      "h3": "text-2xl md:text-3xl",
      "body": "text-sm md:text-base",
      "small": "text-[11px]"
    }
  },
  "spacing": {
    "section": "py-20 md:py-32",
    "container": "px-6 md:px-10",
    "card": "py-8 px-1",
    "gap": {
      "sm": "gap-3",
      "md": "gap-6",
      "lg": "gap-10"
    }
  },
  "colors": {
    "background": {
      "primary": "bg-[#0B0B0C]",
      "secondary": "bg-[#141416]",
      "accent": [
        "bg-[#FF4D00]"
      ]
    },
    "text": {
      "primary": "text-[#F4F1EB]",
      "secondary": "text-[#F4F1EB]/70",
      "muted": "text-[#F4F1EB]/45"
    },
    "button": {
      "primary": "bg-[#FF4D00] text-[#0B0B0C]",
      "secondary": "bg-transparent text-[#F4F1EB] border border-[#F4F1EB]/25"
    }
  },
  "forbidden": {
    "classes": [
      "rounded-lg",
      "rounded-xl",
      "rounded-2xl",
      "rounded-3xl",
      "rounded-full",
      "shadow-md",
      "shadow-lg",
      "shadow-xl",
      "shadow-2xl",
      "bg-gradient-to-r",
      "bg-gradient-to-br",
      "from-indigo-600",
      "via-purple-600",
      "to-pink-500",
      "duration-100",
      "duration-2000",
      "ease-linear",
      "italic"
    ],
    "patterns": [
      "^rounded-(lg|xl|2xl|3xl|full)$",
      "^shadow-(md|lg|xl|2xl)$",
      "^bg-gradient-",
      "^duration-(100|150|2000)$",
      "^ease-linear$"
    ],
    "reasons": {
      "rounded-lg": "Kinetic typography uses sharp editorial edges (rounded-none)",
      "rounded-full": "Sharp editorial edges only; pills soften the type stage",
      "shadow-lg": "Depth comes from type contrast, never drop shadows",
      "bg-gradient-to-r": "The stage is flat ink; gradients dilute the type",
      "from-indigo-600": "No AI-cliche gradients; ink, bone and one signal orange only",
      "duration-100": "Motion needs room to breathe: 300-900ms with expo-out",
      "duration-2000": "Animations over 1.2s drag; keep entrances under 0.9s",
      "ease-linear": "Linear easing is lifeless; use cubic-bezier(0.22,1,0.36,1)",
      "italic": "Emphasis comes from weight and width axes, not slant"
    }
  },
  "required": {
    "button": [
      "uppercase tracking-[0.15em] text-sm font-semibold",
      "border border-[#F4F1EB]/25",
      "rounded-none",
      "transition-all duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]",
      "hover:border-[#FF4D00]",
      "active:scale-[0.98]"
    ],
    "card": [
      "border border-[#F4F1EB]/15",
      "rounded-none",
      "hover:border-[#FF4D00]",
      "transition-colors duration-500"
    ],
    "input": [
      "bg-transparent",
      "border border-[#F4F1EB]/20",
      "rounded-none",
      "text-[#F4F1EB] placeholder-[#F4F1EB]/25",
      "focus:outline-none"
    ]
  }
}

示例提示词

动力学排印落地页

文字为唯一主角的产品发布页

Create a kinetic typography landing page with:
1. Stage: #0B0B0C background, #F4F1EB text, single #FF4D00 accent
2. Load variable font Anybody (wght 100-900, wdth 50-150) from fonts.loli.net
3. Hero: clamp(3rem,10vw,9rem) headline, each line rising from an overflow mask with 80ms stagger, one accent word running a wght 300-800 breathing loop
4. A full-width marquee strip of uppercase feature words, pause on hover
5. Numbered feature cards whose headlines jump from wght 450 to 800 on hover
6. CTA button with signal-orange fill wipe rising on hover
7. All easing cubic-bezier(0.22,1,0.36,1); only transform/opacity/font-variation-settings animate; prefers-reduced-motion lands everything on static end states

文字驱动作品集

无图片的纯排印作品集

Create a type-driven portfolio site with:
1. Ink stage #0B0B0C, bone type #F4F1EB, orange signal #FF4D00
2. Project list as huge headline rows (clamp 2.5rem-6rem): on hover the row's font-variation-settings width stretches wdth 100 to 130 and an orange index number slides in
3. Section headings enter with per-char mask rise, 40ms stagger, expo-out
4. A skills marquee strip between sections, opposite scroll directions on alternate strips
5. Footer contact line with a giant breathing "HELLO" (wght 300-800 loop)
6. GSAP ScrollTrigger optional recipe for scroll-scrubbed entrances; CSS fallback required
7. prefers-reduced-motion: all text static at final weights