Achieving space between elements using Flexbox with a line separating each row

I have already found a solution to this question, but I am interested in exploring better alternatives. My goal is to utilize flexbox to create rows of items with equal spacing and dividing lines between them. The examples provided in the code snippet achieve this by using an :after pseudo-element, albeit requiring additional CSS to hide it on the final row.

.item:nth-child(4n + 1):nth-last-child(4):after,
.item:nth-child(4n + 1):nth-last-child(4):after,
.item:nth-child(4n + 1):nth-last-child(2):after,
.item:nth-child(4n + 1):nth-last-child(1):after{
display: none;  
}

It seems there might be a more streamlined approach (utilizing flexbox). Does anyone have any ideas?

I attempted applying a border to each item, but this introduces space between them which is not ideal. Furthermore, I would still need to use :nth-last-child to hide it.

.outer{
background-color: #ccc;
margin-bottom: 15px;
}

.wrap{
overflow: hidden;
flex: 4;
justify-content: space-between;
flex-flow: row wrap;
width: 80%;
margin: 0 auto;
background-color: #cdcdcd;
display: flex;
}

.item{
width: 23%;
padding-bottom: 30px;
margin-bottom: 30px;
position: relative;
}
.item2{
width: 23%;
padding-bottom: 30px;
margin-bottom: 30px;
position: relative;
border-bottom: 1px solid red;
}
.item:nth-child(4n + 1):after{
content: "";
position: absolute;
left: 0;
width: 500%;
bottom: 0;
border-bottom: 1px solid red;
}
@media (max-width: 768px) {
.item:nth-child(2n + 1):nth-last-child(2):after,
.item:nth-child(2n + 1):nth-last-child(1):after{
display: none;  
}
.item{
width: 43%;
}
}
@media (min-width: 768px) {
.item:nth-child(4n + 1):nth-last-child(4):after,
.item:nth-child(4n + 1):nth-last-child(4):after,
.item:nth-child(4n + 1):nth-last-child(2):after,
.item:nth-child(4n + 1):nth-last-child(1):after{
display: none;  
}
}
<div class="outer">
<h3>Working example - 8 Items</h3>
<div class="wrap">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
</div>
</div>
<div class="outer">
<h3>Working example - 5 Items</h3>
<div class="wrap">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
</div>
</div>
<div class="outer">
<h3>Using normal border</h3>
<div class="wrap">
<div class="item2">Item 1</div>
<div class="item2">Item 2</div>
<div class="item2">Item 3</div>
<div class="item2">Item 4</div>
<div class="item2">Item 5</div>
</div>
</div>

Answer №1

You have the option to utilize the :before pseudo-element and eliminate the need for the display:none declarations :

.outer{
  background-color: #ccc;
  margin-bottom: 15px;
}

.wrap{
  overflow: hidden;/* hiding first row of item:before */
  /* flex: 4; not necessary here */
  justify-content: space-between;
  flex-flow: row wrap;
  width: 80%;
  margin: 0 auto;
  background-color: #cdcdcd;
  display: flex;
}

.item{
  width: 23%;
  padding-bottom: 30px;
  margin-bottom: 30px;
  position: relative;
}
.item2{/* adding variety, not crucial */
  width: 23%;
  padding : 30px 0;
  margin-bottom: -10px;
  position: relative;
  border-bottom: 1px solid red;
}
.item:nth-child(4n + 1):before{
  content: "";
  position: absolute;
  left: 0;
  width: 500%;
  top: -30px;
  border-bottom: 1px solid red;
}
<div class="outer">
  <h3>Example with 8 Items</h3>
  <div class="wrap">
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="item">Item 5</div>
      <div class="item">Item 6</div>
      <div class="item">Item 7</div>
      <div class="item">Item 8</div>
  </div>
</div>
<div class="outer">
  <h3>Example with 5 Items</h3>
  <div class="wrap">
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="item">Item 5</div>
  </div>
</div>
<div class="outer">
  <h3>Using regular borders</h3>
  <div class="wrap">
      <div class="item2">Item 1</div>
      <div class="item2">Item 2</div>
      <div class="item2">Item 3</div>
      <div class="item2">Item 4</div>
      <div class="item2">Item 5</div>
  </div>
</div>


edit

You can set a breakpoint as well and utilize each item to draw a line

.outer{
  background-color: #ccc;
  margin-bottom: 15px;
}

.wrap{
  overflow: hidden;/* will hide first row of item:before */
  /* flex: 4; i do not see the use here */
  justify-content: space-between;
  flex-flow: row wrap;
  width: 80%;
  margin: 0 auto;
  background-color: #cdcdcd;
  display: flex;
}

.item{
  width: 23%;
  margin: 29px 1% 31px;
  position: relative;
}
.item2{/* just to do it different , don ' t mind that part */
  width: 23%;
  padding : 30px 0;
  margin-bottom: -10px;
  position: relative;
  border-bottom: 1px solid red;
}
.item:before{
  content: "";
  position: absolute;
  left: -20%;
  width: 800%;
  top: -30px;
  border-bottom: 1px solid red;
}
.brkpt .item  {
  min-width:60px;
  max-width:100px;
  background:gray
  }
<div class="outer">
  <h3>Working example - 8 Items</h3>
  <div class="wrap">
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="item">Item 5</div>
      <div class="item">Item 6</div>
      <div class="item">Item 7</div>
      <div class="item">Item 8</div>
  </div>
</div>
<h3>Working example - 16 Items breaking points every 120px average</h3>
  <div class="wrap brkpt">
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="item">Item 5</div>
      <div class="item">Item 6</div>
      <div class="item">Item 7</div>
      <div class="item">Item 8</div>
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="item">Item 5</div>
      <div class="item">Item 6</div>
      <div class="item">Item 7</div>
      <div class="item">Item 8</div>
  </div>
</div>
<div class="outer">
  <h3>Working example - 5 Items</h3>
  <div class="wrap">
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="item">Item 5</div>
  </div>
</div>
<div class="outer">
  <h3>Using normal border</h3>
  <div class="wrap">
      <div class="item2">Item 1</div>
      <div class="item2">Item 2</div>
      <div class="item2">Item 3</div>
      <div class="item2">Item 4</div>
      <div class="item2">Item 5</div>
  </div>
</div>

Answer №2

After considering it further, I have come up with a responsive solution that I believe is the most effective method... To view 4 columns, simply click on the full page button.

.outer{
  background-color: #ccc;
  margin-bottom: 15px;
}

.wrap{
  overflow: hidden;
  flex: 4;
  justify-content: space-between;
  flex-flow: row wrap;
  width: 80%;
  margin: 0 auto;
  background-color: #cdcdcd;
  display: flex;
}
.full{
  width: 100%;
  background-color: red;
  margin-bottom: 30px;
  height: 1px;
  display: none;
}
@media (max-width: 768px) {
  .visible-small{
    display: block;
  }
}
@media (min-width: 768px) {
  .visible-large{
    display: block;
  }
}
.item{
  width: 23%;
  margin-bottom: 30px;
  position: relative;
}
<div class="outer">
  <h3>Using extra div</h3>
  <div class="wrap">
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="full visible-small"></div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="full visible-large visible-small"></div>
      <div class="item">Item 5</div>
  </div>
</div>
<div class="outer">
  <h3>Using extra div</h3>
  <div class="wrap">
      <div class="item">Item 1</div>
      <div class="item">Item 2</div>
      <div class="full visible-small"></div>
      <div class="item">Item 3</div>
      <div class="item">Item 4</div>
      <div class="full visible-large visible-small"></div>
      <div class="item">Item 5</div>
      <div class="item">Item 6</div>
      <div class="full visible-small"></div>
      <div class="item">Item 7</div>
      <div class="item">Item 8</div>
      <div class="full visible-large visible-small"></div>
      <div class="item">Item 9</div>
  </div>
</div>

Answer №3

When it comes to small devices, using this method can present some serious challenges. I recommend utilizing the following image:

https://i.sstatic.net/MbA0C.png

You can set this image as the background for the entire menu (<div class="wrap"), making necessary adjustments for the height of menu items.

.wrap{
   background-image: url(IMAGE-URL);
   background-repeat: repeat;
 }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

'Dynamic' styling in Next.js using conditional CSS

I am exploring ways to style elements based on their parameters. I have been searching for terms like "conditional css react" and "implementing conditional styles in react with css". Here is a snippet of my code: e.g. <div class="ChatComponent_ ...

What are the steps to modify the MIME type in order for the browser to correctly display a CSS

I'm encountering an issue where my CSS code is not rendering in the browser, and it seems to be related to MIME types (which I'm not familiar with). I am using EJS as a template engine. The error I see in the console is... Refused to apply sty ...

Is there a way for me to make the two form fields expand and fill the gap between them?

I've created a form with the first name and last name fields displayed horizontally next to each other, as shown in the image. When a user clicks on a field, it should change color (still pending coding). However, there seems to be an unwanted gap be ...

Sending a PHP variable to a JavaScript function

When attempting to pass a value to a JavaScript function by clicking a link, I encountered an error message: Uncaught SyntaxError: Unexpected identifier The following is the code snippet: <?php include_once("php_includes/check_login_status.php") ...

What is the reason behind the malfunction of the float?

Having an issue with the "1" form not extending to 100% width next to the "Tickets". Here is a visual representation of the problem: View how it currently looks here. html: <section id="main_content"> <div class="left inner"> ...

Set up a custom JavaScript function to automatically refresh a webpage

I am in the process of setting up a JavaScript function to refresh on a specific webpage. The website utilizes an overarching JS and CSS framework, but I desire this particular function to load in a unique manner. The JS function within the framework dyna ...

Creating a vertical navigation menu and displaying its submenu on corresponding pages in a horizontal layout

I'm struggling to design a navigation layout for my website where I want to display the main menu items like this: Menu 1 Menu 2 Menu 3 Menu 4 Menu 5 and have their respective sub-menus displayed horizontally on their main menu pages like this: ...

"Customize Bootstrap layout to have a stable width for desktop screens and a flexible width for

I received a psd design with a background for html5-bootstrap development that needed to be responsive. The original psd had a width of over 1200px, with the main container around 900px wide and the background displaying correctly. When converting to HTML ...

Mastering the application of map, filter, and other functions in Angular using Observables

After creating this Observable: const numbers$:Observable<any>=Observable.create((observer)=>{ for(let i=0;i<5;i++) observer.next(i); }) I attempted to use map and filter as shown below: numbers$.pipe(map(x=>{x+110})).subscr ...

Tips for spinning HTML5 Canvas's background image and adjusting the zoom with a slider

As someone who is new to the world of coding, I have a few goals in mind: First and foremost, I want to create a canvas. I also aim to add a background image to the canvas. Importantly, this background image should be separate from any foreground images ...

Guide on how to showcase an array in a string format using table rows in JavaScript or jQuery

After making an AJAX call to a PHP database, I receive a String as a result in my script. The format of the string is shown below: array(4) { [0]=> array(3) { ["id"]=> string(3) "181" ["number"]=> ...

How can you utilize CSS to automatically generate section numbers, specifically for multiple sections?

Is it possible to automatically generate section numbering in CSS only when there are multiple sections present? I discovered that using CSS, one can create automatic numbering for sections. body { counter-reset: section } h2 { counter-reset: sub-section ...

How can I prevent opening duplicate tabs of the same website simultaneously?

Is there a way to prevent users from accessing the same website page from multiple tabs? Could this be accomplished using JavaScript? ...

Is it possible to create a fading effect on an image using a border-radius of 50%?

Struggling with fading out an image that's circular in shape due to the border-radius: 50%. <section id="main"> <h1>Non-Important-Text</h1> <h4> it's all fun and games until you can't find a damn sol ...

The accuracy of IE9 <section> is not quite up to par

When viewing This Page in IE9, the element section#tcs-website-content appears as 990px wide even though its CSS property is set to width: 100%. This occurs despite all parent elements also having a width of 100%, resulting in a browser width of 1024px. A ...

Looking for assistance in personalizing a Tab slider plugin with jQuery and CSS?

Hi there! I stumbled upon this post (http://stackoverflow.com/questions/7645702/tab-slide-out-using-jquery-need-more-than-one) while experimenting with a plugin. I'm curious if anyone here knows how to integrate this plugin into a menu. My idea is to ...

What is the best way to retrieve the href and id values dynamically from a card in React JS?

Hello everyone, I'm new to stackoverflow and still in the process of learning how to code. Please bear with me if this question sounds like a newbie one. My question is about having dynamic values for href and id when mapping data using axios to crea ...

The custom HTML menu implementation is causing the jQuery autocomplete to lose its "Select" functionality

Seeking assistance in implementing jQuery autocomplete with a custom drop down menu. I have managed to customize menu items using the data()._renderItem method (which is currently commented out), however, this approach disables the menu "Select" function ...

How can I apply various textures in three.js?

Hello there! I'm diving into the world of threejs and currently working on a block game similar to Minecraft. Instead of relying solely on objects, I've decided to build my program using planes (specifically the PlaneGeometry class). As I wrap ...

What is the best way to display multiple HTML files using node.js?

click here to see the image Here is my server.js file. Using express, I have successfully rendered the list.html and css files on my server. However, I am encountering an issue when trying to navigate from list.html to other html files by entering localho ...