使用 CSS 與一點魔法,在 HTML 中英文交界加入空格

更新 目前(2023-02-18)改成直接在原文章中輸入空格,因為以下描述的方法實行起來有一些難處(最明顯的就是不能避掉標點符號)。

最近開始寫中文的Public Logs,寫一寫總會去預覽一下排起來的樣子。但寫最近一篇Week 39的時候,卻越看越不對勁:為什麼中文字跟英文字之間,一點空格都沒有?身為對字體排版還算有點要求的人,這種狀況實在是令人不爽。因此我開始尋找將中英稍微隔開來的方法。

直接用CSS解決?

曾經,IE支援一個名為text-autospace的CSS設定。它的用途是指定表意文字(中日韓文)與其他語系的文字(拉丁文、西里爾文、希臘文、阿拉伯文等)中間的空格大小。在StackOverflow上也有人問過相關的問題。可惜這個設定並未被Firefox、Safari與Chrome納入,因此逐漸遭到淘汰。

目前也有人討論是否將這些設定納入w3c網頁標準規範(https://github.com/w3c/csswg-drafts/issues/6950),但目前看來沒有定論。

改幹HTML

再搜尋了ㄧ會,唯一的方法似乎剩下直接開幹HTML。我最一開始的想法是這樣子:

+–––––+———————————––+ | Markdown | 1. 取出英文區段 | | | 2. 在外圍加入<span lang="en"> | +–––––+———————————––+ | CSS | - 加入span[en]的padding規則 | +–––––+———————————––+

因此我在我的轉換腳本_(連結失效)_中將Markdown轉成HTML的部份,加入了一個sed處理:

cat "$i" | \
sed '2,${/^#/!s|\([A-Za-z0-9 :,.]*[A-Za-z0-9 :,.]\)|<span lang="en">\1</span>|g}' | \
pandoc -f markdown -t html | \
sed 's/→/→/g' >> "${i%.*}.html" \
|| err -f "Pandoc failed to convert, or sed has an error with $i";

最相關的部份是:

sed '2,${/^#/!s|\([A-Za-z0-9 :,.]*[A-Za-z0-9 :,.]\)|<span lang="en">\1</span>|g}' 

這個方法最大的問題是,它同時會抓出純英文的部份,因此讓一些其他的Markdown格式整個跑掉。

跑掉的首頁

於是我想說,能不能改抓「前面有中文字」的英文字串?查詢了一下,發現sed很難指定抓取中文字。但這個StackOverflow答案建議,處理這種可以使用perl

Perl has pretty good support for dealing with Unicode. That might be a better bet for your task than sed. This one-liner works like your first sed example:

perl -CIOED -p -e 's/\p{Script_Extensions=Han}/$& /g' filename

The -CIOED tells perl to do its I/O in utf8. -p runs the given code once for each line of the input file, then prints the result. -e specifies a line of Perl code to run. See the documentation on command-line arguments for more.

The regular expression uses named ranges to identify the characters to match.

You might also want to read the Perl Unicode documentation.

因此我把原本的sed部份改了一下,以符合perl的格式:

cat "$i" | \
    perl -CIOED -p -e 's/(\p{Script_Extensions=Han}\[?)([A-Za-z0-9 :,.]*[A-Za-z0-9 :,.])/$1<span lang="en">$2<\/span>/g' | \
    pandoc -f markdown -t html | \
    sed 's/→/→/g' >> "${i%    .*}.html" \
    || err -f "Pandoc failed to convert, or sed has an error with $i";

用這段程式可以將下列Markdown(取自Public Logs的Week 39

[ltlnx](../index.html) > [Public Logs](index.html) > **Week 39 (2022-09-25 – 2022-10-01)**

# Week 39 (2022-09-25 – 2022-10-01)

_(English readers: most parts of my public log will be in Chinese. Sorry about that.)_

### 2022-09-25
最近把一些東西重新裝回去了,例如新酷音。在=+=Slackware=+=將=+=fcitx=+=正式升級成=+=fcitx5=+=之後,
原本想說試試看先不裝新酷音,適應看看原生的行列;經過一個禮拜之後,深刻感受到這樣
是行不通的。接著又試著裝了=+=gcin=+=,卻發現在=+=Wayland=+=上跑會造成ㄧ大堆東西=+=segfault=+=。但
詞音打起來真的好舒服,比新酷音舒服太多了。真的好可惜。

一段時間沒寫這鬼東西了。還是希望自己多紀錄人生呢,也能稍微踏實一點。

轉為

[ltlnx](../index.html) > [Public Logs](index.html) > **Week 39 (2022-09-25 – 2022-10-01)**

# Week 39 (2022-09-25 – 2022-10-01)

_(English readers: most parts of my public log will be in Chinese. Sorry about that.)_

### 2022-09-25
最近把一些東西重新裝回去了,例如新酷音。在<span lang="en">Slackware</span>將<span lang="en">fcitx</span>正式升級成<span lang="en">fcitx5</span>之後,
原本想說試試看先不裝新酷音,適應看看原生的行列;經過一個禮拜之後,深刻感受到這樣
是行不通的。接著又試著裝了<span lang="en">gcin</span>,卻發現在<span lang="en">Wayland</span>上跑會造成ㄧ大堆東西<span lang="en">segfault</span>。但
詞音打起來真的好舒服,比新酷音舒服太多了。真的好可惜。

一段時間沒寫這鬼東西了。還是希望自己多紀錄人生呢,也能稍微踏實一點。

接下來只要再掛一個CSS樣式:

span[lang="en"]{padding: 0 0.25rem}

就大功告成了!結果就是現在看到的這個樣子。目前剩下的問題就是,這段程式碼還無法避開code區塊,之後可能要加寫一些規則來偵測並避開它們。

2022-10-08 更新

  1. <span>的CSS更新

    如果在span外面套padding的話,會有一個問題:如果英文字在最左邊,就會有一個多出來的左邊空格。

    “StackOverflow“字樣旁有多餘的空格

    但如果改用span[lang="en"]:before{content: " "}span[lang="en"]:after{content: " "},因為瀏覽器將空格視為文字的一部分,問題就會消失:

    改變CSS後,“StackOverflow“字樣旁的空格消失了

    問題是,如果這樣設定,標題的中英文間空隙就會太大。

    如圖

    因此我們需要一個能將字體大小「隨著原字體大小縮小,而稍微放大」的公式。使用CSS的calc(),我們可以輕鬆達到這點:如果我們用以下的對應表格

    +———————––+————————+ | 外圍字體大小 | 空格大小 | +:=======================:+:======================:+ | 1rem | 1rem | +———————––+————————+ | 2rem | 0.5rem | +———————––+————————+

    那麼我們可以推導出下列線性公式:

    font-size: calc((1em * -0.5) + 1.5rem)

    效果如下:

    空隙縮小了

    因此最終的CSS為:

    span[lang="en"]:before {content: " "; font-size: calc((1em * -0.5) + 1.5rem)}
    span[lang="en"]:after {content: " "; font-size: calc((1em * -0.5) + 1.5rem)}

Last updated: 2022-10-08

標籤:隨想

如果想讓我知道您看過這個頁面,請點擊這個連結運作原理