CSSでborder-width
プロパティの値に0.3pxとか1.7pxみたいに小数を指定した場合、表示される要素の境界線の線幅にどれくらい違いが現れるのか以前から気になってたので、サンプルのコードを書いて各ブラウザーで確認してみました。
サンプルのコードはこちら: https://codepen.io/kaz_hashimoto/pen/VwyVqzN
細い境界線を1本引いただけでは差がわかりにくいため、複数本並べて表示してみます。Chromeで表示するとこうなりました。(GIFアニメーションです。Firefoxではクリックして再生)
ピンク色と白のストライプの1本1本が境界線です。境界線の幅は0.1pxから2pxまで0.1px刻みに、そして並べる本数は1本から10本まで変化させています。
セルの右側の数式は、boxの幅100pxを内法と境界線のストライプの幅の和に分解したものです。数式に表示したpx値はCSSプロパティの使用値(used value)1です。
境界線のストライプを作るHTMLのコードは、border-right
を設定したdiv.boxを境界線の本数分ネストすることで実現しています。
ブラウザーによる表示の違いを比較
他のブラウザーではどんな線幅で表示されるでしょうか? 結果はご覧のとおり。
デスクトップ版ブラウザー
スマホ版ブラウザー
画面に表現できる線幅の細かさや段階は、ブラウザーによる違いだけでなくディスプレイのデバイスピクセル比(DPR, device pixel ratio)も関係してそうです。デスクトップ版の左側2つは同じディスプレイ(DPR=2)で表示したものですが、ChromeとOperaの場合、見かけの線幅も0.1px刻みで変化する(最小0.5px)のに対して、FirefoxとSafariでは0.5px刻みに丸めた線幅になりました。
今回テストした環境は下表のとおりです。
DPR | OS | ブラウザー | 実行環境 |
---|---|---|---|
1 | Windows 10 | Edge 100, IE11 | BrowserStack |
2 | macOS 11.6.5 | Chrome 100, Firefox 99, Safari 15.4, Opera 85 | 実機 |
3 | iOS 15.2 | Safari 15.2 | iOS Simulator |
3.5 | Android 10 | Chrome 100 | 実機 |
半端なpxの境界線はどのように描画されているか
0.7pxなど半端な線幅が指定された境界線を、Chromeは画面上のピクセルでどのように表現しているのでしょうか?
そこで、サンプルの画面をChrome DevToolsの"capture full size screenshot"コマンド2を使って保存します。Photoshopでその画像を開いて、境界線のストライプ部分をピクセルが確認できるくらいまで拡大してみました。
使用したディスプレイはDPR=2なので、1 css pxは画面上で2x2のタイル(シアン色で示した矩形)に相当します。見てのとおり、
-
border-width
の指定値が0.6pxや0.7pxの場合も、border1本に対して塗りつぶされるタイルは1列の幅 = 1 device px (dpx) = 0.5 css pxである。 - 一方、
border-width
の使用値はそれぞれ0.59375pxと0.695312pxで算出されている。 - 境界線のストライプが太く見えたのは、所々タイル1列の幅の隙間が挿入されていたため。その隙間からは背景が見えてしまう。
このように、計算上の幅(使用値)と塗りつぶしたタイルの幅の合計とのズレは隙間を挿入することにより補正していたようです。
では、境界線を1本だけ引いた場合に隙間は生じるでしょうか?下図は指定幅0.5px〜0.9pxで引いた境界線です。拡大するとタイル1列分だけが塗りつぶされています。
次にdiv.boxのパディング領域の背景を青色で塗りつぶしてみます。パディング領域は階層の最も内側のdiv.innerが占めているので、そのbackground-color
をblue
に設定します。
指定幅0.6pxや0.9pxなどの場合、境界線とパディングの縁との間に隙間ができてその下の背景が見えてしまっているのがわかります。
隙間が生じるか否かはboxの寸法にも依存するようです。下図は指定幅0.7pxの境界線を1本から10本まで順に増やしていった時の様子です。内側のboxの幅が狭くなるにつれて、境界線とパディングの縁との間に隙間が現れたり消えたりしています。(GIFアニメーションです)
実際の画像で検証
要素の境界線とパディングの縁との間に生じる隙間について、実際の画像を使って検証してみましょう。
サンプル2: https://codepen.io/kaz_hashimoto/pen/vYpMrRw
サンプル2は、グリッドレイアウトに同じ画像6個を同じ寸法で配置します。各グリッドセルのdiv.boxには幅0.8pxの境界線を設定し、背景を赤色で塗りつぶしてあります。画像と境界線との間に隙間がなければ、赤い背景色は画像に隠れて見えないはずです。下図はChromeで表示した画面です。背景色がチラチラ見えているのがわかります。これが隙間です。
※素材画像: Photo by Evangeline Sarney on unsplash
境界線の色を白にすると隙間の箇所がはっきりします。
boxの上下左右の境界線のどこに隙間が生じるかは、boxの位置や寸法にも依存するようです。ウインドウ幅を変えてグリッドの列数やセルの幅を変化させた時にも隙間が現れる辺が切り替わるのを確認できます。
注)Nextボタンをクリックして画面を再描画させる必要があります3
表示サイズが大きい画像の場合、隙間ができると境界線に接する画像の端がぼやけたり筋のように見えることがあります。特にコーナーの部分では隙間が目立ちやすいです。
サンプル3: https://codepen.io/kaz_hashimoto/pen/BaJEbmZ
※素材画像: Photo by Content Pixie on unsplash
関連記事: 1pxのborder付けた画像をChromeでズームした時に現れる隙間を消す方法