隣接する要素のborderが重なって太くなる問題

  • このエントリーをはてなブックマークに追加
borderが重なっているところが太い!!

こんにちは。五平餅くんです。

今日は、ブログの投稿一覧ページで、記事と記事が隣接して密着状態のデザインをコーディングしたときにハマったことをお話します。

tableの場合はborderがデフォルトで重なるようになっている

tableで表を作りたい時、thとtdにborderをつけたら、border同士が重なるようになってますよね。

例えばこんな感じです。

tableでth、tdにborderをつけた場合。

実際にはセル一つ一つにborderがついてるので、隣接するborderは2倍の太さになるはずですが、tableではあらかじめ一本の線のように表現してくれます。

しかし、tableでなくflexで横に並べたレイアウトではそうはいきません!

例えばこんな感じです。

flexで横に並べたborder要素。1列目、2列目、3列目の右borderや2行目の上borderが重なって太くなってしまう。
flexで横に並べたborder要素。1列目、2列目、3列目の右borderや2行目の上borderが重なって太くなってしまう。

↑の図でご説明した通り、1列目、2列目、3列目の右borderや、2行目の上borderが重なって太くなってしまいました。

「それなら、display: tabletable-layout:collapseで横並びにすればいいのでは?」

僕も初めはそう思いました。やってみると、borderが重なるのは直りました。

しかし!

display:tableで横に並べると、今度は折り返しがうまく行きません。

display:tableとtable-layout:collapseで横並び+線重なり防止をした結果。折り返しがうまくいかない。
display:tableとtable-layout:collapsedisplay:tableとtable-layout:collapseで横並び+線重なり防止をした結果。折り返しがうまくいかない。

さて、解消方ですが、大変シンプルな方法でした。

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;
}

@media screen and (max-width: 1499px) {
  .inner {
    width: 97%;
  }
}

/* ここから重要! */

.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;
}

@media screen and (max-width: 1499px) {
  .inner {
    width: 97%;
  }
}

/* ここから重要! */

.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と同じ幅になっています。

親要素.flexと同じ幅に戻った

実は全体的には上に1px、左に1pxズレているのですが、値が細かすぎて全く気になりません(個人的には)。

(もし気になるという場合には、.flex-contentのnth-of-typeで1行目と一番左を特定して、marginを0にしてやるとうまくいくかもしれません。そこまではめんどくさいため僕ははしょります。)

まとめ

borderが重なってしまう問題の対処方は、現時点でこれしか見つかりませんでした。

あまり綺麗な方法ではないですが、もしよければご活用ください!

最後まで読んでいただき、ありがとうございました!

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。