Can I make a CSS grid with dynamic number of rows or columns?
Okay, after reading the MDN reference, I found the answer! The key to dynamic rows (or columns) is the repeat
property.
const COLORS = [ '#FE9', '#9AF', '#F9A', "#AFA", "#FA7"];
function addItem(container, template) { let color = COLORS[_.random(COLORS.length - 1)]; let num = _.random(10000); container.append(Mustache.render(template, { color, num }));}
$(() => { const tmpl = $('#item_template').html() const container = $('#app'); for(let i=0; i<5; i++) { addItem(container, tmpl); } $('#add_el').click(() => { addItem(container, tmpl); }) container.on('click', '.del_el', (e) => { $(e.target).closest('.item').remove(); });});
.container { width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(auto-fill, 120px); grid-row-gap: .5em; grid-column-gap: 1em;}
.container .item {}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div id="app" class="container"></div>
<button id="add_el">Add element</button>
<template id="item_template"> <div class="item" style="background: {{color}}"> <p>{{ num }}</p> <p> <button class="del_el">Delete</button> </p> </div></template>
CSS grid with dynamic number of rows and adjustable width
Make only the red container resizable with an initial width equal to 50% and use flex-grow:1
on the green container
function addCell(color) {
let container = document.getElementById(color + "-container");
let cell = document.createElement("div");
cell.innerText = color;
container.appendChild(cell).className = "container-item";
}
#container {
border: 1px solid #ddd;
display: flex;
gap: 10px;
padding: 10px;
height: 50vh;
resize: vertical;
overflow: auto;
}
#green-container,
#red-container {
display: grid;
overflow: auto;
}
#red-container {
border: 1px solid red;
width: 50%;
resize: horizontal;
}
#green-container {
border: 1px solid green;
flex-grow: 1;
}
.container-item {
padding: 10px;
border: 1px solid black;
}
<button onclick="addCell('red')">add red cell</button>
<button onclick="addCell('green')">add green cell</button>
<div id="container">
<div id="red-container"></div>
<div id="green-container"></div>
</div>
Set CSS Grid number of columns dynamically on the basis of list items
You can use grid-template-rows: repeat to do that like this:
.list {
list-style: none;
display: grid;
grid-template-rows: repeat(15, 45px);
gap: 10px;
grid-auto-flow: column;
}
.list-item {
background: black;
width: 40px;
height: 40px;
margin: 10px;
color: white;
font-size: 12px;
}
<ul class='list'>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
<li class="list-item">
<a>item</a>
</li>
</ul>
Dynamic CSS grid with template-columns: auto and full-width row
Your header
rule sets row to 1, and this limits your grid layout. You need at least 3 rows in order to have one for the header, and two for the full-width element.
Start by removing the
header
rule completely.Then add grid-template-rows to the wrapper.
Change your wrapper to use
repeat()
, this makes the horizontal span work as expected:
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(4, minmax(0, 1fr));
background-color: #fff;
color: #444;
}
- In order to make
full-width
span 2 rows you need at least 3 rows in total. Plus you need to declare your grid-row span like this:
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(4, minmax(0, 1fr));
background-color: #fff;
color: #444;
grid-template-rows: repeat(3, minmax(0, 1fr));
}
.full-width {
grid-column: 1 / -1;
grid-row: span 2 / span 2;
}
- If you want an empty node at the top left corner of the grid, we need to increase the amount of columns to 5. We also need an extra class that pushes the first grid child one column towards the right (the other children will be pushed along):
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(5, minmax(0, 1fr));
background-color: #fff;
color: #444;
grid-template-rows: repeat(3, minmax(0, 1fr));
}
.wrapper:first-child {
grid-column-start: 2;
}
CSS grid - dynamic column at the start of the grid
Yes, you can.
The grid
layout allows you to set multiple elements in the very same defined cell.
You could set .select
and .title
inside the first column and first-row. (similar effect to absolute positionning somehow)
If the .select
(is here) stands ahead the .title
, give the .title
a margin
or a padding
to leave space for the checkbox.
Live example below with and without the .select
box
body {
background: #131418;
margin: 1em;
}
:root {
--extra-section: 70px;
}
.container {
padding: 0.5em;
border: 1px solid silver;
color: silver;
/* grid */
display: grid;
grid-template-columns: 1fr auto repeat(3, minmax(var(--extra-section), auto));
grid-auto-columns: var(--extra-section);
grid-auto-flow: column;
grid-column-gap: 0.5em;
align-items: center;
}
body {
background: #131418;
margin: 1em;
}
:root {
--extra-section: 70px;
}
.container {
padding: 0.5em;
border: 1px solid silver;
color: silver;
/* grid */
display: grid;
grid-template-columns: 1fr auto repeat(3, minmax(var(--extra-section), auto));
grid-auto-columns: var(--extra-section);
grid-auto-flow: column;
grid-column-gap: 0.5em;
align-items: center;
}
.container .select,
.container .title {
grid-column:1;
grid-row:1;
}
.select {position:relative;/* bring it up front to be clickable */}
.container .select + .title {
padding-inline-start:1.5rem;/* or padding-left for ltr direction */
}
<div class="container">
<div class="select">
<label>
<input type="checkbox">
</label>
</div>
<div class="title">
Lorem ipsum dolor sit amet, consectetur
</div>
<div class="people">
<img src="https://i.pravatar.cc/25" />
<img src="https://i.pravatar.cc/25" />
<img src="https://i.pravatar.cc/25" />
</div>
<div class="likes">9</div>
<div class="bookmarks">4</div>
<div class="shares">2</div>
</div>
<hr>
<div class="container">
<div class="title">
Lorem ipsum dolor sit amet, consectetur
</div>
<div class="people">
<img src="https://i.pravatar.cc/25" />
<img src="https://i.pravatar.cc/25" />
<img src="https://i.pravatar.cc/25" />
</div>
<div class="likes">9</div>
<div class="bookmarks">4</div>
<div class="shares">2</div>
</div>
Related Topics
CSS Transition Opacity Fade Background
Looping Animation of Text Color Change Using CSS3
Does IE9 Have a File Size Limit for CSS
How to Apply Vendor Prefixes to Inline Styles in Reactjs
What Does !Default in a CSS Property Value Mean
Is H1 Tag That's Hidden Using Display:None Given Prominence by Search Engines
How to Target Safari for MAC Only
Load Fonts with Webpack and Font-Face
Attribute Property Binding for Background-Image Url in Angular 2
Stop Firefox Dpi Scaling (When Windows Setting Is at 125%)
Does the CSS Flexbox Module Work on Direct Child Elements Only
Css: Is a Hidden Object Clickable
How to Remove the Hash from Compass's Generated Sprite Image Filenames
Webkit Animation Is Leaving Junk Pixels Behind on the Screen
Why Use an HTML5 Semantic Tag Instead of Div