border-collapseを理解して、テーブルセルにdivをぴったり重ねる

## テーブルのセルにdivを重ねたい！
こういう事って、よくありますよね。うむうむ。
でもちょっとこんがらがっちゃう。
そこでこの記事ではパターン別に計算方法を整理してみました。

## まずは復習から
`border-collapse`と`box-sizing`について確認していきます。

### border-collapseとは
テーブルセルの配置の仕方を指定するものです。
`collapse`の場合、borderの中心を`whidth`や`height`に合うようにずらすことで重なりを表現します。

| type | 配置の仕方 | 見え方 |
|:--|:--|:--|
| collapse | 隣り合うセル同士を重ねる | 格子状になる |
| separate | 隣り合うセル同士を重ねない | 四角を寄せ集めた状態になる |
<p class="codepen" data-height="262" data-theme-id="dark" data-default-tab="html,result" data-user="putan" data-slug-hash="bGVRMzJ" style="height: 262px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="table size - border-collaps">
  <span>See the Pen <a href="https://codepen.io/putan/pen/bGVRMzJ">
  table size - border-collaps</a>
</p>



### box-sizingとは
widthとheightの計算の仕方を指定するものです。

| type | サイズの取り方 | borderの位置 |
|:--|:--|:--|
| content-box | paddingとborderを含めない | widthやheightの外側 |
| border-box | paddingとborderを含める | widthやheightの内側 |
<p class="codepen" data-height="322" data-theme-id="dark" data-default-tab="css,result" data-user="putan" data-slug-hash="MWaoXbb" style="height: 322px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="table size - box-sizing">
  <span>See the Pen <a href="https://codepen.io/putan/pen/MWaoXbb">
  table size - box-sizing</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>



## 実践
では `border-collaps` と `boz-sizing` の掛け合わせで1つずつ見ていきます。

### separate + border-box
こちらは素直ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5514/7a8a72cd-c41b-8d38-1452-7d48d4e752b1.png)

| | 計算 |
|:--|:--|
| 重ねるdivの相対位置（left） | tdのwidth * (列数 - 1) |
| 重ねるdivの相対位置（top） | tdのheight * (行数 - 1) |
| 重ねるdivの幅 | tdのwidth * 列数 |
| 重ねるdivの高さ | tdのheight * 行数 |
<p class="codepen" data-height="280" data-theme-id="dark" data-default-tab="css,result" data-user="putan" data-slug-hash="rNOwZMB" style="height: 280px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="table size - separate+ border-box">
  <span>See the Pen <a href="https://codepen.io/putan/pen/rNOwZMB">
  table size - separate+ border-box</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>


### separate + content-box
こちらもわかりやすいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5514/e6da239b-fa1e-8a44-158f-c430a895e38d.png)


| | 計算 |
|:--|:--|
| 重ねるdivの相対位置（left） | (tdのwidth + (border-width * 2)) * (列数 - 1) |
| 重ねるdivの相対位置（top） | (tdのheight + (border-width * 2)) * (行数 - 1) |
| 重ねるdivの幅 | (tdのwidth + (border-width * 2)) * 列数 |
| 重ねるdivの高さ | (tdのheight + (border-width * 2)) * 行数 |
<p class="codepen" data-height="344" data-theme-id="dark" data-default-tab="css,result" data-user="putan" data-slug-hash="rNOwZma" style="height: 344px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="table size - separate + content-box">
  <span>See the Pen <a href="https://codepen.io/putan/pen/rNOwZma">
  table size - separate + content-box</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>



### collapse + border-box
ここからが難所です。
`border-box`の場合、`border`はboxの内側に入り込んでいますが、
`collapse`がboxに`border`の中心を合わせようと、**borderの位置を0.5border分外側にずらします**。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5514/194c1171-2668-585f-8149-39b9470333af.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5514/b6d998db-631e-8b22-cec0-27ed536dbafc.png)


| 指定するサイズ | 計算 |
|:--|:--|
| 重ねるdivの相対位置（left） | tdのwidth * (列数 - 1) |
| 重ねるdivの相対位置（top） | tdのheight * (行数 - 1) |
| 重ねるdivの幅 | tdのwidth * 列数 + border-width |
| 重ねるdivの高さ | tdのheight * 行数 + border-width |
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="putan" data-slug-hash="zYvzWaX" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="table size - collapse + border-box">
  <span>See the Pen <a href="https://codepen.io/putan/pen/zYvzWaX">
  table size - collapse + border-box</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

### collapse + content-box
`content-box`の場合、元々は`border`はboxサイズの外側にありますが、
`collapse`がboxに`border`の中心を合わせようと、**boxサイズを0.5border分外側にずらします**。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5514/fa07b2f7-43d0-8bb3-9e6e-89311bd56160.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5514/ae4f5dd4-0d1a-3fc4-700d-ebe2b0844cfb.png)

| | 計算 |
|:--|:--|
| 重ねるdivの相対位置（left） | (tdのwidth + border-width) * (列数 - 1) |
| 重ねるdivの相対位置（top） | (tdのheight + border-width) * (行数 - 1) |
| 重ねるdivの幅 | (tdのwidth + border-width) * 列数 + border-width |
| 重ねるdivの高さ | (tdのheight + border-width) * 行数 + border-width |
<p class="codepen" data-height="319" data-theme-id="dark" data-default-tab="css,result" data-user="putan" data-slug-hash="qBOjyqG" style="height: 319px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="table size - collapse + content-box">
  <span>See the Pen <a href="https://codepen.io/putan/pen/qBOjyqG">
  table size - collapse + content-box</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>




<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## まとめ
はい、ということで`border-collapse`と`box-sizing`の組み合わせ4パターンで無事テーブルにdivを重ねることができました。
今回は`padding`や`border-spacing`を0としましたが、ぜひその辺りも調整してdivを重ねてみてください。


## 参照
[MDN border-collapse](https://developer.mozilla.org/ja/docs/Web/CSS/border-collapse)
[MDN box-sizing](https://developer.mozilla.org/ja/docs/Web/CSS/box-sizing)
[スタックオーバーフロー table、tr、tdタグの box-sizing: border-box について
](https://ja.stackoverflow.com/questions/45313/table-tr-td%E3%82%BF%E3%82%B0%E3%81%AE-box-sizing-border-box-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)