最終更新日:
隣接する要素のborderが重なって太くなる問題
こんにちは。五平餅くんです。
今日は、ブログの投稿一覧ページで、記事と記事が隣接して密着状態のデザインをコーディングしたときにハマったことをお話します。
目次
tableの場合はborderがデフォルトで重なるようになっている
tableで表を作りたい時、thとtdにborderをつけたら、border同士が重なるようになってますよね。
例えばこんな感じです。
実際にはセル一つ一つにborderがついてるので、隣接するborderは2倍の太さになるはずですが、tableではあらかじめ一本の線のように表現してくれます。
しかし、tableでなくflexで横に並べたレイアウトではそうはいきません!
例えばこんな感じです。
↑の図でご説明した通り、1列目、2列目、3列目の右borderや、2行目の上borderが重なって太くなってしまいました。
「それなら、display: tableとtable-layout:collapseで横並びにすればいいのでは?」
僕も初めはそう思いました。やってみると、borderが重なるのは直りました。
しかし!
display:tableで横に並べると、今度は折り返しがうまく行きません。
さて、解消方ですが、大変シンプルな方法でした。
display:flexのまま、少し付け足すのみで実現できます。
marginなしで隣接している要素にborderがついている時
まずは、borderが重なった状態のコードです。
<div id="content">
<div class="inner">
<div class="flex">
<div class="flex-content">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<div class="flex-content">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<div class="flex-content">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<div class="flex-content">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<div class="flex-content">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<div class="flex-content">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<div class="flex-content">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
</div>
</div>
</div>
* {
box-sizing: border-box;
}
a {
text-decoration: none;
color: inherit;
}
a:hover {
text-decoration: underline;
}
.inner {
max-width: 800px;
width: 97%;
margin: 0 auto;
}
/* ここから重要! */
.flex {
display: flex;
flex-wrap: wrap;
}
.flex-content {
padding: 10px;
background: #f5f5f5;
border: 1px solid #000;
width: 25%;
}
.flex-content__img {
width: 100%;
}
.flex-content__img img {
width: 100%;
height: auto;
}
.flex-content__title {
padding-top: 5px;
font-size: 20px;
}
この状態では、まだborderが重なって太くなっています。
borderが重なって太くなる問題の対処法
さて、いよいよ線を重ならないようにしていきます。
<div id="content">
<div class="inner">
<div class="flex">
<!--クラス「border-next」をつける-->
<div class="flex-content border-next">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<!--クラス「border-next」をつける-->
<div class="flex-content border-next">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<!--クラス「border-next」をつける-->
<div class="flex-content border-next">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<!--クラス「border-next」をつける-->
<div class="flex-content border-next">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<!--クラス「border-next」をつける-->
<div class="flex-content border-next">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<!--クラス「border-next」をつける-->
<div class="flex-content border-next">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
<!--クラス「border-next」をつける-->
<div class="flex-content border-next">
<div class="flex-content__img">
<img src="https://placehold.jp/000000/ffffff/300x300.png?text=%E3%81%93%E3%81%93%E3%81%AB%E7%94%BB%E5%83%8F%E3%81%8C%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99" />
</div>
<div class="flex-content__title">
<a href="#">タイトルですタイトルです</a>
</div>
</div>
</div>
</div>
</div>
* {
box-sizing: border-box;
}
a {
text-decoration: none;
color: inherit;
}
a:hover {
text-decoration: underline;
}
.inner {
max-width: 800px;
width: 97%;
margin: 0 auto;
}
/* ここから重要! */
.flex {
display: flex;
flex-wrap: wrap;
}
.flex-content {
padding: 10px;
background: #f5f5f5;
border: 1px solid #000;
/* width: 25%; */
}
/*borderの太さ分上と右にずらして、widthに1px足す*/
.flex-content.border-next {
margin-top: -1px;
margin-left: -1px;
width: calc(25% + 1px);
}
.flex-content__img {
width: 100%;
}
.flex-content__img img {
width: 100%;
height: auto;
}
.flex-content__title {
padding-top: 5px;
font-size: 20px;
}
この3つのプロパティを付け加えた場合のデモはこちら↓
ご覧いただいた通り、線の重なりはなくなりました。
解説
.flex-contentをborderの太さ分(1px)左にずらして、borderの重なりを消しました。
その分全体的に左に寄ってしまうので、width: calc(25% + 1px)で左にずらした分を補強してやります。
calcは、計算ができる便利な関数です。
従来の幅(25%)にの左にずらした分(1px)を足せば、ちゃんと親要素.flexと同じ幅になっています。
実は全体的には上に1px、左に1pxズレているのですが、値が細かすぎて全く気になりません(個人的には)。
(もし気になるという場合には、.flex-contentのnth-of-typeで1行目と一番左を特定して、marginを0にしてやるとうまくいくかもしれません。そこまではめんどくさいため僕ははしょります。)
まとめ
borderが重なってしまう問題の対処方は、現時点でこれしか見つかりませんでした。
あまり綺麗な方法ではないですが、もしよければご活用ください!
最後まで読んでいただき、ありがとうございました!