HTML+CSSでaとかcodeとかの前後に空白を入れつつ、段落の左端を揃える

カテゴリ: css

日本語の場合、単語の間にスペースを入れないため、リンクコードと平文が地続きになりがちです。ちょっと空白を入れたい時は以下のようなCSSが活躍します。

リンクを例にとってみましょう。

p a::before,
p a::after {
  content: " "; 
  font-size: 0;
  word-spacing: 1rem;
}

リンクの前後に余白ではなく空白(半角スペース)を使うところがミソです。また、ここではあえて大袈裟に1remの空白を入れて、以下の例でわかりやすくしています。

メリット

  1. 空白の大きさをword-spacingで調整可能
    • font-size: 0にしているところがポイント。空白の大きさは半角スペースの幅+word-spacing
  2. 段落の頭や折り返し、強制改行で段落の左端にa要素が来ても、禁則処理で行頭のスペースは消える
  3. <a>要素が2連続してもwhite-space: normal(既定値)で空白の幅は倍にならない

<p>
<a>あいうえお</a>かきくけこ<br>
<a>さしすせそ</a><a>たちつてと</a>
</p>

あいうえおかきくけこ
さしすせそたちつてと

デメリット

メリット3点目のwhite-space: normalは時に悪さもします。

  1. HTMLファイル内で<a>要素の直前で改行すると、通常の半角スペース扱いになる
  2. 英文内など<a>要素の前後に明示的に半角スペースを挿入した場合、左側は半角スペースの幅、右側はword-spacingの幅になる

ちなみに1については<a>とか<code>とか関係なしに、 white-space: normalな状態でソース上で改行すると半角スペース1つ入ります。日本語の途中に半角スペースが入ると気持ち悪いので避けるか、対策が必要です。

「そ」と「た」の間、「efg」の前後に注目です。

<p>
あいうえお<a>かきくけこ</a>さしすせそ
<a>たちつてと</a>abcd <a>efg</a> hijk
</p>

あいうえおかきくけこさしすせそ たちつてと abcd efg hijk

デメリット対策

  1. 改行問題はコメントで繋ぐ by Tomoyaさん
  2. 和英の不整合は
    1. lang属性などを使ってルールの適用範囲をコントロールする
    2. 空白のサイズ調整を諦めて、半角スペースの挿入に留める css p a::before, p a::after {content: " ";}

ここでは和英の不整合をlang属性で回避してみます。 a要素とlang属性が隣接する場合のルールも追加してもよさそうですね。

<style>
:lang(en) a::before,
:lang(en) a::after {
  content: none;
}
</style>

<p>
あいうえお<a>かきくけこ</a>さしすせそ<!--
--><a>たちつてと</a><span lang="en">abcd <a>efg</a> hijk</span>
</p>

あいうえおかきくけこさしすせそたちつてとabcd efg hijk

他のアイディア

  • アリ
  • ナシ
    • CSSのmarginで頑張る
      • marginは相殺するので、<a>要素同士が並んでもいたずらに余白が広がらない
      • 一方で段落の頭や折り返した頭など、段落左端に<a>要素が来た時の例外処理が難しい
        • first-letterfirst-childなどで段落頭のmargin制御がせいぜい
    • CSSのpaddingで頑張る
      • paddingは相殺しない上に、marginと同じく左端が揃わない。

終わりに

元ネタは、vim-jpのslackemacs-jpのウェブページのスタイルを改善したいという質問とそれに続く議論です。禁則処理のような、普段意識しない黒魔術もといテクニックを駆使したため、エッジケースを踏みまくりました。皆さんで議論したおかげで記事化前に実装の穴を突けたとも言えます。この場をお借りしてお礼申し上げます。

たのしかったぞー!

ちなみに私はHTMLをもっぱらPandoc’s markdownから出力する派であり、east_asian_line_breaksエクステンションにより、改行時の空白に悩まされずに澄んでいます。