css

【CSS】FlexやGridでborderが重なって太くなる問題の解決方法

CSS FlexboxやGridレイアウトで要素にborderを設定すると、隣接した要素のborderが重なって思ったよりも太くなってしまうことってよくありますよね。

今回は、この問題を解決する方法についてまとめていきます。

問題の説明

例えば、Flexboxで並べた要素にそれぞれborder: 3px solid #333;を設定すると、隣接する要素同士のborderが重なって6pxの太さになってしまいます。

❌ Before: 問題のある状態
borderが重なって太くなる
Flexboxの例
Item 1
Item 2
Item 3
Gridの例
1
2
3
4
5
6
💡 境界線をよく見ると、要素同士が接している箇所は線が太くなっています(3px + 3px = 6px)

この状態だと、境界線が不均一に見えてしまい、デザイン的にあまり美しくないですよね。

解決方法1: outlineとgap/paddingを使う方法

この問題を解決する最もシンプルな方法は、borderの代わりにoutlineを使用し、親要素にgappaddingを設定する方法です。

なぜoutlineを使うとうまくいくのか

borderとoutlineの最も大きな違いは、ボックスモデルへの影響です。

  • borderは要素のボックスモデルの一部として描画されます。そのため、隣接する要素のborderと物理的に接触し、重なって太く見えてしまいます。
  • outlineは要素の外側に描画され、ボックスモデルには影響しません。つまり、レイアウト上のスペースを取らないため、隣接する要素のoutlineと重なることがないのです。

さらに、gappaddingを同じ値(例: 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>
✅ After: 解決した状態
outlineで均一な線に
Flexboxの例
Item 1
Item 2
Item 3
Gridの例
1
2
3
4
5
6
✨ すべての境界線が均一な3pxになり、見た目が美しくなりました!

この方法のポイントは以下の通りです:

  • 親要素のgappaddingを同じpx値に設定する(例: 両方とも3px)
  • 子要素にはborderではなくoutlineを使う
  • 子要素のoutlineの太さは、gap/paddingと同じ値にする

不均等なレイアウトでも対応可能

この方法の優れている点は、要素の幅が不均等な場合でも、境界線が均一になるということです。Flexboxで異なる幅の要素を使った場合や、Gridでspan指定をした場合でも、境界線の太さはどこも均一になります。

Flexboxで異なる幅の要素

flex: 1flex: 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>
インタラクティブデモ: Flexboxで異なる幅
✅ 現在: outline版
flex: 1
flex: 2
flex: 1
✨ 要素の幅が異なっても、境界線はすべて均一な3pxです

Gridでspan指定

Gridレイアウトでgrid-column: span 2grid-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>
インタラクティブデモ: Gridでspan指定
✅ 現在: outline版
span 2
1
1
span 3
1
span 2
span 2
✨ spanで複数カラムにまたがる要素でも、境界線はすべて均一な3pxです

解決方法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>
table-cellを使った例
1
2
3
4
5
6
7
8
9
💡 border-collapse: collapseを使用すると、隣接するセルのborderが自動的に結合されます

ただし、この方法はFlexboxやGridと比べて柔軟性が低いため、基本的には最初に紹介したoutlineを使う方法をおすすめします。

まとめ

今回は、FlexboxやGridレイアウトでborderが重なって太くなる問題の解決方法についてまとめていきました。

outlinegappaddingを組み合わせる方法は、FlexboxでもGridでも同じように使えて、コードもシンプルになるという点はすごくいいと思います。

もしこの記事がお役に立てたら幸いです。