Preventing double borders in CSS Grid

61,498

Solution 1

You may do like this :

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  border-bottom: 1px solid black;
  border-left: 1px solid black;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border-top: 1px solid black;
  border-right: 1px solid black;
}

body {
 background:pink;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

Another idea is to rely on gradient to fill gaps like below:

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  grid-gap:1px;
  background:
    linear-gradient(#000,#000) center/100% 1px no-repeat,
    repeating-linear-gradient(to right,transparent 0 50px,#000 0 51px);
  border:1px solid;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
}

body {
 background:pink;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

You can also adjust the initial solution to make it more flexible and it will work with any number of items inside a row.

Run the below code on full page and resize the window:

.wrapper {
  display: grid;
  max-width:800px;
  grid-template-columns: repeat(auto-fill,minmax(100px,1fr));
  border-top: 1px solid black;
  border-left: 1px solid black;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid black;
  border-right: 1px solid black;
}

body {
 background:pink;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11</div>
</div>

Solution 2

Instead of using an actual border around grid items, use the background color on the container (for "border" color) and the grid-gap property (for "border" width).

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  border: 1px solid black;
  grid-gap: 1px;
  background-color: black;
}

.wrapper > div {
  background-color: white;
  padding: 15px;
  text-align: center;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

Solution 3

I found a solution by using the outline property.

.grid {
	width: 100%;
	height: 700px;
	display: grid;
	grid-template-columns: repeat(4, 25fr);
	grid-template-rows: repeat(4, 25fr);
	margin-bottom: 30px;
	grid-gap: 1px;
}

.grid-item {
	background-color: silver;
	outline: 1px solid gray; /* The outline creates the border */
	text-align: center;
	position: relative;
	z-index: 1; /* original z-index */
}

/* If you want to change the color on the hover state */
.grid-item:hover {
	outline: 1px solid red;
	z-index: 2; /* You must apply a z-index bigger than the original z-index or else some parts of the outline will be behind other grid elements */
}
<div class="grid">
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
</div>

Solution 4

.wrapper {
  display: grid;
  grid-template-columns: 50px 50px 50px 50px;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border: 1px solid black;
  margin:0 -1px -1px 0;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

margin:0 -1px -1px 0; 

This should do the trick.

Solution 5

There is an easy way to do this:

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 1px;
}

.grid__item {
  border: 1px solid gray;
  box-sizing: content-box;
  width: 100%;
  height: 100%;
}
<div class="grid">
  <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 class="grid__item">7</div>
  <div class="grid__item">8</div>
  <div class="grid__item">9</div>
  <div class="grid__item">10</div>
  <div class="grid__item">11</div>
  <div class="grid__item">12</div>
</div>

P.s. The main trick here is in box-sizing: content-box. You don't need it if you do not globally override it with another value. But many people uses border-box, in that case, this override solves the problem with the gap.

Share:
61,498
klugjo
Author by

klugjo

JavaScript, React and all sorts of web stuff.

Updated on July 05, 2022

Comments

  • klugjo
    klugjo almost 2 years

    Given the current CSS grid example, how can I collapse the borders in order to avoid the double borders ?

    This is such a simple thing to achieve using an Html table. How do I do it using display: grid ?

    .wrapper {
      display: grid;
      grid-template-columns: 50px 50px 50px 50px;
    }
    
    .wrapper > div {
      padding: 15px;
      text-align: center;
      border: 1px solid black;
    }
    <div class="wrapper">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div>8</div>
    </div>

  • klugjo
    klugjo over 6 years
    Kind of hacky but at least it does the trick. Can't believe there isn't an easier way to do this. I might as well build my grid with flexbox ..
  • René
    René over 6 years
    This answer works better with non solid lines and semi-transparant borders. However, cell items are 49px here which can be a bit of nuisance. That's easily fixable.
  • Mohammed Joraid
    Mohammed Joraid about 5 years
    @pttsky you can change the opacity of the whole div.
  • EoghanM
    EoghanM about 5 years
    You just need to add a .grid { grid-gap: 1px; } to fix the superposition of elements.
  • GeorgeButter
    GeorgeButter almost 5 years
    It makes more sense if the container has border top, that way if there is only 6 items in the grid the grid won't have a random line.
  • Maksim Shamihulau
    Maksim Shamihulau over 4 years
    It does not work, there are different border widths.
  • Onur Arı
    Onur Arı almost 4 years
    If cells have different border sizes/colors this does not work.
  • mfgmicha
    mfgmicha almost 3 years
    works great if you only want top & bottom border and left & right no border. grid: row-gap: 1px items: box-shadow: 0 1px black, 0 -1px black;
  • Hairi
    Hairi over 2 years
    This is the real asnwer! It even works with wrapping content