前端设计

中级 Intermediate 参考型 Reference claude-code
8 min read · 386 lines

创建独特的生产级前端界面,摆脱千篇一律的 AI 审美

前端设计

本技能指南用于创建独特的、生产级的前端界面,避免千篇一律的"AI 风格"审美。实现真正可运行的代码,对审美细节和创意选择给予极高关注。

用户提供前端需求:一个组件、页面、应用或界面。他们可能会提供关于用途、受众或技术约束的上下文信息。

设计思维

在编码之前,理解上下文并确定一个大胆的审美方向:

  • 用途:这个界面解决什么问题?谁在使用它?
  • 基调:选择一个极端风格:极简粗暴、极繁主义混乱、复古未来主义、有机/自然、奢华/精致、趣味/玩具风、编辑/杂志风、粗野主义/原始、装饰艺术/几何、柔和/粉彩、工业/实用主义等。风格种类繁多,以上仅供灵感参考,但最终设计应忠于所选的审美方向。
  • 约束:技术要求(框架、性能、无障碍性)。
  • 差异化:什么让它令人难忘?用户会记住的那一个亮点是什么?

关键原则:选择一个明确的概念方向并精准执行。大胆的极繁主义和精致的极简主义都能成功——关键在于意图性,而非强度。

然后实现可运行的代码(HTML/CSS/JS、React、Vue 等),需满足:

  • 生产级且功能完整
  • 视觉上引人注目且令人难忘
  • 具有清晰审美观点的整体一致性
  • 每个细节都精心打磨

前端审美指南

重点关注:

  • 字体排印:选择美观、独特且有趣的字体。避免使用 Arial、Inter 等通用字体;转而选择能提升前端审美的独特字体——出人意料的、有个性的字体选择。将一个独特的展示字体与一个精致的正文字体进行搭配。
  • 色彩与主题:确定一个统一的审美风格。使用 CSS 变量保持一致性。以主色调搭配鲜明强调色的方案,远胜于畏缩的、均匀分布的色板。
  • 动效:使用动画实现效果和微交互。HTML 优先使用纯 CSS 方案。React 可用时使用 Motion 库(动画使用 anime.js,参见下方 Anime.js v4 参考)。聚焦高影响力时刻:一个精心编排的页面加载配合交错展现(animation-delay),比零散的微交互更令人愉悦。使用滚动触发和令人惊喜的悬停状态。
  • 空间构成:意想不到的布局。不对称性。重叠。对角线流动。打破网格的元素。慷慨的留白或有控制的密度。
  • 背景与视觉细节:营造氛围和层次感,而非默认使用纯色。添加与整体审美匹配的语境化效果和纹理。运用创意形式,如渐变网格、噪点纹理、几何图案、分层透明度、戏剧性阴影、装饰性边框、自定义光标和颗粒叠加。

绝不使用通用的 AI 生成审美,例如过度使用的字体系列(Inter、Roboto、Arial、系统字体)、老套的配色方案(特别是白色背景上的紫色渐变)、可预测的布局和组件模式,以及缺乏特定上下文个性的千篇一律的设计。

创造性地诠释,做出出乎意料的选择,让设计真正为上下文量身定制。每个设计都不应相同。在浅色和深色主题、不同字体、不同审美风格之间变化。绝不在不同生成之间趋同于常见选择(例如 Space Grotesk)。

重要提示:实现复杂度应匹配审美愿景。极繁主义设计需要精心编写的代码,包含大量动画和效果。极简主义或精致的设计需要克制、精确,以及对间距、字体排印和微妙细节的仔细关注。优雅来自于对愿景的出色执行。

记住:Claude 具备非凡的创造力。不要退缩——展示在跳出框架思考并全力投入独特愿景时能够真正创造的作品。


Anime.js v4 参考指南

严重警告:务必使用 Anime.js v4 语法

本项目使用 Anime.js v4.x.x——在任何情况下都不要使用 v3 语法

如果你准备写 import anime from 'animejs'——停下! 那是 v3。本项目使用 v4。请使用以下正确的导入方式。

快速开始 - 基本设置

1. 正确的 v4 导入(必须)

// 正确的 v4 导入方式
import { animate, createTimeline, stagger, utils, svg, eases, engine } from 'animejs';

// 错误的 v3 导入方式 - 绝不使用
// import anime from 'animejs';

2. 配置时间单位为秒(仅在应用入口设置一次)

// 重要:仅在应用主入口文件设置一次
// React: App.js/App.tsx 或 index.js/index.tsx
// Vue: main.js/main.ts
// 原生 JS: 最先加载的主脚本文件

import { engine } from 'animejs';

// 仅在应用入口设置,不要在组件中设置
engine.timeUnit = 's';

// 现在所有时长都使用秒:1 = 1秒, 0.5 = 500ms
// 不要在单个组件中设置——这是全局设置!

3. 简单动画使用单行格式(必须)

// 好 - 简洁、可读、一行搞定
animate('.element', { x: 250, duration: 1, ease: 'outQuad' });

// 差 - 简单动画不必多行
animate('.element', {
  x: 250,
  duration: 1,
  ease: 'outQuad'
});

验证清单

生成 anime.js 代码前,确认:

  • 使用 import { animate, ... } from 'animejs' 而非 import anime
  • engine.timeUnit = 's' 仅在应用入口设置一次(不在组件中)
  • 所有时长使用秒(1 = 1秒)
  • 简单动画写在一行
  • 使用 animate() 而非 anime()
  • 使用 createTimeline() 而非 anime.timeline()
  • 使用 ease: 而非 easing:
  • 值使用 to:,而非 value:
  • 回调使用 on 前缀(onUpdate、onComplete)
  • 使用 loopalternate,而非 direction
  • 使用正确的 v4 stagger 语法 stagger()
  • 尽可能使用简写属性(x、y、z)

核心 API - 最常用模式

基础动画(简单动画单行写法)

// 简单补间 - 始终一行
animate('.element', { x: 250, rotate: 180, duration: 0.8, ease: 'inOutQuad' });

// 淡入 - 一行
animate('.element', { opacity: [0, 1], y: [20, 0], duration: 0.6, ease: 'outQuad' });

// 弹性缩放 - 一行
animate('.element', { scale: [0, 1], duration: 0.8, ease: 'outElastic(1, 0.5)' });

// 无限循环 - 一行
animate('.element', { rotate: 360, duration: 2, loop: true, ease: 'linear' });

时间线创建

const tl = createTimeline({ defaults: { duration: 1, ease: 'outQuad' } });

tl.add('.element1', { x: 250 })
  .add('.element2', { y: 100 }, '+=0.2')  // 在前一个动画结束0.2秒后
  .add('.element3', { rotate: 180 }, '<'); // 与前一个动画同时开始

交错动画(单行写法)

animate('.elements', { x: 250, delay: stagger(0.1) });  // 每个元素间隔0.1秒
animate('.elements', { x: 250, delay: stagger(0.1, { from: 'center' }) });

常见 AI 错误示例

错误 #1:使用 v3 导入模式

// 错误 - 这是 v3
import anime from 'animejs';
anime({ targets: '.element', translateX: 250 });

// 正确 - 始终使用 v4
import { animate } from 'animejs';
animate('.element', { x: 250 });

错误 #2:使用 'targets' 属性

// 错误 - 'targets' 是 v3 语法
animate({ targets: '.element', translateX: 250 });

// 正确 - 第一个参数就是目标
animate('.element', { x: 250 });

错误 #3:使用 'easing' 而非 'ease'

// 错误
animate('.element', { x: 250, easing: 'easeInOutQuad' });

// 正确
animate('.element', { x: 250, ease: 'inOutQuad' });

错误 #4:使用 'value' 设置动画值

// 错误 - 'value' 是 v3 语法
animate('.element', { x: { value: 250 } });

// 正确 - 使用 'to' 设置值
animate('.element', { x: { to: 250 } });

错误 #5:时间线语法错误

// 错误 - anime.timeline() 是 v3 语法
const tl = anime.timeline();

// 正确 - 使用 createTimeline
import { createTimeline } from 'animejs';
const tl = createTimeline();

属性语法参考(v3 -> v4)

缓动函数

// v4:使用 'ease'(不带 'ease' 前缀)
{ ease: 'inOutQuad' }
{ ease: 'outElastic(1, 0.5)' }
{ ease: 'cubicBezier(0.4, 0, 0.2, 1)' }

// v3:不要使用 'easing' 或 'ease' 前缀
// { easing: 'easeInOutQuad' }

方向与循环

// v4
{
  loop: true,        // 无限循环
  loop: 3,          // 循环3次
  alternate: true,   // 交替方向
  reversed: true     // 反向播放
}

// v3:不要使用 'direction'
// { direction: 'alternate' }

变换属性(优先使用简写)

// v4 两种写法都有效:
animate('.element', { x: 100, y: 50, z: 25 });           // 简写(推荐)
animate('.element', { translateX: 100, translateY: 50, translateZ: 25 }); // 完整写法

回调(全部使用 'on' 前缀)

// v4:简单回调 - 保持一行
animate('.element', { x: 250, duration: 1, onComplete: () => console.log('完成!') });

// v4:多个回调 - 使用多行
animate('.element', {
  x: 250,
  duration: 1,
  onBegin: (anim) => console.log('开始'),
  onUpdate: (anim) => console.log('进度:', anim.progress),
  onComplete: (anim) => console.log('结束')
});

// v3:不要使用无前缀的回调
// { update: () => {}, complete: () => {} }

常见动画模式

悬停动画(每个动画一行)

element.addEventListener('mouseenter', () => animate(element, { scale: 1.1, duration: 0.3, ease: 'outQuad' }));
element.addEventListener('mouseleave', () => animate(element, { scale: 1, duration: 0.3, ease: 'outQuad' }));

顺序时间线

const tl = createTimeline({ defaults: { duration: 0.5 } });
tl.add('.step1', { x: 100 })
  .add('.step2', { y: 100 })
  .add('.step3', { scale: 2 });

滚动触发动画

import { createScrollObserver } from 'animejs';

createScrollObserver({
  target: '.scroll-element',
  root: document.querySelector('.scroll-container'),
  play: () => animate('.element', { x: 250, duration: 1 }),
  visibility: 0.5
});

高级功能

SVG 动画

import { animate, svg } from 'animejs';

// 路径变形(单行)
animate('#path1', { d: svg.morphTo('#path2'), duration: 1 });

// 绘制 SVG 线条
const drawable = svg.createDrawable('.svg-path');
animate(drawable, { draw: '0% 100%', duration: 2 });

// 运动路径(简单用法单行)
const motionPath = svg.createMotionPath('#motion-path');
animate('.element', { x: motionPath.translateX, y: motionPath.translateY, rotate: motionPath.rotate });

工具函数

import { utils } from 'animejs';

// DOM 选择
const elements = utils.$('.elements');

// 获取当前值
const currentX = utils.get('.element', 'translateX');

// 立即设置值
utils.set('.element', { x: 100, opacity: 0.5 });

// 移除动画
utils.remove('.element');

// 数学工具
utils.random(0, 100);
utils.shuffle([1, 2, 3, 4]);
utils.lerp(0, 100, 0.5); // 50
utils.clamp(150, 0, 100); // 100

性能提示

  1. 使用变换属性而非位置属性

    // 好 - 使用 transform
    animate('.element', { x: 100 });
    
    // 差 - 触发重排
    animate('.element', { left: 100 });
    
  2. 将动画批量放入时间线

    // 好 - 单个时间线
    const tl = createTimeline();
    elements.forEach(el => tl.add(el, { x: 100 }));
    
    // 差 - 多个独立动画
    elements.forEach(el => animate(el, { x: 100 }));
    
  3. 对复杂动画使用 will-change CSS 属性

    .animated-element {
      will-change: transform, opacity;
    }
    

AI 代码生成规则

生成 anime.js 动画代码时:

  1. 在应用主入口文件设置 engine.timeUnit = 's'(绝不在组件中)
  2. 始终使用秒作为时长单位(1 = 1秒)
  3. 始终将简单动画写在一行
  4. 始终使用 v4 导入方式
  5. 绝不使用 anime() 函数
  6. 始终使用 animate() 做动画
  7. 绝不使用 targets 属性
  8. 始终使用 ease 而非 easing
  9. 绝不使用 value,改用 to
  10. 始终给回调加 on 前缀
  11. 绝不使用 direction,改用 alternatereversed
  12. 始终使用 createTimeline() 创建时间线
  13. 优先使用简写(x)而非完整写法(translateX
  14. 格式化短动画为单行(4个属性以内)
  15. 绝不在任何情况下生成 v3 语法

相关技能 Related Skills