ブログで上付き文字 sup や下付き文字 sub を使うと、場合によって正しく表示されないことがあった。本記事ではその原因と解決方法について述べていく。
この記事の目次
上付きにも下付きにもならないことがあった
ある日、上付き文字(superscript)や下付き文字(subscript)をブログで表示させる方法を調べていると、自分の想定する用途だと HTML タグの sup と sub を使えばいいことがわかった。
- <sup>: 上付き文字要素 - HTML: HyperText Markup Language | MDN
- <sub>: 下付き文字要素 - HTML: HyperText Markup Language | MDN
どっちも存在をおぼろげに知っていたものの、どういう用途で使うのかわからなかったタグだ。おそるおそるテストブログで使ってみると、以下のようにちゃんと上付きや下付きで表示された。
Cr2O72- + 14H+ + 6e- → Cr3+ + 7H2O
<p>Cr<sub>2</sub>O<sub>7</sub><sup>2-</sup> + 14H<sup>+</sup> + 6e<sup>-</sup> → Cr<sup>3+</sup> + 7H<sub>2</sub>O</p>
この時点で目的は達成できたが、ふと、他のテーマではどう表示されるのか気になった。試しにテストブログに別のテーマを適用させてみると以下のように表示された(状況再現のために sup と sub の代わりに span を使用)。
Cr2O72- + 14H+ + 6e- → Cr3+ + 7H2O
ちゃんとタグを使ったはずなのに上付きにも下付きにもならず、文字サイズも通常の文字と同じように表示されてしまった。なんで?
犯人はリセット CSS
CSS が原因だと検討がついたので、上付きにも下付きにもならなかったほうのテーマのソースコード内を「sup」で検索すると、テーマの CSS の中に以下のような記述を見つけた。なお、コードの一部を省略、整形済み。
[前略], sub, summary, sup, [中略] {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent
}
上記のコードはいわゆるリセット CSS と呼ばれるものの一部。リセット CSS とは、ブラウザ固有のデフォルト CSS である user agent stylesheet を打ち消してブラウザ間の表示を揃えるための CSS のことを指す。
他の箇所の記述も照らし合わせたところ、このテーマでは HTML5 Doctor Reset CSS をベースとしたリセット CSS を採用していることが判明した。
上に示した CSS の中で特に注目したいのが以下の 2 行だ。
font-size: 100%;
vertical-align: baseline;
1 行目で通常の文字と同じ文字サイズに変更され、2 行目で要素のベースライン(基準線)が親要素のベースラインに揃えられいる。この記述が原因で、sup と sub が通常の文字と同じように表示されてしまったというわけだ。
各ブラウザの sup と sub における user agent stylesheet
主要ブラウザである Chrome, Safari, Firefox, Edge の sup と sub における user agent stylesheet を調べたところ、どのブラウザでも以下のように記述されていた。
sub {
vertical-align: sub;
font-size: smaller
}
sup {
vertical-align: super;
font-size: smaller
}
- Chrome:Source/core/css/html.css - chromium/blink - Git at Google
- Safari:webkit/trunk/Source/WebCore/css の html.css – WebKit
- Firefox:html.css - mozsearch
- Edge:公式文書が見つからなかったため、Windows 版のバージョン 112.0.1722.58 で検証
vertical-align を sub にすると下付きの位置に、super にすると上付きの位置に文字を移動できる。
また、font-size: smaller を指定することで、親要素より 1 段階小さいサイズへ変換される。実際にこの CSS を Chrome で検証すると、親要素が 16 px の場合、sup , sub ともに 13.3333 px となったため、文字サイズが親要素の 5/6 倍(約 83.3 %)になることがわかった。
sup と sub を正しく表示させる CSS
ここまでの内容を踏まえ、リセット CSS でスタイルが打ち消された sup と sub をちゃんと上付きや下付きにさせる CSS について考えてみる。
手っ取り早く表示させるなら、前述の主要ブラウザの user agent stylesheet をそのまま使うのがいちばん手軽だ。
sub {
vertical-align: sub;
font-size: smaller
}
sup {
vertical-align: super;
font-size: smaller
}
ただ個人的には、font-size が smaller(親要素の文字サイズの約 0.83 倍)だと少し大きめに感じるので、.75em や 75% くらいがちょうどいいかなと思う。
さらに、上記の CSS には少し厄介な問題がある。sup と sub が上下にはみ出すことで、周囲の行間 line-height がずれてしまうのだ。
この行間の崩れを防ぐ方法はいくつかあるが、ここではリセット CSS の Destyle.css で使われているコードを紹介する。
/*! destyle.css v4.0.0 | MIT License | https://github.com/nicolas-cusan/destyle.css */
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline
}
sub {
bottom: -.25em
}
sup {
top: -.5em
}
vertical-align: baseline で文字の垂直方向の位置をベースラインに揃え、position: relative で sup と sub が相対的な位置をとるよう設定する。sub を bottom で下方向に、sup を top で上方向に位置をずらすことで、デフォルトの行間に影響を与えずに上付き文字、下付き文字を使うことができる。
ちなみに、相対位置を em(現在の文字サイズ基準)ではなく ex(小文字 x の高さ基準)で指定する場合もあるようだ。
あとがき
sup と sub を使った文字が正しく表示されないことがあったため調査してみると、ブログのテーマで使用されていたリセット CSS が原因だとわかった。それを踏まえ、各ブラウザの user agent stylesheet や別のリセット CSS などを参考にしながら、正しく上付き・下付きになるような CSS を紹介した。
便利だと思って使っていたリセット CSS が、意図しない表示崩れを招くことを学んだ。記述内容をちゃんと理解しないまま闇雲に使うのはよろしくないな。
最後に補足しておくと、じゃあ HTML5 Doctor Reset CSS が劣っていて、Destyle.css が優れているという話では全然ない。どんなものにもメリット・デメリットはつきものなので、それを理解したうえで自分好みのリセット CSS を使うのがいちばんだと思う。