CSS Grid: Dividing items equally based on the number of items present

Currently, I am delving into grid layouts in CSS and experimenting with code to divide a row. Here is the snippet I am playing around with:

.grid-sample {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    row-gap: 4rem;
    padding: 0 5rem; 
}

As far as I comprehend, using grid-template-columns: 1fr ... divides the row into 4 equal columns.

I wonder if there is a way to enhance this code so that it dynamically adjusts based on the number of items present? For instance, when there are only 3 items, can the row automatically split into 3 equal columns instead of grouping them in the first three positions of the 4-column grid?

Your insights will be greatly appreciated!

Answer №1

CSS grid is the way to go for this implementation, utilizing grid-auto-columns and setting grid-auto-flow to columns:

document.querySelector('button').addEventListener('click', (e) => {
  let button = e.currentTarget,
    parent = button.nextElementSibling,
    newChild = document.createElement('span');

  parent.append(newChild);
});
.grid-sample {
  display: grid;
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
  gap: 4rem;
  padding: 0 5rem;
  /* purely to generate content, otherwise irrelevant */
  counter-reset: childCounter;
  margin-block: 1rem;
}

span {
  background-color: hsl(250deg 90% 85% / 1);
  text-align: center;
}

span::before {
  content: counter(childCounter, decimal-leading-zero);
  counter-increment: childCounter;
}
<div class="grid-sample">
  <span></span>
</div>

<div class="grid-sample">
  <span></span>
  <span></span>
  <span></span>
</div>



<div class="grid-sample">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid-sample">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<button type="button">Add span</button>
<div class="grid-sample">
  <span></span>
</div>

JS Fiddle demo.

The drawback of this method is that it continues adding elements into new columns instead of wrapping them onto a new line when reaching maximum space.

In such cases, using flex-box layout could be a better alternative, like this:

document.querySelector('button').addEventListener('click', (e) => {
  let button = e.currentTarget,
    parents = document.querySelectorAll('section > div'),
    newChild = document.createElement('span');

  parents.forEach(
    (el) => el.append(newChild.cloneNode())
  )
});
section {
  box-sizing: border-box;
  inline-size: clamp(40rem, 90%, 1100px);
  margin-inline: auto;
  padding: 0;
}

.grid-sample,
.flex-sample {
  gap: 2rem;
  padding: 0 2rem;
  /* purely to generate content, otherwise irrelevant */
  counter-reset: childCounter;
  margin-block: 1rem;
}

.grid-sample {
  display: grid;
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
}

.flex-sample {
  display: flex;
  flex-flow: row wrap;
  justify-content: start;
}

span {
  background-color: hsl(250deg 90% 85% / 1);
  flex-grow: 1;
  padding: 0.5rem;
  text-align: center;
}

span::before {
  content: counter(childCounter, decimal-leading-zero);
  counter-increment: childCounter;
}
<button>Add new child</button>
<section>
  <div class="grid-sample">
    <span></span>
  </div>
</section>
<section>
  <div class="flex-sample">
    <span></span>
  </div>
</section>

JS Fiddle demo.

For further reading, check out these references:

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

Image set as the background on a website

I recently started working with Groovy and Grails, designing my own personal website. I'm looking to set an image (located in the asset folder) as the background for my index.gsp page. How can I achieve this? ...

How to align Font Awesome icons inside `<span>` vertically with each other

Trying to vertically align multiple font awesome icons: ############################# icon icon icon icon icon icon ############################# <div class="announcement-card-body modal-body card border-0"> <span class="info fa fa-info- ...

The CSS transition will only activate when coupled with a `setTimeout` function

After using JavaScript to adjust the opacity of an element from 0 to 1, I expected it to instantly disappear and then slowly fade back in. However, nothing seems to happen as anticipated. Interestingly, if I insert a setTimeout function before applying th ...

Jquery vertical menu with a dynamic sliding animation from the right side to the left side

Hello everyone, I am looking to have my vertical menu slide from right to left instead of the typical top to bottom sliding that comes with using .toggle() in jQuery. Specifically, when the hamburger menu is clicked, I want the menu to slide out from right ...

iPhone 3GS and 4 not expanding DIVs by 100%

I've been encountering a significant issue with a div that's set to 100%. It displays properly on desktop screens, but on iPhones, there appears to be a gap on the right side. I've attempted to use the following CSS: body { min-width:980p ...

What is the proper way to add my image to CSS?

I'm encountering an issue while trying to insert my picture - I keep receiving a 404 error even though I believe my path is correct. Here are my files: main-menu phone.png _menu.scss Within my _menu.scss file, the following code is p ...

How can I address the variations in CSS appearance between Firefox and Google Chrome?

I'm currently working on a table with two cells in each row just for fun. For the first row, I want both cells to display the same picture. To achieve this, I wrote the following CSS: tr:nth-child(1){ background-image:url("cat.jpg"); background-size: ...

Guide: Previewing uploaded images with HTML and jQuery, including file names

Any constructive criticism and alternative methods for accomplishing this task are welcomed. I am currently working on writing jQuery code that will allow users to preview file(s) without reloading the DOM. To achieve this, I have been using .append() to ...

Panel floating with Bootstrap framework

I have created a unique two-column layout using Bootstrap, utilizing the col-md-6 class. The layout consists of a row with a panel at the top containing a table, a left column panel displaying a list of media items, and a right column panel containing text ...

Struggling to accurately differentiate between a CSS and Bootstrap code

I'm attempting to create a visually appealing underline under the active tab, but I am facing challenges in targeting the specific class. Since I am utilizing bootstrap and unable to adjust the width and margin of text-decoration or recognize an eleme ...

Leveraging JavaScript code repeatedly

Apologies if this question has been asked before, as I couldn't find it. I have an HTML table with images used as buttons: <td> <button class="trigger"> <img src="D:\Elly Research\ CO2858\Presentation\Calypso ...

Iterating through an SVG path multiple times

If I have the arrow below and I want to place it at various locations within the svg: <svg width="400" height="400"> <path transform="translate(150,100)" fill="black" d="M 0.5,0.5 l-100,0 -25,20 25,20 100,0 z" /> <path transform="translate( ...

Elements with inline-block display not aligning horizontally next to each other

I am puzzled as to why the two sections, section.structure and section.specificity, are not aligning properly. It seems that when I reduce the width, they line up correctly at a certain point which I haven't identified yet. My goal is to have the wid ...

The functionality of the CSS transform property seems to be malfunctioning

My HTML and CSS code displays texts in two blocks within a dl element. I attempted to change the ▶ symbol to a different shape using the css transform scale property. However, some browsers only show the triangle in the first column. Why is this happenin ...

Incorporating a bottom line or border within the input field with a specified width

I have been struggling with styling an input field. I added a 1px solid #000 border around it, but now I need to include a thicker black line within the input itself. I tried using border-bottom: 5px solid #000, but that just created a border at the bottom ...

Create a visually appealing collage using CSS without the need for traditional IMG tags

I'm currently working on a fun little project. My goal is to create a photo grid in HTML5 that displays 3x4 pictures (without using Divs) and adding all the images via CSS, meaning no img tag in the HTML file. The challenge is to make this grid respo ...

Utilize the hexadecimal color code as a string within the darken function

When working with a less style, I have a string variable. @colorString: 'DADADA'; I can convert it into a color: @color: ~'#@{colorString}'; Then, I am able to use @color to define a value in a style: div { color: @color } However ...

Creating a proper nth-child CSS for multi-level HTML elements involves understanding the structure of the elements

My current project involves a screen where widgets can be dynamically inserted into the DOM. I am looking to adjust the z-index based on the number of times the class decrement-z-index appears. This is the CSS code I have written in an attempt to achieve ...

Yii2 Gridview - Horizontal Scroll Bar at the Top of the Page

I found a helpful post on Stack Overflow about creating a Yii2 Gridview with a fixed first column (Yii2 : Gridview with fixed first column), and now I'm looking to add a horizontal scrollbar at the top of the grid. My users really appreciate being ab ...

What sets apart element.class from element .class in CSS?

I've been puzzled trying to figure out why my CSS was not applying when I had mydiv .myclass { font-size: 24px !important; } But then I randomly decided to try mydiv.myclass { font-size: 24px !important; } and surprisingly it worked perfectly. Wh ...