<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans">
<title>ruuo</title>
<subtitle>ruuo 的个人站点。</subtitle>
<link rel="alternate" type="text/html" href="https://ruuo.de/"/>
<link rel="self" type="application/atom+xml" href="https://ruuo.de/feed.xml"/>
<id>https://ruuo.de/</id>
<updated>2026-08-16T16:00:00Z</updated>
<author><name>ruuo</name><uri>https://ruuo.de</uri></author>
<entry>
<title>少写一点</title>
<link rel="alternate" type="text/html" href="https://ruuo.de/posts/on-writing-less/"/>
<id>https://ruuo.de/posts/on-writing-less/</id>
<published>2026-08-16T16:00:00Z</published>
<updated>2026-08-16T16:00:00Z</updated>
<summary>写得少不是产量问题，是筛选问题。真正值得写下来的事情，本来就不多。</summary>
<category term="随笔"/>
<content type="html">&lt;p&gt;更新频率是个陷阱。&lt;/p&gt;
&lt;p&gt;一旦开始按周或者按月给自己派任务，写作的驱动力就从“这件事想清楚了”变成了“这周该发了”。前者产出的东西有密度，后者产出的东西有字数。&lt;/p&gt;
&lt;p&gt;问题在于，只有作者本人能分辨这两者的区别。读者看到的都是一篇文章，标题一样体面，段落一样整齐。差别要读到第三段才显出来——想清楚了的那篇会持续给出新信息，凑数的那篇在原地重复第一段已经说完的话。&lt;/p&gt;
&lt;div class=&quot;callout callout-pull&quot;&gt;
&lt;p&gt;写得慢不是因为敲字慢，是因为想清楚一件事本来就慢。&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;值得写下来的事情有个粗糙的判据：&lt;strong&gt;你能不能说出一句别人没说过的话&lt;/strong&gt;。不是观点更激进，也不是措辞更漂亮，而是确实提供了一个新的角度或者一条新的信息。&lt;/p&gt;
&lt;p&gt;按这个标准筛，大部分选题会被筛掉。这是正常的。一年里真正想明白的事情，本来也就那么几件。&lt;/p&gt;
&lt;p&gt;剩下的时间不写，不是浪费。是在攒。&lt;/p&gt;
</content>
</entry>
<entry>
<title>为什么这个博客没有用现成的生成器</title>
<link rel="alternate" type="text/html" href="https://ruuo.de/posts/building-this-site/"/>
<id>https://ruuo.de/posts/building-this-site/</id>
<published>2026-08-15T16:00:00Z</published>
<updated>2026-08-15T16:00:00Z</updated>
<summary>现成的静态站点生成器足够好，但它们都不解决中文排版和字体体积这两个问题。这篇记录从零写一套的取舍过程。</summary>
<category term="工程"/>
<category term="排版"/>
<content type="html">&lt;p&gt;选择自己写一套静态站点生成器，通常是个坏决定。Hugo、Astro、Eleventy 都成熟、快、生态完整，而自己写的那套永远缺功能、有 bug、只有一个用户。&lt;/p&gt;
&lt;p&gt;所以值得先说清楚：什么情况下这个坏决定会变成对的。&lt;/p&gt;
&lt;h2 id=&quot;现成方案不解决的两件事&quot;&gt;现成方案不解决的两件事&lt;a class=&quot;hlink&quot; href=&quot;#现成方案不解决的两件事&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;第一件是中文排版。&lt;/strong&gt; 主流生成器的排版能力围绕拉丁文字构建。中西文间距、标点挤压、着重号、避头尾——这些要么没有，要么依赖运行时的 JavaScript 在页面加载后再改一遍 DOM。后者意味着读者会先看到没处理过的版面，然后眼睁睁看着文字跳动一次。&lt;/p&gt;
&lt;p&gt;这类工作本该在构建期完成。文章内容是静态的，处理结果也是静态的，没有任何理由推迟到读者的浏览器里做。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二件是中文字体。&lt;/strong&gt; 思源黑体覆盖三万余字，原始文件接近 17 MB。这个体积不可能直接上生产。&lt;/p&gt;
&lt;p&gt;通行的做法是按 Unicode 区段切成上百个分片，浏览器按需下载。这是个聪明的方案，但它把字体托管绑定到了特定的 CDN 上。&lt;/p&gt;
&lt;p&gt;另一条路是：既然文章内容在构建时就完全确定，那么全站到底用到哪些字也完全确定。只把这些字打进字体文件即可。&lt;/p&gt;
&lt;figure class=&quot;code&quot; data-lang=&quot;python&quot; data-lines=&quot;7&quot;&gt;&lt;figcaption class=&quot;code-head&quot;&gt;&lt;span class=&quot;code-title&quot;&gt;按用字子集化&lt;/span&gt;&lt;span class=&quot;code-lang&quot;&gt;Python&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt;&lt;span class=&quot;t-n&quot;&gt;used&lt;/span&gt; &lt;span class=&quot;t-o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;t-nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;t-k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;t-n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;t-ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;t-n&quot;&gt;rendered_pages&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;t-n&quot;&gt;used&lt;/span&gt;&lt;span class=&quot;t-o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;strip_markup&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;t-n&quot;&gt;subsetter&lt;/span&gt; &lt;span class=&quot;t-o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;t-n&quot;&gt;subset&lt;/span&gt;&lt;span class=&quot;t-o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;Subsetter&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;t-o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;t-n&quot;&gt;subsetter&lt;/span&gt;&lt;span class=&quot;t-o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;populate&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;t-o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;t-o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;t-nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;used&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;t-n&quot;&gt;subsetter&lt;/span&gt;&lt;span class=&quot;t-o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;subset&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;这套站点上的实际效果：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;字体&lt;/th&gt;
&lt;th&gt;原始&lt;/th&gt;
&lt;th&gt;子集后&lt;/th&gt;
&lt;th&gt;压缩比&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;思源黑体&lt;/td&gt;
&lt;td&gt;16.9 MB&lt;/td&gt;
&lt;td&gt;约 110 KB&lt;/td&gt;
&lt;td&gt;99.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inter&lt;/td&gt;
&lt;td&gt;859 KB&lt;/td&gt;
&lt;td&gt;约 92 KB&lt;/td&gt;
&lt;td&gt;89.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JetBrains Mono&lt;/td&gt;
&lt;td&gt;297 KB&lt;/td&gt;
&lt;td&gt;约 41 KB&lt;/td&gt;
&lt;td&gt;86.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;子集化本身不难，难的是三条不能破的底线：&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;变量轴&lt;/dt&gt;
&lt;dd&gt;子集之后 &lt;code&gt;wght&lt;/code&gt;、&lt;code&gt;opsz&lt;/code&gt; 轴必须还在。否则一套字体退化成若干静态字重，体积反而更大，也失去了大字紧、小字松的光学补偿。&lt;/dd&gt;
&lt;dt&gt;排版特性&lt;/dt&gt;
&lt;dd&gt;&lt;code&gt;palt&lt;/code&gt;、&lt;code&gt;halt&lt;/code&gt; 决定标点能否挤压，&lt;code&gt;kern&lt;/code&gt;、&lt;code&gt;calt&lt;/code&gt; 决定西文的字偶距与连字。子集化工具默认会丢掉大部分 OpenType 特性，必须显式保留。&lt;/dd&gt;
&lt;dt&gt;系统兜底&lt;/dt&gt;
&lt;dd&gt;字体栈里始终留着 &lt;code&gt;PingFang SC&lt;/code&gt;、&lt;code&gt;Microsoft YaHei&lt;/code&gt; 这一层。万一某个字没进子集，读者看到的只是字形略有出入，而不是一个方框。&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2 id=&quot;一个容易踩的坑&quot;&gt;一个容易踩的坑&lt;a class=&quot;hlink&quot; href=&quot;#一个容易踩的坑&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;子集是按用字算的，用字变了，文件内容就变了，内容指纹跟着变，缓存全部失效。也就是说，每发一篇新文章，所有回访读者都要重新下载一遍中文字体。&lt;/p&gt;
&lt;p&gt;解决办法是让字符集&lt;strong&gt;只增不减&lt;/strong&gt;：把历次构建用到的字累积记在一个账本里，删掉旧文章不会让字体缩小。&lt;/p&gt;
&lt;figure class=&quot;code&quot; data-lang=&quot;json&quot; data-lines=&quot;1&quot;&gt;&lt;figcaption class=&quot;code-head&quot;&gt;&lt;span class=&quot;code-title&quot;&gt;var/charset.json&lt;/span&gt;&lt;span class=&quot;code-lang&quot;&gt;JSON&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code class=&quot;lang-json&quot;&gt;&lt;span class=&quot;t-p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;一&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;丁&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;七&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;万&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;丈&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;三&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;上&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;下&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;不&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-s2&quot;&gt;&quot;与&quot;&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;这样文章写到二三十篇之后，新增文章几乎不会引入新字，字体指纹自然稳定下来，缓存长期有效。&lt;/p&gt;
&lt;h2 id=&quot;关于动效的克制&quot;&gt;关于动效的克制&lt;a class=&quot;hlink&quot; href=&quot;#关于动效的克制&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;页面上有几处动效：导航栏滚动时从透明变成毛玻璃，内容分节在进入视口时轻微上浮，页面之间跳转时标题会形变。&lt;/p&gt;
&lt;p&gt;它们有两个共同点。&lt;/p&gt;
&lt;p&gt;其一，全部由 CSS 完成。滚动驱动动画用的是 &lt;code&gt;animation-timeline&lt;/code&gt;，页面切换用的是 View Transitions，没有一个滚动监听器。这不只是代码量的问题——JavaScript 驱动的滚动动画会和主线程抢时间，页面一忙就掉帧，而 CSS 的滚动时间轴跑在合成器上，不受影响。&lt;/p&gt;
&lt;p&gt;其二，位移量都很小。入场上浮只有 18 像素。&lt;/p&gt;
&lt;ul class=&quot;contains-task-list&quot;&gt;
&lt;li class=&quot;task-list-item enabled&quot;&gt;&lt;input class=&quot;task-list-item-checkbox&quot; checked=&quot;checked&quot;  type=&quot;checkbox&quot;&gt; 缓动曲线用真实的阻尼弹簧解算，不用 &lt;code&gt;ease-out&lt;/code&gt;&lt;/li&gt;
&lt;li class=&quot;task-list-item enabled&quot;&gt;&lt;input class=&quot;task-list-item-checkbox&quot; checked=&quot;checked&quot;  type=&quot;checkbox&quot;&gt; 单次动效时长控制在 400 毫秒以内&lt;/li&gt;
&lt;li class=&quot;task-list-item enabled&quot;&gt;&lt;input class=&quot;task-list-item-checkbox&quot; checked=&quot;checked&quot;  type=&quot;checkbox&quot;&gt; &lt;code&gt;prefers-reduced-motion&lt;/code&gt; 下全部关闭&lt;/li&gt;
&lt;li class=&quot;task-list-item enabled&quot;&gt;&lt;input class=&quot;task-list-item-checkbox&quot;  type=&quot;checkbox&quot;&gt; 视差滚动——不打算做&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第三条不是可选项。动效在一部分人身上会引发前庭不适，这是无障碍要求，不是偏好设置。&lt;/p&gt;
&lt;h2 id=&quot;那么这个坏决定值不值&quot;&gt;那么这个坏决定值不值&lt;a class=&quot;hlink&quot; href=&quot;#那么这个坏决定值不值&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;如果目标是尽快把文章发出去，用 Hugo，半小时搞定，不要多想。&lt;/p&gt;
&lt;p&gt;如果排版本身也是想做的事情之一——那么自己写一套的理由就成立了。中西文混排、标点、着重号、字体子集，这些都不是配置项能解决的，它们要求你对内容处理的每一步都有控制权。&lt;/p&gt;
&lt;p&gt;代价是要自己维护。收益是，页面上每一处细节都是有理由的。&lt;/p&gt;
</content>
</entry>
<entry>
<title>中文网页排版里，那些一眼看不出但一直在起作用的细节</title>
<link rel="alternate" type="text/html" href="https://ruuo.de/posts/chinese-web-typography/"/>
<id>https://ruuo.de/posts/chinese-web-typography/</id>
<published>2026-08-13T16:00:00Z</published>
<updated>2026-08-13T16:00:00Z</updated>
<summary>中西文之间的那点空隙、标点该不该占满一个字宽、强调用什么形式——这些细节单看都微不足道，叠加起来却决定了一页中文的成色。</summary>
<category term="排版"/>
<category term="设计"/>
<content type="html">&lt;p&gt;一段中文读起来舒不舒服，通常不取决于用了什么字体。字体是最容易被讨论、也最容易被高估的一环。真正在起作用的，是一批读者永远不会主动注意、但只要做错就会持续制造摩擦的细节。&lt;/p&gt;
&lt;p&gt;它们的共同点是：做对了没人夸，做错了没人说得上来哪里不对，只会觉得“这个网站看着有点累”。&lt;/p&gt;
&lt;h2 id=&quot;中西文之间的那道缝&quot;&gt;中西文之间的那道缝&lt;a class=&quot;hlink&quot; href=&quot;#中西文之间的那道缝&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;汉字是方块字，字面几乎撑满字身框；拉丁字母是比例字，两侧天然带留白。这两种字挨在一起时，视觉上会挤成一团。&lt;/p&gt;
&lt;p&gt;传统排版对此有明确规定：中西文之间加约四分之一个汉字宽的空隙&lt;label class=&quot;sn-toggle&quot; for=&quot;sn-1&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot; aria-label=&quot;注释 1&quot;&gt;1&lt;/label&gt;&lt;small&gt;（这个空隙的学名很多：中西文混排间距、盘古之白、hanzi-western spacing。宽度在四分之一到八分之一汉字宽之间取值，取决于正文字号和字体的字面率。）&lt;/small&gt;。这条规则在纸质书里执行了几十年，到了网页上却大面积失传，因为它需要在文本里插入一点东西，而大多数内容管理系统不提供这个能力。&lt;/p&gt;
&lt;p&gt;常见的做法是直接插入空格字符。这解决了视觉问题，却制造了新问题：读者复制这段文字时，会带出一堆本不属于原文的空格。&lt;/p&gt;
&lt;div class=&quot;callout callout-note&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;更干净的做法&lt;/p&gt;
&lt;p&gt;不插入字符，而是插入一个宽度为零、但左右带外边距的空元素。视觉上有间距，文本内容里却什么都没多出来。复制粘贴出去的是干净的原文。&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;这个站上你现在读到的每一处中西文交界，都由构建期的一遍扫描处理过。&lt;code&gt;Claude Code&lt;/code&gt; 和 &lt;code&gt;Hugo&lt;/code&gt; 这样的词紧贴汉字时，缝隙是自动补上的——包括它们被包在链接或者行内代码里的时候，那种跨标签的接缝最容易漏掉。&lt;/p&gt;
&lt;h2 id=&quot;标点不该总是占满一个字宽&quot;&gt;标点不该总是占满一个字宽&lt;a class=&quot;hlink&quot; href=&quot;#标点不该总是占满一个字宽&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;全角标点在字体里的设计宽度是一个完整汉字。这在竖排和格稿纸时代是对的，因为每个格子必须等宽。&lt;/p&gt;
&lt;p&gt;但横排正文里，连续出现两个标点时，两个字宽的空白会在版面上撕开一个洞：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;他问：“你确定吗？”——没有人回答。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这里的 &lt;code&gt;？&lt;/code&gt;、&lt;code&gt;&amp;quot;&lt;/code&gt;、&lt;code&gt;——&lt;/code&gt; 连成一片，如果每个都占满字宽，这一行会明显比其他行松。专业排版的处理叫&lt;strong&gt;标点挤压&lt;/strong&gt;：根据前后文压缩标点的实际占位。&lt;/p&gt;
&lt;p&gt;现在的浏览器已经支持这件事，只需要一行样式：&lt;/p&gt;
&lt;figure class=&quot;code&quot; data-lang=&quot;css&quot; data-lines=&quot;3&quot;&gt;&lt;figcaption class=&quot;code-head&quot;&gt;&lt;span class=&quot;code-title&quot;&gt;正文的标点挤压&lt;/span&gt;&lt;span class=&quot;code-lang&quot;&gt;CSS&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code class=&quot;lang-css&quot;&gt;&lt;span class=&quot;t-nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;t-w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;text-spacing-trim&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;t-w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;t-n&quot;&gt;trim-start&lt;/span&gt;&lt;span class=&quot;t-p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;t-p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;对应地，还有一条&lt;strong&gt;避头尾&lt;/strong&gt;规则：句号、逗号、右引号不能出现在行首，左引号不能出现在行尾。CSS 的 &lt;code&gt;line-break: strict&lt;/code&gt; 会处理大部分情况。&lt;/p&gt;
&lt;h2 id=&quot;中文没有斜体&quot;&gt;中文没有斜体&lt;a class=&quot;hlink&quot; href=&quot;#中文没有斜体&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这是被误用得最多的一条。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; 在浏览器里默认渲染成斜体。拉丁字母有专门设计的斜体字形，笔画结构会随之改变，不只是倾斜。汉字没有。浏览器遇到中文的 &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt;，只能把正体字形做几何倾斜，结果是笔画粗细失衡、重心歪斜。&lt;/p&gt;
&lt;p&gt;中文强调的传统形式是&lt;strong&gt;着重号&lt;/strong&gt;——在字的下方（横排）或右侧（竖排）加点。国家标准里有明确规定&lt;label class=&quot;sn-toggle&quot; for=&quot;sn-2&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot; aria-label=&quot;注释 2&quot;&gt;2&lt;/label&gt;&lt;small&gt;（GB/T 15834《标点符号用法》。着重号的位置在横排时位于字的下方。）&lt;/small&gt;。&lt;/p&gt;
&lt;p&gt;问题在于，CSS 判断不了一个 &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; 里装的是汉字还是拉丁字母。所以这件事必须在生成页面的时候做：扫一遍文档结构，含中文的强调标一个记号，样式再据此分流。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;内容&lt;/th&gt;
&lt;th&gt;呈现方式&lt;/th&gt;
&lt;th&gt;原因&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;中文强调&lt;/td&gt;
&lt;td&gt;着重号&lt;/td&gt;
&lt;td&gt;汉字没有斜体设计&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;西文强调&lt;/td&gt;
&lt;td&gt;斜体&lt;/td&gt;
&lt;td&gt;有专门设计的斜体字形&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;混排强调&lt;/td&gt;
&lt;td&gt;着重号&lt;/td&gt;
&lt;td&gt;以主体文字为准&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;行长与行距&quot;&gt;行长与行距&lt;a class=&quot;hlink&quot; href=&quot;#行长与行距&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;中文的合理行长比西文短。西文常用的经验值是每行 65 到 75 个字符，换算成汉字大约是 32 到 38 个字。超过这个范围，眼睛从行尾跳回下一行行首时容易串行。&lt;/p&gt;
&lt;p&gt;行距则相反，中文需要得更多。汉字字面大、笔画密，字与字之间没有西文那样天然的疏密节奏，行距不足会让整段糊成一片。西文正文常用 1.5 到 1.6 倍，中文建议 1.75 到 1.9 倍。&lt;/p&gt;
&lt;h2 id=&quot;这些细节值多少&quot;&gt;这些细节值多少&lt;a class=&quot;hlink&quot; href=&quot;#这些细节值多少&quot; aria-label=&quot;本节链接&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;单独看，每一条都微不足道。四分之一个字宽的空隙、几个标点的挤压、强调用点还是用斜——任何一条都不足以让读者说出“这个页面排得好”。&lt;/p&gt;
&lt;p&gt;但它们是叠加的。一页中文里有几百个中西文交界、几十处标点、若干处强调。全部做对和全部不做，读完一篇长文之后的疲劳程度是能感觉出来的——尽管读者说不清原因。&lt;/p&gt;
&lt;p&gt;排版做到位的标志，从来不是被夸奖，而是被忘记。&lt;/p&gt;


</content>
</entry>
</feed>