74

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>
Michael Benjamin
  • 307,417
  • 93
  • 525
  • 644
klugjo
  • 16,697
  • 7
  • 46
  • 64

8 Answers8

71

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>
Michael Benjamin
  • 307,417
  • 93
  • 525
  • 644
58

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>
Temani Afif
  • 211,628
  • 17
  • 234
  • 311
  • 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. – René Dec 19 '17 at 09:26
  • 3
    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. – GeorgeButter Aug 15 '19 at 05:10
  • This is the real asnwer! It even works with wrapping content – Hairi Dec 15 '21 at 09:30
22

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

Krzysztof Mazur
  • 528
  • 2
  • 13
  • 2
    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 .. – klugjo Dec 19 '17 at 08:51
22

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>
EoghanM
  • 22,654
  • 22
  • 86
  • 115
14

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.

Niklan
  • 391
  • 3
  • 9
3

Something I've used with success is simply adding a box shadow to the grid items, along with a column and row gap. This then allows the columns size to always be exactly as determined in grid-template-columns. Then simply changing the column and row gap and box shadow size allows for a thicker border.

.wrapper {
  display: grid;
  grid-template-columns: 50px 50px 50px 50px;
  grid-column-gap: 1px;
  grid-row-gap: 1px;
}
.wrapper > div {
  padding: 15px;
  text-align: center;
  box-shadow: 0 0 0 1px;
}
<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>
dan richardson
  • 3,771
  • 4
  • 30
  • 38
  • 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;` – mfgmicha Jul 05 '21 at 11:39
-1

The win-win code would be to set

  • grid items: border-bottom & border-right
  • grid wrapper: border-top & border-left

So it would correct even if top columns not equal to bottom columns

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  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;
}

<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>
okater
  • 7
  • 2
-1

If you will fix the number of item per row this solution will fit you,

this example for 3 each row, but you can edit

.grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr;
  gap: 0;
  grid-template-areas: '. . .';
}

.grid-item {
  order: 0;
  flex: 0 1 auto;
  text-align: center;
  padding: 1rem;
  font-size: 12px;
  background-color: #e8e8e8;
  border-color: #000;
  border-style: solid;
  border-width: 0;

  border-right-width: 1px;
  border-bottom-width: 1px;
}

/*first 3 items*/
  .grid-item:nth-child(-n + 3) {
    border-top-width: 1px;
  }

/*last item on each row*/
  .grid-item:nth-child(3n + 0) {
    border-right-width: 1px;
    background-color: cadetblue;
  }
  
/*first item on each row*/

.grid-item:first-child,
  .grid-item:nth-child(3n + 1) {
    border-left-width: 1px;
    background-color: red;
  }
  
/*middel item on each row (not used)*/
  .grid-item:nth-child(3n - 1) {
   // border-left-width: 1px;
   background-color: yellow;
  }

/*last item (not used)*/
  .grid-item:last-child {
   // border-left-width: 0;
    background-color: green
    }
<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"> 1 </div>

<div class="grid-item"> 2 </div>

<div class="grid-item"> 3 </div>

<div class="grid-item"> 1 </div>

<div class="grid-item"> 2 </div>


</div>
Mansour Alnasser
  • 3,367
  • 4
  • 30
  • 46