汉字着重号的网页实现
https://blog.csdn.net/Camot/article/details/118032229
补充:鉴于这里显示不出来,我放一些截图吧。
注意 margin-bottom
我后面改成了 -.4em
,但正文里我懒得修改了。可以看到,最终效果里行距保持了一致。
说明:本文转载自我自己的网站。部分样式可能显示得不合适,为最佳的显示效果,建议访问原文。原文的许可证是 CC-BY,原文转载的话需要备注出处。
另:本文中的一切代码(HTML 上以 <code>
标签包裹的内容)均以 Unlicense 许可证发布,可以随便用。能借由我的力量让网上多一些正规的着重号理应是我的荣幸,我怎敢再加什么限制呢?
也就是说,你如果原文转载我的文章,需要给出处;直接拿我的代码去用,甚至另外再写文章阐明用法,都不关我事。
着重号是什么?{#quid-est-signum-emphasis}
只关心技术的朋友可以跳过本节。
{.nota}
先来看看国标的说法吧。
4.12 着重号
4.12.1 定义
标号的一种,标示语段中某些重要的或需要指明的文字。
4.12.2 形式
着重号的形式是“.”,标注在相应文字的下方。
中华人民共和国国家标准标点符号用法(GB/T 15834—2011)
{.dixit}
可以认为,这对应于 HTML 中的 <em>
标签。我们知道,网页上 <em>
标签的默认样式是斜体。使用斜体作为强调是西文的排版传统,与汉字(或者说中日韩字符——但这里是中国,且允许我以“汉字”代称之吧。)的呈现并不相搭配。用人话说,就是看起来很丑。
汉字是没有斜体的。正如西文字体的“斜体”(意大利体)其实是一种与“正体”(罗马体)在形态上有一定区别的另一套字体而并非后者的简单几何变换一样1,在汉字内容的排版中地位近似于斜体的也不是只做了简单几何变换的那种(也是如今网上网下满天飞的),而是另一套与正文有一定区别的字体。在中文出版物中常见的是使用宋体(也叫明体,是一种衬线字体)作为正文字体,而使用黑体(总之是无衬线字体2)作为与西文粗体对应的字体。那么,与西文的斜体对应的是什么字体呢?至少对于中国的出版物,多是使用楷体或者仿宋体。
但是,也有不使用与正文有别的另一套字体,而使用着重号来表示一般强调的。甚至这样的情形,以我相对不少的读书经验来看,比使用独立字体的情况还要多一些。至于原因,我有一些猜测,不一定对:可能是这样可以省一些字体授权费;可能是 MS Word 类文档编辑软件可以很方便地给汉字附加着重号;可能是编辑也喜欢国标。
但是这样的样式似乎在 HTML 里有点难实现啊。为同一文档、标记为同一主要字体的不同字重(指 CSS 的 font-weight
)和字体风格(同前,font-style
)各自使用单独字体的情况可以用 CSS 3 的 @font-face
实现3(这个我过几天会写一篇文章说明我的用法,到时候链到这里),但着重号的网页实现,至少我在网上没有见到过解法。以此为关键字进行搜索,只能搜到一些用 border-bottom: 1px dashed black
之类进行粗略模拟的。然而这样的显示效果……实在有些拉跨。
身为相信 HTML 才是一切人类文档的明天、相信 HTML 代表了先进文档的发展方向的 W3C 信者,怎么能够容忍有 HTML 解决不了的排版问题呢?!……然而不支持就是不支持。但是,我们要相信,办法总比困难多,这个问题一定是可以解决的。本文就是为此而写的。
着重点的显示效果:使用 <ruby>
{#ad-rubeum}
要让着重点对齐 CJK 字符还不简单?使用现成的 ruby
元素就好。可以看看我此前记下的关于 ruby
元素用法的文章。用 CSS 做一些(chrome 还是支持得很差的)样式调整,就可以初步实现着重号的效果了。
着重号的<ruby style="ruby-position:under;">新<rt>·</rt>写<rt>˙</rt>法<rt>•</rt></ruby>
- 1
着重号的新写法
这么一横向(物理)对比,似乎是用 ˙
比较好啊。
但是这样会带来一些问题:
- 手动为字一个个这么加,是不是有点麻烦呢?
- 这些稍微有点偏门的符号,大家用的字体未必都支持,或者即使支持也不一定有比较稳定的显示效果吧。(在我的网站上效果应该还好,因为我这提供了网页字体)
- 而且这样一来,用光标圈点这部分内容的时候就会有像正常的
ruby
元素一样的表现,即光标能够圈到下面的着重点。这样不够丝滑啊。 - 我再仔细一看,这么一用,行距就变得很奇怪了。(例子我就不再举了)有没有办法修一下呢?
先解决后面几个问题。用类和伪元素吧。
ruby.underdot {
ruby-position: under;
}
ruby.underdot rt {
font-weight: bold;
margin-top: -.8em;
margin-bottom: -.2em;
}
ruby.underdot rt::after {
content: ".";
font-size: 1.4em;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
这样就只用了最常见的那个下句点了。大小和间距我也对着 MS Word 里的样式调整过,至少在我的电脑、我的浏览器(Firefox)上可以保证 99% 一致。
如此,则只需要这么写:
着重号的<ruby class="underdot">新<rt></rt>写<rt></rt>法<rt></rt></ruby><br/>
换一行看看<br/>
再换一行看看
- 1
- 2
- 3
着重号的新写法
换一行看看
再换一行看看
唔呣,甚好!(我测试了 Microsoft Edge,发现效果不太行。想必是 Chromium 内核的锅。)
样式的问题解决了。那么只剩下最后一个问题:如何方便地书写。
从底层到表层:使用 JS 进行转换 {#amabo-te-o-javascript}
要我每次都写这一大串 ruby 指定没辙。有没有什么简单的方法进行书写呢?
我第一是想到 CSS。把伪元素玩得飞起的大佬也许有办法不依靠 ruby
就解决这个问题吧,但是我既然已经依赖 ruby
来实现显示效果了,这条路看来不太现实。
那么就只剩下 JavaScript 了……
我很快想到,可以用正则表达式做替换。原理是把某个标签包裹着的所有汉字一个个都变成这样:
<ruby class="underdot">{此处应为一个汉字}<rt></rt></ruby>
- 1
好!那么就采用最接近的语义化标记 em
吧。我最终采用的是 em.cjk
。
然后我改了改之前用正则表达式解决 TeXZilla 生出来的事端时候的 JS 代码,得到以下能跑的 JS:
(function() {
var i, inner, em, ems = document.querySelectorAll('em.cjk');
for (i = 0; i < ems.length;) {
em = ems[i];
inner = em.innerHTML;
inner = inner.replace(/(.{1})/g, "<ruby class='underdot'>$1<rt></rt></ruby>");
em.innerHTML = inner;
em.outerHTML = em.innerHTML; // remove <em class="cjk"></em>
i++;
}
})();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
老样子,灵感还是来源于益辉那个 math-code.js
。
然后以 defer
方式引入到 HTML 文档里,就能跑了。(直接引跑不起来,想来是因为需要在 DOM 已经就绪之后再去调整内容。)本文中此前已经用到了一些着重号,所以例子我就不再举了。