CSSで行間を広げない見栄えの良いルビと圏点を作る(そしてHugoでショートコードにまとめる)
活版印刷、植字大好きー! <ruby>
タグ大好きー!
ルビ。それは活字の8Qサイズを語源とする振り仮名のこと。漢字の読み方を教え、海外小説のニュアンスをできるだけ崩さずに表現し、時に厨二病な演出を可能にする、日本語には欠かせない文章表現の一つです。
悲しいかなHTML及びCSSにおける<ruby>
タグの扱いはとってもぞんざい。ルビの位置が上か下かを設定するruby-positionと、単語と読みの長さが異なる場合のレイアウトを決定するruby-alignが存在しますが、そもそも実験的な機能という位置づけらしく、2020年2月現在、Firefoxぐらいでしかサポートされていません。モノルビ設定もなければ、1-2-1ルールも均等アキも当然なく、それどころかルビのサイズや位置すら気軽に設定できないのが現状です。
Can I use... Support tables for HTML5, CSS3, etc
https://caniuse.com/#search=ruby-position
そもそも、ルビって日本語以外にあるんでしょうか?
英語ではHTMLやCSS、最近ではあまり聞くことのなくなったWYSIWYGなどのように、頭文字を使った略語(イニシャリズム、アクロニム)が広く使われていますが、それらに日本語のようなルビをふる文化はなく、正式名称を示したい場合は後ろに書くのが普通です。HTMLタグとしても<acronym>
、<abbr>
がありますが、一般にはバルーンチップとして表示されるだけです。さらに前者はHTML5で廃止されました。
ではアジア言語圏はと言うと、中国語は漢字だけですが、読み方を示すために発音記号“ピンイン”を漢字の上に置くことがあるようです。でもピンインはあくまで発音記号、日本語のように単独でも使用できる文字であるひらがなを使ったルビとは少し趣《おもむき》が異なる気がします(日本語が表音文字と表意文字を併用する特殊な言語というのもあります)。
中国語における「ルビ」について
https://moromoro.jp/morosiki/resources/chinese_ruby/
台湾語も同様に発音記号をふることがあるみたいなんですが、“ボポモフォ”と言うらしいです。字面が可愛いですね。
韓国語なんかはどうなんでしょう? 漢字を使うので読めない場合はルビを振ると思いますが、そもそも漢字の使用頻度が日本語ほど高くないと聞きます。
日本語の文章表現には欠かせないルビ
一方で日本語はやたらルビを使います。一つの漢字に音読みと訓読みがあるのが基本ですし、当て字という文化もあって知らない限り読めない単語も多いです。人の名前も当て字が殆ど。個人情報の入力フォームに必ず「ふりがな」が存在する国って日本以外にあるのでしょうか?
活字の分野では表現手法として使われるルビが発達しています。ファンタジーやSFでは「この世界《ミドルアース》では……」というように関係代名詞に固有名詞を当てる表現は一般的ですし、アルファベットなどの文字そのものが重要な言葉は表記そのままに翻訳をルビで乗せたり、“凝り性”《アーティスト》のように一般名詞や固有名詞に異なるニュアンスを与えるといった役割もこなします。もともとは海外小説の翻訳からの流れなのでしょうか。本格推理《ミステリ》に出てくる[〇〇荘]なんかは大抵漢字にカタカナが振られていましたし、SF小説の『ニューロマンサー (1984)』なんかルビだらけだった印象です。
いわゆる厨二病なジャンルの小説にもルビは欠かせないですよね。奈須きのことか……(ルビだらけでそれらに意味もなくひたすら読みづらいという印象しかないですが)あとは代表的なところで「不運《ハードラック》と踊《ダンス》っちまったんだよ……」とかw
閑話休題《話を戻しましょう》。
<ruby>
タグ
素直にHTMLの<ruby>
タグでルビを振ってしまうと、位置の調整ができず、行間も広がってしまいます。下記の例では、ルビのある行間のみ広がっていて、さらにルビの長さに合わせて字間も取られているのがわかります。
Chromeによるレンダリング
HTML
そうして私たちはお互に恋し合い、数週間後に結婚したんです。――ところで私自身はホップの<ruby>卸商<rt>おろししょう</rt></ruby>です。私は年に七八百<ruby>磅<rt>ポンド</rt></ruby>の収入がありますから、私たちは別に不自由はしておりません。
CSS
body
{
line-height: 100%;
text-align: justify;
}
(参考)お使いのブラウザでの表示
そうして私たちはお互に恋し合い、数週間後に結婚したんです。――ところで私自身はホップの卸商です。私は年に七八百磅の収入がありますから、私たちは別に不自由はしておりません。
- 上記は
<ruby>
タグと<rt>
タグそれぞれにall: revart
スタイルを指定しています。
そうして私たちはお互に恋し合い、数週間後に結婚したんです。――ところで私自身はホップの卸商です。私は年に七八百磅の収入がありますから、私たちは別に不自由はしておりません。コナンドイル Conan Doyle 三上於莵吉訳 黄色な顔 THE YELLOW FACE
CSSの疑似要素を使って改善
CSSでデザイン調整可能なルビ - Qiita
https://qiita.com/myzkyy/items/5f735808b45ba8dbf588#%E6%99%AE%E9%80%9A%E3%81%AE%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
今度は、上記サイトを参考にさせていただき、CSSの疑似要素を使って見た目を改善したものです。わかりやすいようルビの範囲に背景色を付けていますが、行間はルビが入る前提で全体的に広く取った上で、そこに綺麗にルビが収まっている事がわかると思います。ポイントはHTML5のカスタムデータ属性を使うことで、<ruby>
タグの構造はしっかり維持出来ているという事です。
Chromeによるレンダリング
HTML
そうして私たちはお互に恋し合い、数週間後に結婚したんです。――ところで私自身はホップの<ruby data-ruby="おろししょう">卸商<rt>おろししょう</rt></ruby>です。私は年に七八百<ruby data-ruby="ポンド">磅<rt>ポンド</rt></ruby>の収入がありますから、私たちは別に不自由はしておりません。
CSS
body
{
line-height: 160%;
text-align: justify;
}
ruby[data-ruby]
{
position: relative;
}
ruby[data-ruby]::before
{
content: attr(data-ruby);
position: absolute;
line-height: 100%;
text-align: center;
left: -3em;
right: -3em;
transform-origin: bottom center;
/* ルビの文字サイズを親文字に対する比率で指定 */
transform: scale(0.5);
/* 100%を越える部分が親文字とルビとのスペースになる。単位は親文字に対する比率 */
bottom: 105%;
/* デバッグ用 */
background-color: rgba(255, 0, 0, 0.2);
}
ruby[data-ruby] rt
{
display: none;
}
(参考)お使いのブラウザでの表示
そうして私たちはお互に恋し合い、数週間後に結婚したんです。――ところで私自身はホップの卸商です。私は年に七八百磅の収入がありますから、私たちは別に不自由はしておりません。
なお、ルビのサイズ指定をわかりやすくするために、参考サイトから少しだけプロパティを変えました。具体的には……
- 親要素に指定した行間160%が継承されてしまうので、ルビの方では
line-height: 100%
を指定して打ち消し。 - ルビの文字サイズを
font-size
で指定すると、疑似要素全体としての大きさは親要素の文字の大きさを継承したまま、文字だけが小さくなってしまい、位置の指定がわかりづらくなるので、transform
プロパティを使って要素全体を縮小。 - さらに
transform-origin
はbottom
とし、親文字と下端を一旦《いったん》揃えてからbottom
で上に移動することで、親文字のサイズを基準とした値でルビのオフセットを指定できるように。
100%で親文字上端ぴったり、100%を超える部分がルビ下端から親文字上端のスペースになります。 - 上記の変更を加えた結果、ルビの字数が親文字の字数を越えると折り返されてしまうようになったので、
left
とright
にマイナス値を指定して長いルビも表示できるように。(親文字の字数+両方のemの絶対値の合計)がほぼそのまま表示できるルビの字数になります。
Hugoのショートコードにまとめる
これで見た目はなんとかなったものの、ただでさえ書くのが面倒なタグである<ruby>
がさらに冗長になってしまったので、ショートコードにまとめました。規則的な書き方のHTMLはなんでもショートコードにまとめてしまえるのがHugoの良いところ。
layouts/shortcodes/ruby.html
<ruby data-ruby="{{.Get 0}}">{{.Inner}}<rt>{{.Get 0}}</rt></ruby>
使う時は{{<ruby "おろししょう">}}卸商{{</ruby>}}
みたいに書けば先程のHTMLのように書き出してくれます。
圏点《けんてん》、傍点《ぼうてん》
もう一つ、ルビほど多用はされませんが、重要な活字表現として圏点(または傍点ないし脇点《わきてん》、いずれも同じもの)があります。単純に文章を強調する以外にも、ひらがなが連続して分かりづらい場合に文節の区切りを示して読みやすくするのにも使われます。ミステリファンとしては、盲点だった重要な事実に傍点が振られていたりするともう大興奮です。
これもルビと同じレイアウトで実現できるので、読み仮名の代わりに●や﹅を小さめのフォントサイズで使い、一文字ずつ前述のルビタグで囲めば綺麗に実現できます。
(参考)お使いのブラウザでの表示
「あなたが犯人ではありませんね、山田さん」
ただ、何しろ一文字ずつタグで囲まなきゃいけないというのが作業として大変辛いですね。そこでまたHugoの出番。ショートコードを使うことで、一文字ずつタグで囲む手間のかかる作業もおまかせできちゃいます! ショートコード便利!
layouts/shortcodes/kenten.html
{{range findRE ".{1}" .Inner}}<span class="kenten" data-symbol="●">{{.}}</span>{{end}}
上記では、ショートコードの内部にあるテキストをHugoのfindRE
関数で一文字ずつに分解したあと、range
を使ってそれぞれHTMLタグで囲んでいます。
書く時
「あなたが{{<kenten>}}犯人ではありません{{</kenten>}}
ね、山田さん」
出力してくれる時
「あなたが<span class="kenten" data-symbol="●">犯</span><span class="kenten" data-symbol="●">人</span><span class="kenten" data-symbol="●">で</span><span class="kenten" data-symbol="●">は</span><span class="kenten" data-symbol="●">あ</span><span class="kenten" data-symbol="●">り</span><span class="kenten" data-symbol="●">ま</span><span class="kenten" data-symbol="●">せ</span><span class="kenten" data-symbol="●">ん</span>ね、山田さん」
このHTMLを手で書くとなると相当に手間ですが、上のショートコードぐらいなら普通に使えますね!
ほんとはCSSが標準でInDesign並みにルビの見た目をいじれるようになってればいいんですけど、まあ未だにChromeですらサポートされてないruby関連プロパティが今後使えるようになるとは思えないし、そもそもその2つのプロパティがサポートされたところで美しい組版には程遠いしで、CSSで強引に再現するしか無いというお話と、Hugoのショートコードは便利だなぁというお話でした。
あ、「いじれるようになってれば」に打った圏点に意味はないです。でもまあこのようにひらがなが続く文章で読みやすくするためにも使われたりしますね、圏点。好きです。
この記事はここで終わりです。
読んでいただきありがとうございました。
良かったらシェアしてね!
That's all for this article. Thank you for your reading.
Please share this if you like it!