1pxのborder付けた画像をChromeでズームした時に現れる隙間を消す方法

CSSで`img`要素の周囲に1pxのborderを付けた画像をChromeで表示した時、ズームで拡大していくと下図のように左右borderと画像の端との間にわずかな隙間が生じる現象に遭遇しハマったので、解決方法をここに書きます。

**動作環境**
macOS 10.14 (Mojave), Retinaディスプレイ(Radeon Pro 575), Chrome 79

![chrome-1px-border-gap-sample_w800.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/4c242d98-87dc-822c-9634-dfac387a1658.png)
図の上段が問題のレイアウトで、`li`要素で囲んだ２つのimg要素をフロートで配置したものです。
画像出典: [Lorem Picsum](https://picsum.photos/) Images from [Unsplash](https://unsplash.com/)

<details><summary>HTML(要点のみ)</summary><div>

```html
<div class="grid">
  <ul class="img-list">
    <li class="box1">
      <img src="https://picsum.photos/id/1001/1222/454" alt="">
    </li>
    <li class="box2">
      <img src="https://picsum.photos/id/326/590/454" alt="">
    </li>
  </ul>
</div>
```
</div>

<details><summary>CSS(要点のみ)</summary><div>

```css
ul {
  list-style-type: none;
}
.grid {
  width: 930px;
  margin: 0 auto 40px;
}
.img-list {
  overflow: hidden;
}
.img-list li {
  float: left;
  width: 297px;
  margin-right: 19px;
}
.img-list li:last-child {
  margin-right: 0;
}
.img-list .box1 {
  width: 613px;
}
.img-list img {
  box-sizing: border-box;
  width: 100%;
  height: auto;
  vertical-align: bottom;
  border: 1px solid blue;
}
```
</div>

画像の枠線は`img`要素に対して`border: 1px solid blue`で付けています。このサンプルでは、Chromeで125%に拡大した時に問題の“隙間”が現れました。丸で囲った部分を拡大したのが下段の図です（デバイスピクセル比=2のモニタで確認しています）。左側がChrome、右側がFirefox[^2]で表示したものです。Firefoxでは隙間なくぴっちりと画像の周囲に枠線が描かれるのに対して、Chromeでは1px分の隙間を入れられてしまいました。
[^2]: Firefoxはメニューに125%の拡大がないため、このアドオンで倍率を設定: [Default Zoom](https://addons.mozilla.org/en-US/firefox/addon/default-zoom/)

## 隙間の振る舞い
今回のサンプルコードに関していえば、borderの隙間が発生する条件は倍率125%に加えていくつかあるようです。
### ブラウザのウィンドウ幅が奇数ピクセルになると発生する
隙間を見分けやすくするため、画像を囲む`li`要素の背景色を赤`#ff0000`にしました。125%に拡大した後、ブラウザのウィンドウ幅を大きくしていくと、隙間が出たり消えたりするのがわかります（下図）。1395pxとか幅が奇数ピクセルの時に隙間が現れ、偶数ピクセルでは隙間が消えます。
![video_125p_edit.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/c52521e7-7b1c-2554-1a3c-31f27b778d9f.gif)

### 包含ブロックに左右margin: autoが設定されていると発生する
サンプルのコードでは、包含ブロック`div.grid`に`margin: 0 auto 40px`を設定しているのですが、このプロパティを消すと隙間が消えます！（下図） しかし、デスクトップ版のページレイアウトに左右marginを使わないわけにはいかないので、これは対策には使えません。
![video_125p_margin_edit.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/6f8fc98e-e4fe-2f94-eb5c-723c8c7b1951.gif)

## 解決策
Chromeで隙間を消す方法は意外に簡単でした。CSSでたった１行、borderの太さを`thin`に変えるだけ。
参考にした解法: [Borders disappear in Chrome when I zoom in](https://stackoverflow.com/questions/12547580/borders-disappear-in-chrome-when-i-zoom-in/50912523#50912523)

```css
img {
  /* border: 1px solid blue; */
  border: thin solid blue;
}
```

やってみましょう。下図で上側が`border: thin ...`、下側が`border: 1px ...`です。拡大率125%でウィンドウ幅を変えても、`thin`に設定した方は隙間が生じないことがわかります。また、80%に縮小した時、`border: 1px`の方は、左側のborderが消えてしまうのに対して、`thin`の方はちゃんとborderが描かれます。
![video_125p_fix_edit.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/43288b95-b622-449d-a9ef-5a5029e34f56.gif)

サンプルのコード: [https://codepen.io/kaz_hashimoto/pen/NWqpqPV](https://codepen.io/kaz_hashimoto/pen/NWqpqPV)

自分の環境で確認したデスクトップ版ブラウザのうち、今回の現象が発生するのはChromeだけでした。

**確認したブラウザ**

* macOS: Chrome/Firefox/Safari/Opera
* Windows 10: IE11/Edge(従来版)

Chrome以外は従来どおりの`border: 1px ...`方式で大丈夫そうなので、実際の案件ではJavaScriptを使ってブラウザ判定し、UAがデスクトップ版Chromeの場合のみ`body`にclassをセットして、CSSルールを分けるようにしておきました。要点だけ書くとこんな感じ。

```css
img {
  border: 1px solid blue;
}
.chrome-pc img { /* JavaScriptでbodyにclass="chrome-pc"をセットしておく */
  border: thin solid blue;
}
```