【🐣成長記録1】iPhoneで内側のborderが太くなってしまう

## はじめに

こんにちは！ささかまです！
前回のアドベントカレンダーに続き２回目の記事になります！
今回は、iPhoneで見たときにtableタグで作った表のborderが内側だけ太くなってしまう現象の原因と解決策についてまとめていきたいと思います！

## 問題が発生した状況
今回の問題が発生してしまった表は下のものになります。
一番左の列が固定で、横にスクロールできる表になっています。
この問題はiPhone(iOS 17.2.1)のSafari、Chrome、Firefoxで確認することができました。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="wvOPMEe" data-user="ixeujzbc-the-solid" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ixeujzbc-the-solid/pen/wvOPMEe">
  初期状態</a> by 佐々木悠真 (<a href="https://codepen.io/ixeujzbc-the-solid">@ixeujzbc-the-solid</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3313803/dfdb3356-52d6-b0f1-5f75-ee13f0c118c6.jpeg">

PCで見る分には問題ないのですがiPhoneで見ると外枠のborderよりも内側のborderの方が若干太く見えてしまいます。
また、左端の列をstickyで固定しスクロールすると、固定したセル両端のborderも消えてしまいました。こちらも直していきます。

## 解決方法
### stickyで固定した時に左右のborderが消える（サブクエスト）

まず最初にstickyで固定した時に、固定したセルのborderが消えてしまう問題を解決していきたいと思います。
こちらを修正するのは簡単で、親要素であるtableタグに`border-collapse:separate;`を指定してあげることで解決できます。
border-collapseとはtable内のセルが境界を共有するか分離するかを設定するプロパティです。

```css
border-collapse: collapse; /*隣接するセルは境界線を共有します*/
border-collapse: separate; /*隣接するセルは個別で境界線を持ちます*/
```

`border-collapse: collapse;`を指定してしまうと境界線が結合されて、スクロールしたときに持っていかれてしまうみたいです。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="MWxRyrr" data-user="ixeujzbc-the-solid" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ixeujzbc-the-solid/pen/MWxRyrr">
  Untitled</a> by 佐々木悠真 (<a href="https://codepen.io/ixeujzbc-the-solid">@ixeujzbc-the-solid</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

separateを指定したことで左右のborderが消えずに残ってくるようになりました。
collapseによって共有されていた境界線が個別になったので、全方向にかけていたborderを下と右にのみ指定してborderが被らないように変更しました。

### iPhoneで見ると内側のborderが太くなる（メインクエスト）
次に本題のiPhoneで見たときに内側のborderが太くなってしまう問題を解決していきます。
と思ったのですが、先ほど固定したセルのborderが消えてしまう問題を解消するためにcollapseからseparateに変更したらこちらも直っていました。
修正した部分はborder-collapseとborderの位置のみなのでこれが原因だと考えます。
`position: sticky`で固定していたのが原因なのかなとも思ったので、一度固定を解除して、原因を探ってみます。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="VwRQdJK" data-user="ixeujzbc-the-solid" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ixeujzbc-the-solid/pen/VwRQdJK">
  collapse</a> by 佐々木悠真 (<a href="https://codepen.io/ixeujzbc-the-solid">@ixeujzbc-the-solid</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


iPhoneで見ると内側のborderが太くなっています。
position: stickyは関係なさそうです。やはりborderが太くなってしまう原因はborder-collapseが原因なのではないかなとおもいます。

## 敗北
色々調べてみたのですが、border-collapseがiPhoneでのみ見え方が変わるという記事は見つけられませんでした。自分一人の力では残念ながら原因を突き止めることはできないと思い、アドバイスをいただきました。どうやら`デバイスピクセル比`というものが関係しているかもしれないとのことでした。

### デバイスピクセル比
デバイスピクセル比とはCSS上の1pxを表示させるのに使われているピクセル数の比率のことです。
例えばCSS上で2pxを指定したborderを、デバイスピクセル比が2の端末で見ると２*２＝４で4pxになります。
上記を踏まえた上で再度表を確認してみます。

## 仮説
下画像はiPhone 11 Pro(デバイスピクセル比3)で表を見た時のものになります。

![スクリーンショット 2024-02-06 12.31.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3313803/9fc14c80-fc1d-92f1-5540-3571d012af7f.png)

CSS上でborderの太さは全て１pxを指定しています。
外側の青borderは3px幅になっています。こちらはデバイスピクセル比が3のため特に問題はありません。問題は内側の青borderです。こちらの太さは4pxとなっています。よくみると赤と青のborderの境目も揃っておらず、青が1px分はみ出てしまっています。

どうやら**border-collapseのレンダリング計算結果には多少の誤差がある**ようで、その誤差とデバイスピクセル比が掛け合わさって今回の内側だけ太くなってしまう現象が起きたと考えられます。
以上のことから仮説を立てると
1. 内側のborderのみ`border-collapse: collapse;`で境界線を共有に
1. しかしそこで本来1pxになるはずだったborderの太さが誤差で1.4px?(正確な値はわからないので例です。)になってしまう
1. PCなどのデバイスピクセル比が1,2の端末では`1*1.4=1.4`,`2*1.4=2.8`となるため外側のborderと差が出ない
1. デバイスピクセル比が3の端末では`3*1.4=4.2`となる
1. `border-collapse: collapse;`の影響を受けない外側のborderはデバイスピクセル比により3px、内側のborderは先ほどの計算から4px
1. デバイスピクセル比が3のiPhone端末でのみ内側と外側で1pxの誤差が出てしまう

デバイスピクセル比が異なるいくつかの端末でどのような表示になるか確認してみました。

### 検証結果
|  | デバイスピクセル比 | 内側borderの太さ |
|:-:|:-:|:-:|
| iPhone 13 Pro | 3 | 太くなる |
| iPhone 13 | 3 | 太くなる |
| iPhone 11 Pro | 3 | 太くなる |
| iPhone 7 | 2 | 外側と同じ |
| Pixel 7a | 2.625 | 外側と同じ |

デバイスピクセル比が3のものだけ内側のborderが太くなっていました。
`border-collapse: collapse;`とデバイスピクセル比が原因という仮説は合っていそうです。

## まとめ
今回はiPhoneで内側borderが太くなってしまう現象についてまとめてみました。
大元の原因としては、border-collapseの計算結果に誤差が生まれた事になるので、解決策としてはやはり`border-collapse: separate;`を指定して、それぞれborderを当てるのがいいのかなと思います。
デバイスピクセル比の存在やborder-collapseのレンダリング計算結果には多少の誤差があることなど、初めて知る知識が多く、かなり勉強になりました！

## 参考サイト
最後に参考にさせていただいたサイトを載せておきます。最後まで見ていただきありがとうございました！
* [【CSS】table-cellを［position:sticky;］で固定したときのボーダーが消える現象を解決する方法](https://on-ze.com/archives/5021)
* [cssで同じサイズなのにディスプレイによって線のサイズがバラバラに見える現象【対処法】](https://apricot-design.com/staffblog/devicepixelratio/)
* [iPhone 画面サイズ・ピクセル数早見表](https://www.genz.jp/useful_information/iphone_size_quickreferencematrix/)