GMT+8 CN —:— 0000 X 0000 Y 00%

2026Vibe CodingVibe Coding

CHESTER.DESIGNCHESTER.DESIGN

版式、排版系统、动效、中英两套文案,每一行 CSS 和 JS 都是我自己写的,全程在 Claude Code 里推进。做它是想知道一件事:当实现不用再转手,一个设计决定能推到多深。The layout, the type system, the motion, both sets of copy, and every line of CSS and JS. I wrote all of it, working in Claude Code. I built it to find out one thing: how far a design decision can be pushed when nobody has to hand it over to be implemented.

角色 / Role
设计 + 实现 / Design + build
实现 / Built with
Claude Code
技术 / Stack
HTML · CSS · JS · GSAP
构建 / Build
无打包器 / No bundler

一份 JSON,喂三个地方One JSON file, three places

主页的卡片和它链向的详情页最早是分开写的两份,结果 Logo 那张卡片和自己的详情页说了不一样的话。现在整个卡片区加十三个详情页都从同一份 content.json 出,加一个作品只改一处。漏字段会让构建直接失败,页面上不会安静地出现一个 undefined。The cards on the home page and the detail pages they link to were written out twice at first, which is how the Logo card ended up saying something different from its own detail page. The card block and all thirteen detail pages now come out of one content.json. Adding a project is a single edit. A missing field stops the build, so the word undefined never quietly appears on a page nobody re-reads.

对比度是量出来的The contrast numbers are measured

颜色、字号、行高、字距都来自一份 tokens.json,构建脚本据此生成 CSS 变量,同时实测八组 WCAG 对比度,任何一组不达标就非零退出。它还会核对样式表里每一个变量引用是否真的存在。引用一个不存在的变量会让整条声明静默失效,浏览器一个字都不说。写这一页的时候它抓到过一次。Colour, type size, leading and tracking all come out of one tokens.json. The build emits the CSS variables and measures eight WCAG pairs on the way through; one failure and it exits non-zero. It also checks that every variable the stylesheet references actually exists. A reference to one that does not kills the whole declaration in silence, and the browser never says a word. It caught one while this page was being written.

两种语言都在 HTML 里Both languages ship in the HTML

两种语言都写在 HTML 里,切换只改 CSS 的显隐,所以文字仍然可以选中、能被屏幕阅读器读到、能被搜索引擎索引。花时间的是排版:中文和拉丁各要一套字距、字重、行高,而这两组值必须挂在不同的层上。字距挂在行内的语言 span 上,行高必须挂在块级元素上。挂反了不报错,只是静默失效,而计算样式看起来完全正确。Both languages sit in the HTML and the toggle only flips CSS visibility, so the text stays selectable, readable to a screen reader and indexable. Typography is where the time went. Chinese and Latin each want their own tracking, weight and leading, and the two sets have to be mounted on different layers: tracking rides the inline language span, leading has to sit on the block. Mount them the other way round and nothing errors. It just silently does nothing, while the computed styles still look right.

/* tracking rides the inline language span:
   a direct hit always beats a value inherited from the block */
.hero__title [lang="zh"] { letter-spacing: var(--track-display-1-cjk); }
.hero__title [lang="en"] { letter-spacing: var(--track-display-1-latin); }

/* leading has to sit on the block: an inline span's
   line-height loses to the block's own strut and does nothing */
html[data-lang="zh"] .hero__title { line-height: var(--lh-display-1-cjk); }
html[data-lang="en"] .hero__title { line-height: var(--lh-display-1-latin); }

中文网页字体的重量What Chinese webfonts weigh

中文字体是这类站真正的体积来源。标题字先扫一遍全站用字,命中的一千一百个字符压进一片 100 KB;正文字体的两百个分片按 unicode-range 声明,浏览器只取用得到的十几片。厂商给的两个字重清单本身就有 170 KB 且阻塞渲染,按实际用字裁到 61 KB。选中文字体那一刻,这笔账就得算进去。Chinese type is where the weight in a site like this lives. The display face is subset against every character on the site; the eleven hundred in use fit into one 100 KB slice. The body face ships as two hundred slices declared by unicode-range, so the browser fetches only the dozen it needs. The vendor's own manifests for two weights come to 170 KB of render-blocking CSS, trimmed here to 61 KB against the real copy. That bill comes due the moment you choose a Chinese typeface.

01 / 07首屏:五秒入场影片满屏铺开,播完停在尾帧The opening — a five-second clip at full bleed, holding on its last frame
02 / 07作品区:一条循环的带子,七类筛选,指针停在卡片上就暂停Work — one looping band, seven filters, pausing wherever the pointer rests on a card
03 / 07十六秒走完全站:首屏 → 工具 → 作品 → 经历 → 关于我The whole site in sixteen seconds: opening, tools, work, career, about
04 / 07经历区:sticky 舞台加一层星场,四段随滚动切换Career — a sticky stage over a warp field, four passages driven by scroll
05 / 07关于我:满幅循环影片,正文的对比度靠一层横向压暗买回来About — a full-bleed loop, the body copy's contrast bought back by one horizontal scrim
06 / 07同一屏的英文版:字距、行高、断行各走一套参数The same screen in English: its own tracking, leading and line breaks
07 / 07设计系统:tokens.json 生成变量表,也生成这张对照页The design system — tokens.json emits the CSS variables and this reference sheet with them