CSS FlexboxやGridレイアウトで要素にborderを設定すると、隣接した要素のborderが重なって思ったよりも太くなってしまうことってよくありますよね。
今回は、この問題を解決する方法についてまとめていきます。
問題の説明
例えば、Flexboxで並べた要素にそれぞれborder: 3px solid #333;を設定すると、隣接する要素同士のborderが重なって6pxの太さになってしまいます。
この状態だと、境界線が不均一に見えてしまい、デザイン的にあまり美しくないですよね。
解決方法1: outlineとgap/paddingを使う方法
この問題を解決する最もシンプルな方法は、borderの代わりにoutlineを使用し、親要素にgapとpaddingを設定する方法です。
なぜoutlineを使うとうまくいくのか
borderとoutlineの最も大きな違いは、ボックスモデルへの影響です。
borderは要素のボックスモデルの一部として描画されます。そのため、隣接する要素のborderと物理的に接触し、重なって太く見えてしまいます。outlineは要素の外側に描画され、ボックスモデルには影響しません。つまり、レイアウト上のスペースを取らないため、隣接する要素のoutlineと重なることがないのです。
さらに、gapとpaddingを同じ値(例: 3px)に設定することで、要素間と外側の余白が統一され、outlineの太さ分の隙間ができます。この隙間があることで、すべての境界線が均一な太さに見えるという仕組みです。
Flexboxでの実装例
/* 親要素 */
.flex-container {
display: flex;
gap: 3px;
padding: 3px;
}
/* 子要素 */
.flex-item {
outline: 3px solid #ccc;
background: white;
padding: 20px;
}
<div class="flex-container">
<div class="flex-item">Item 1</div>
<div class="flex-item">Item 2</div>
<div class="flex-item">Item 3</div>
</div>
Gridでの実装例
Gridレイアウトでも同じ方法が使えます。
/* 親要素 */
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 3px;
padding: 3px;
}
/* 子要素 */
.grid-item {
outline: 3px solid #ccc;
background: white;
padding: 20px;
}
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
</div>
この方法のポイントは以下の通りです:
- 親要素の
gapとpaddingを同じpx値に設定する(例: 両方とも3px) - 子要素には
borderではなくoutlineを使う - 子要素の
outlineの太さは、gap/paddingと同じ値にする
不均等なレイアウトでも対応可能
この方法の優れている点は、要素の幅が不均等な場合でも、境界線が均一になるということです。Flexboxで異なる幅の要素を使った場合や、Gridでspan指定をした場合でも、境界線の太さはどこも均一になります。
Flexboxで異なる幅の要素
flex: 1やflex: 2を使って要素の幅を変えた場合でも、境界線は綺麗に揃います。
.flex-container {
display: flex;
gap: 3px;
padding: 3px;
}
.flex-item-1 {
flex: 1;
outline: 3px solid #333;
padding: 20px;
}
.flex-item-2 {
flex: 2;
outline: 3px solid #333;
padding: 20px;
}
<div class="flex-container">
<div class="flex-item-1">flex: 1</div>
<div class="flex-item-2">flex: 2</div>
<div class="flex-item-1">flex: 1</div>
</div>
Gridでspan指定
Gridレイアウトでgrid-column: span 2やgrid-column: span 3を使って要素が複数のカラムにまたがる場合でも、境界線は綺麗に揃います。
.grid-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 3px;
padding: 3px;
}
.grid-item {
outline: 3px solid #333;
padding: 20px;
}
.grid-item-span2 {
grid-column: span 2;
}
.grid-item-span3 {
grid-column: span 3;
}
<div class="grid-container">
<div class="grid-item grid-item-span2">span 2</div>
<div class="grid-item">1</div>
<div class="grid-item">1</div>
<div class="grid-item grid-item-span3">span 3</div>
<div class="grid-item">1</div>
<div class="grid-item grid-item-span2">span 2</div>
<div class="grid-item grid-item-span2">span 2</div>
</div>
解決方法2: table-cellを使う方法
もう一つの方法として、display: table-cellを使う方法もあります。この方法では、border-collapse: collapseを使用すると、隣接するセルのborderが自動的に結合されます。
/* 親要素 */
.table-container {
display: table;
border-collapse: collapse;
}
/* 行 */
.table-row {
display: table-row;
}
/* セル */
.table-cell {
display: table-cell;
border: 3px solid #333;
padding: 20px;
}
<div class="table-container">
<div class="table-row">
<div class="table-cell">1</div>
<div class="table-cell">2</div>
<div class="table-cell">3</div>
</div>
<div class="table-row">
<div class="table-cell">4</div>
<div class="table-cell">5</div>
<div class="table-cell">6</div>
</div>
<div class="table-row">
<div class="table-cell">7</div>
<div class="table-cell">8</div>
<div class="table-cell">9</div>
</div>
</div>
ただし、この方法はFlexboxやGridと比べて柔軟性が低いため、基本的には最初に紹介したoutlineを使う方法をおすすめします。
まとめ
今回は、FlexboxやGridレイアウトでborderが重なって太くなる問題の解決方法についてまとめていきました。
outlineとgap、paddingを組み合わせる方法は、FlexboxでもGridでも同じように使えて、コードもシンプルになるという点はすごくいいと思います。
もしこの記事がお役に立てたら幸いです。