14

I need to use a grid layout but also need a horizontal line separating each row.

The only thing I've been able to find is applying a border to each cell, but this only works if there are enough cells to fill each row.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
}

.box {
  border-bottom: 2px solid #ffa94d;
  padding: 1em;
}
<div class="wrapper">
  <div class="box">One</div>
  <div class="box">Two</div>
  <div class="box">Three</div>
  <div class="box">Four</div>
</div>

Is there a way to fix the above so that the entire row has a border?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Reactgular
  • 52,335
  • 19
  • 158
  • 208

4 Answers4

14

Add a grid-gap equal to the width of your border then consider gradient to achieve this:

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
  grid-row-gap:2px;
  background:
    repeating-linear-gradient(to bottom,
      #0000 0 100px, #ffa94d 0 102px /*+2px here*/
    );
}

.box {
  padding: 1em;
}
<div class="wrapper">
  <div class="box">One</div>
  <div class="box">Two</div>
  <div class="box">Three</div>
  <div class="box">Four</div>
</div>

Another idea is to consider a pseudo-element that you add to the 1st,4th,7th .. (3n + 1)th element:

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
  overflow:hidden;
}

.box {
  position:relative;
  padding: 1em;
}
.box:nth-child(3n + 1)::after {
  content:"";
  position:absolute;
  bottom:0px;
  left:0;
  width:100vw;
  height:2px;
  background:#ffa94d;
}
<div class="wrapper">
  <div class="box">One</div>
  <div class="box">Two</div>
  <div class="box">Three</div>
  <div class="box">Four</div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
8

Imagine your table as a collection of cells (much like an excel spreadsheet). You can create a simple cell class that you append to each of your grid items to manipulate the cells without affecting the table data itself. Consider:

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  
  grid-row-gap: 20px;
}


.cell {
  position: relative;
  border-bottom: 2px solid #ffa94d;
}
<div class="wrapper">
  <!-- Here is your first row -->
  <div class="cell">One</div>
  <div class="cell">Two</div>
  <div class="cell">Three</div>

  <!-- Here is your second row -->
  <div class="cell">Four</div>
  <!-- You can extend the line by the number of cells per row -->
  <div class="cell"></div>
  <div class="cell"></div>
  
  <!-- Organize your html into row groups to easily visualize them -->
  <!-- This will produce a blank row with no line -->
  <div></div>
  <div>-- blank row --</div>
  <div></div>
  
  <!-- You can also control where the line begins and ends -->
  <div class="box cell">First Column Only</div>
  <div></div> <!-- No cells here.. We just want to underline the first column -->
  <div></div>
  
  <!-- 2nd and 3rd columns only -->
  <div></div>
  <div class="cell">Second Column</div>
  <div class="cell">Third Column</div>
  
  
  
</div>

Note that I only used a grid-row-gap. If you introduce a grid-gap, or a grid-column-gap, your lines will be broken at the column gaps (this may be the desired effect in some cases).

It is true that this is a more involved method of controlling the horizontal lines separating the grid and less "programmatic" and more micro-management-esque but, it does provide great control over introducing the lines into your grid.

The other answers were great options too! I just wanted to provide my two cents.

Steel82
  • 81
  • 1
  • 1
1

This can be achieved with a pseudo element, absolutely positioned. It will override the grid-gap. You will have to set it to a wide width, which is only a little hacky, then set the overflow on the container to hidden.

body {
  margin:0;padding:0;
}

.products {
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  grid-gap:20px;
  overflow:hidden;
  border-bottom:1px solid black;
}

.card-product {
  position:relative;
  text-align:center;
}
.card-product:after {
  content:'';
  position:absolute;
  border-bottom:1px solid black;
  top:-20px;left:0;
  height:1px;
  width:1000%;
}
<section class="products">

  <article class="card-product">  
    <h3 class="card-product__title">
      Product Title
    </h3>
    <h4 class="card-product__sub">
      Product Category
    </h4>
  </article>

  <article class="card-product">  
    <h3 class="card-product__title">
      Product Title
    </h3>
    <h4 class="card-product__sub">
      Product Category
    </h4>
  </article>

  <article class="card-product">  
    <h3 class="card-product__title">
      Product Title
    </h3>
    <h4 class="card-product__sub">
      Product Category
    </h4>
  </article>
  
  <article class="card-product">  
    <h3 class="card-product__title">
      Product Title
    </h3>
    <h4 class="card-product__sub">
      Product Category
    </h4>
  </article>

  <article class="card-product">  
    <h3 class="card-product__title">
      Product Title
    </h3>
    <h4 class="card-product__sub">
      Product Category
    </h4>
  </article>

  <article class="card-product">  
    <h3 class="card-product__title">
      Product Title
    </h3>
    <h4 class="card-product__sub">
      Product Category
    </h4>
  </article>

  <article class="card-product">  
    <h3 class="card-product__title">
      Product Title
    </h3>
    <h4 class="card-product__sub">
      Product Category
    </h4>
  </article>

</section>
mediachunk
  • 11
  • 1
0

The box class puts a border in the grid children, and you can make a grid children grow to fill any number of columns; below there's an example, where definig the class span3, the fourth grid child spans for 3 columns.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
}

.box {
  border-bottom: 2px solid #ffa94d;
  padding: 1em;
}
.span3 {
  grid-column-end: span 3;
}
<div class="wrapper">
  <div class="box">One</div>
  <div class="box">Two</div>
  <div class="box">Three</div>
  <div class="box span3">Four</div>
</div>