CSSでの文字縁取りを考える 前編 文字縁取りの基本
文字の縁取りは、CSSでは意外と悩みがちです。太さを変えると文字が潰れたり、ブラウザごとに見え方が違ったり。この記事では縁取り文字を安定して制御する考え方と実践的な表現テクニックを整理します。
はじめに
「縁取り文字」をCSSで表現したことはありますか? もしかすると、いくつかのプロパティを思いつく方もいるかもしれません。ただ、一見シンプルそうでいて、単にプロパティを指定しただけでは、太さや可読性、ブラウザ差などをコントロールできないことがあります。実は、意外と実装に悩むケースも多いのです。
この記事では、そのような細かい落とし穴を避ける方法を示しつつ、最終的に-webkit-text-strokeとpaint-orderプロパティの組み合わせを使って「縁取り文字」をつくる方法を紹介します。
なお、このシリーズで紹介するデモは、次のリポジトリにまとまっています。併せて参照してください。
「CSSでの文字の縁取りを考える」シリーズ リポジトリ
-webkit-text-strokeプロパティ
文字縁取り用のCSSプロパティには、-webkit-text-strokeがあります。このプロパティを使うと、文字に縁取り効果を簡単に追加できます。
-webkit-text-strokeは、テキストの縁に線を描画するためのプロパティで、-webkit-text-stroke: <幅> <色>;のように指定します。
構文
-webkit-text-stroke: <幅> <色>;たとえば、-webkit-text-stroke: 2px blackとすると、文字に2ピクセル幅の黒い縁取りが追加されます。
「-webkit-」という接頭辞がつきますが、Firefoxでも「-webkit-text-stroke」の名前のままサポートされているため、主要なブラウザすべてで利用可能です。
補足:Firefoxでの-webkit-サポート
過去に、多数のWebサイトでwebkit接頭辞のCSSを利用されたため、Firefoxではうまく表示されないケースがありました。表示の互換性が向上するため、Firefox 49以降では-webkit-接頭辞付きプロパティのサポートが追加されました。
-webkit-text-strokeプロパティの問題点
-webkit-text-stroke自体は、10年以上前の2015年頃から、多くのブラウザで利用できました。しかし、文字の縁取りには使いづらい特徴があります。そのため、なかなか注目はされないプロパティでした。-webkit-text-strokeを適用すると、縁取りは縁の内側と外側の両方に膨らみます。
縁取りが内側に膨らむと文字本体の「塗り」部分が侵食され、「縁取り装飾」としてうまく機能しなくなってしまいます。
次のデモは縁取りなし、細い縁取り(1px、2px)、太い縁取り(16px)の設定です。文字色を薄茶色(#EAE0CF)で指定していますが、縁取りが太いと「内側への膨らみ」により、文字の塗り色が見えなくなります。
SVGとpaint-order
-webkit-text-strokeの性質はSVGのstroke属性によく似ています。SVGのstroke属性でも線が内側と外側の両方に膨らみます。これと合わせて、SVGでは「塗り」と「線」の描画順を制御するためにpaint-order属性が用意されています。
SVGにおいて、既定の描画順では「塗り」が先に描画され、その後に「線」が上塗りされます。
一方、SVGではpaint-order属性を使用すると、描画順序を変更できます。たとえば、paint-order="stroke fill"と指定すると、「線」が先に描画され、その後に「塗り」が描画されます。
この順番で描画すると、先に描画された「線」の内側へ侵食部分を、後から描画された「塗り」で覆い隠せます。
このとき「線」として見えるのは、覆い隠されなかった部分なので、「線として見える太さ」は指定値の半分になります。残りの半分は上塗りされて見えなくなっています。
paint-orderはSVG専用の機能でしたが、2024年からすべての主要ブラウザで-webkit-text-strokeにも効果が反映されるようになりました。CSSでpaint-orderプロパティを使用すると、SVGと同様に-webkit-text-strokeの描画順序を制御できます。
補足:paint-orderのブラウザ対応
paint-orderについて、Safariは2017年からFirefoxでは2018年からCSSプロパティとしてHTML要素にも適用できました。Chromiumについては、2024年以降に対応しました。
paint-orderにより、冒頭で紹介した「枠線が塗りの内側に侵食してしまう問題」を解決できます。-webkit-text-strokeを適用するときにはpaint-order: stroke fillも併用すればいいわけです。
補足:paint-orderの値
今回は登場していませんが、paint-orderの値にはfill、strokeに加えて、markersも列挙できます。markersとはSVGのmarker要素のことで、CSSで指定できるリストマーカー::markerとは異なります。
次のデモは上にあるのが、paint-order: stroke fillの指定がないもの、下がpaint-order: stroke fillの指定をしたものです。paint-order: stroke fillのおかげで、下の文字は文字が潰れていません。
デモでわかるようにpaint-orderを上手に使えば、きれいな縁取りを思ったとおりの幅で表現できるようになります。-webkit-text-strokeで指定した幅の半分を縁取りして使うと考えればコントロールしやすいでしょう。
コラム:SVG由来の塗りと線
-webkit-text-strokeプロパティはSVGのstroke属性に由来しますが、fill属性に由来する-webkit-text-fill-colorプロパティも存在します。ただし、-webkit-text-fill-colorプロパティはcolorプロパティと機能と効果が重複するので、あえて-webkit-text-fill-colorプロパティが必要になる場面はあまりなく、テキストの塗りには従来通りcolorプロパティを使えばいいでしょう。
colorと-webkit-text-fill-colorを同時に指定した場合には-webkit-text-fill-colorの色で塗られます。colorと-webkit-text-fill-colorの大きな違いとして、-webkit-text-fill-colorは前景色(currentColor)に影響を与えません。
CSSの縁取り文字例
-webkit-text-strokeとpaint-order: stroke fill;を組み合わせれば、文字の縁取りが扱いやすくなることがわかりました。
さらにtext-shadowと組み合わせると、縁取りの強調ができたり、版ずれ効果に応用ができます。text-shadowはテキストに影を付けるプロパティで、影のオフセット(X/Y方向の位置)、ぼかし、色を指定できます。影はカンマ区切りで複数指定でき、それぞれが独立した影として描画されます。
文字を立体的にする
text-shadowで文字の下側に影をつけています。ぼかし幅0の影(つまり文字と同じ形状)を3つ用意し、それぞれ上から2px、4px、6pxの位置に配置します。こうすることで、文字を立体的にすることができます。
text-shadowで下側を強調
<p style="
font-family:'WDXL Lubrifont JP N',sans-serif;
font-size:64px;
font-weight:700;
-webkit-text-stroke:2px #213448;
text-shadow:
0 2px #213448,
0 4px #213448,
0 6px #213448;
color:#FFF;
paint-order:stroke fill;
">
縁だけあいうえお123ABC
</p>背景とのコントラストを確保する
背景画像が文字色に馴染んでしまいそうな場合には、やや太めの縁取りをつけると文字の可読性を確保できます。-webkit-text-strokeとpaint-order: stroke fillを組み合わせればテキストの線が太くても、文字が潰れることはありません。
縁取りで背景とのコントラストを強調
<p style="
font-family:'Dela Gothic One',sans-serif;
font-size:64px;
-webkit-text-stroke:10px white;
paint-order:stroke fill;
color:#30b03f;
background:url(./kodim23.png);
">
コントラスト確保
</p>「印刷ズレ」のような風合いを出す
このデモはcolor:transparent;で文字の塗りを透明にしています。ただし、文字そのものが消えるわけではなく、text-shadowと-webkit-text-strokeは有効で、描画されます。
印刷ズレのように見えるオレンジ色の部分はそのような手法で描画されています。
縁取りのみを表示しながら、text-shadowで文字色をつける
<p style="
font-family:'Dela Gothic One',sans-serif;
font-size:64px;
font-weight:700;
text-shadow:4px 4px #FFA500;
-webkit-text-stroke:.5px #000;
color:transparent;
">
版ずれ あいうえお
</p>ここまでのまとめ
-webkit-text-strokeによる文字の縁取りは、線が内側に侵食して文字が潰れやすいという問題とその理由を挙げ、SVG由来の描画順制御であるpaint-orderを併用することで、太さや可読性を安定して制御する方法を解説しました。
また、text-shadowを組み合わせ、縁取り文字のバリエーションも紹介しましたので、実務でも使ってみてください。
後編では、SVGとの比較で、HTML+CSSの実装に残る問題と、その回避方法などを紹介します。