mizusame

上付き文字 sup と下付き文字 sub を正しく表示させる

ブログで上付き文字 sup や下付き文字 sub を使うと、場合によって正しく表示されないことがありました。本記事ではその原因と解決方法について述べていきます。

アイキャッチ

上付きにも下付きにもならないことがあった

ある日、上付き文字(superscript)や下付き文字(subscript)をブログで表示させる方法を調べていると、自分の想定する用途だと HTML タグの supsub を使えばいいことがわかりました。

どっちも存在をおぼろげに知っていたものの、どういう用途で使うのかわからなかったタグです。おそるおそるテストブログで使ってみると、以下のようにちゃんと上付きや下付きで表示されました。

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>

この時点で目的は達成できたのですが、ふと、他のテーマではどう表示されるのか気になりました。試しにテストブログに別のテーマを適用させてみると以下のように表示されました(状況再現のために supsub の代わりに 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行目で要素のベースライン(基準線)が親要素のベースラインに揃えられています。この記述が原因で、supsub が通常の文字と同じように表示されてしまったわけです。

sup と sub に対しての各ブラウザの user agent stylesheet

主要ブラウザである Chrome, Safari, Firefox, Edge の supsub における user agent stylesheet を調べたところ、どのブラウザでも以下のように記述されていました。

sub {
  vertical-align: sub;
  font-size: smaller
}
sup {
  vertical-align: super;
  font-size: smaller
}

vertical-alignsub にすると下付きの位置に、super にすると上付きの位置に文字を移動できます。

また、font-sizesmaller を指定することで、文字サイズを親要素よりも 1 段階小さくしています。下記のリンク先によると、文字サイズが 1 段階上がるごとに 1.2 倍になるとのことなので、smaller の場合はその逆数の 1/1.2 = 0.83333... ≒ 0.83 倍です。

sup と sub を正しく表示させる CSS

ここまでの内容を踏まえ、リセット CSS で打ち消された supsub をちゃんと上付きや下付きにさせる CSS について考えてみます。

まず手っ取り早く表示させるなら、前項でも紹介した、主要ブラウザの user agent stylesheet に採用されているこちらを使うのがいいでしょう。

sub {
  vertical-align: sub;
  font-size: smaller
}
sup {
  vertical-align: super;
  font-size: smaller
}

個人的には font-sizesmaller(親要素の文字サイズの約 0.83 倍)だと少し大きめに感じるので、.75em75% くらいがちょうどいいかなと思います。

ただし、上記の CSS には少し厄介な問題があります。supsub が上下にはみ出ることで、行間 line-height がずれてしまうのです。

これを防ぐための方法はいくつかありますが、ここでは、リセット CSS Destyle.csssupsub に関わる 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: relativesupsub が相対的な位置をとるよう設定します。subbottom で下方向に、suptop で上方向に位置をずらすことで、デフォルトの行間に影響を与えずに上付き文字、下付き文字を使うことができます。

ちなみに、相対位置を em(現在のフォントサイズが基準)ではなく ex(小文字の x の高さが基準)で指定する場合もあるようです。

あとがき

supsub を使った文字が正しく表示されないことがあったため調査してみると、ブログのテーマで使用されていたリセット CSS が原因であることがわかりました。また、各ブラウザの user agent stylesheet や別のリセット CSS などを参考にし、正しく上付き・下付きになるような CSS を紹介しました。

便利なものとして認識していたリセット CSS が、こうして HTML の表示に悪影響を与えてしまうこともあるのだと学びました。記述内容をちゃんと理解しないで闇雲に使ってはいけませんね。

最後に念のため言っておくと、じゃあ HTML5 Doctor Reset CSS が劣っていて、Destyle.css が優れているという話では全然ありません!! どちらにもメリット・デメリットはあると思うので、それを踏まえたうえで自分好みのリセット CSS を使うのがおすすめです。

    編集
    ホーム