How do you (dynamically) justify cells to the right with CSS Grid? - css

I have a 2 col 2 row grid with 3 of the items/cells occupied.
I would like it to appear like:
A
B
C
I know I can use grid-column: 2; on the 3rd item but that doesn't really help me if I have a dynamic number of rows and items.
I'm also aware of direction: rtl; on the wrapping element, but this obviously reverses the order which is not idea, eg:
B
A
C
I've tried justify-content: right/end/flex-end but no luck there either.
I am aware I can achieve the above with flex-box but was just curious if there was a way with CSS grid?

Since you only have two columns you can write a specific selector and target the last item
.box {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 5px;
border: 1px solid;
margin: 10px;
}
.box div {
height: 50px;
background: red;
}
/* place the last item at last column */
.box div:last-child {
grid-column-end: -1;
}
<div class="box">
<div></div>
<div></div>
</div>
<div class="box">
<div></div>
<div></div>
<div></div>
</div>
<div class="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="box">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Related

Responsive checkerboard grid in CSS?

This snippet contains a responsive grid. As you change the screen width the number of columns varies automatically. Sometimes there is an even number of columns, sometimes there is an odd number. When there is an odd number of columns, the cells alternate colours like a checkerboard, but when there is an even number of columns, they do not. Is there any way to achieve the checkerboard effect for even numbers of columns as well as odd numbers? Does it require Javascript, or can it be done using CSS alone?
body {
margin: 0;
}
.checkers {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(8em, 1fr));
padding: 1em;
gap: 1em;
}
.checkers>div {
background-color: red;
aspect-ratio: 1/1;
}
.checkers>div:nth-child(even) {
background-color: blue;
}
<div class="checkers">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
If you can omit the use of 1fr and consider fixed width elements, you can do this using some background trick:
.checkers {
display: grid;
grid-template-columns: repeat(auto-fit, 8em);
padding: 1em;
gap: 1em;
position: relative; /* Relative on the main container */
z-index:0;
}
.checkers > div {
aspect-ratio: 1;
clip-path: inset(0); /* clip the pseudo element to element*/
}
.checkers > div:before {
content:"";
position: absolute;
z-index:-1;
inset: 1em; /* same as padding */
/* create a checkboard pattern using gradient
18em = (8em + 1em[gap])*2
*/
background: repeating-conic-gradient(red 0 25%,blue 0 50%) 0 0/18em 18em;
}
body {
margin: 0;
background: pink;
counter-reset: num;
}
.checkers div:after {
content: counter(num);
counter-increment: num;
color:#fff;
font-weight:900;
font-size: 25px;
}
<div class="checkers">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
As far as I can tell, this cannot be done for an even number of columns. What you can do is ensure there is always an odd number of columns. You will need to explicitly set an odd number of columns for grid-template-columns, which can be adjusted with media queries.
In this snippet I have borrowed the breakpoints from Bootstrap as a starting point. I have initially set the grid to have 3 columns minimum (grid-template-columns: repeat(3, 1fr);), then increment by 2 (next odd number) at each breakpoint up to 13 columns:
body {
margin: 0;
}
.checkers {
display: grid;
grid-template-columns: repeat(3, 1fr);
padding: 1em;
gap: 1em;
overflow: hidden;
}
.checkers>div {
background-color: red;
aspect-ratio: 1/1;
}
.checkers>div:nth-child(even) {
background-color: blue;
}
#media (min-width: 576px) {
.checkers {
grid-template-columns: repeat(5, 1fr);
}
}
#media (min-width: 768px) {
.checkers {
grid-template-columns: repeat(7, 1fr);
}
}
#media (min-width: 992px) {
.checkers {
grid-template-columns: repeat(9, 1fr);
}
}
#media (min-width: 1200px) {
.checkers {
grid-template-columns: repeat(11, 1fr);
}
}
#media (min-width: 1400px) {
.checkers {
grid-template-columns: repeat(13, 1fr);
}
}
<div class="checkers">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
You can adjust the breakpoint sizes to be multiples of your grid square sizes to get it dialed in to your liking.

CSS Grid Margin Top for entire columns

Is it possible to shift all 2nd/even grid colums as a whole like in the image using CSS grid?
My current css code situation is very simple, it looks like this:
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
I am trying to achive something that looks like the following image:
You can use the :nth-child() pseudo class to achieve this. This is how I approached it:
<div class="container">
<div class="cards">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
</div>
.container{
max-width: 900px;
margin: 0 auto;
height: auto;
}
.cards{
display: grid;
place-items: center;
grid-template-columns: repeat(4,1fr);
gap: 5px;
}
.card{
width: 200px;
height: 250px;
border: 3px solid black;
}
.card:nth-child(2n-2){
position: relative;
top: 100px;
}
/* or use margin */
/*
.card:nth-child(2n-2){
margin-top: 100px;
}
*/
Here is the codepen link: https://codepen.io/glenhug/pen/QWrWXJY
Also this is post had a nice explanation: How to target a specific column or row in CSS Grid Layout?
This might do the trick.
.grid-container {
width: min-content;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
}
.grid-container > div {
width: 50px;
height: 50px;
border: 1px solid black;
}
.grid-container div:nth-child(2n) {
position: relative;
top: 15px;
}
<div class='grid-container'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Not with CSS grid but combining inline-block, float and shape-outside you can do it and it will be responsive and works with any element.
Find all the details in my article: https://css-tricks.com/hexagons-and-beyond-flexible-responsive-grid-patterns-sans-media-queries/
Here is a demo:
.main {
display:flex;
--s: 100px; /* size */
--r: 1; /* ratio */
--mv: 4px; /* margin */
--vc: calc(var(--s) * var(--r) * .5);
--mh: calc(var(--mv) + var(--s)/2);
--f: calc(2*var(--s)*var(--r) + 4*var(--mv) - 2*var(--vc) - 2px);
}
.container {
font-size: 0; /*disable white space between inline block element */
}
.container div {
width: var(--s);
margin: var(--mv) var(--mh);
height: calc(var(--s)*var(--r));
display: inline-block;
font-size: initial;
background: red;
margin-bottom: calc(var(--mv) - var(--vc));
}
.container div:nth-child(odd) {
background: green;
}
.container::before {
content: "";
width: calc(var(--s)/2 + var(--mh));
float: left;
height: 135%;
shape-outside: repeating-linear-gradient(
#0000 0 calc(var(--f) - 2px),
#000 0 var(--f));
}
<div class="main">
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>

Flexbox layouting with space-between

i'm working with flexbox with justify-content: space-between & flex-wrap: wrap,
so each item separates as far as possible.
But i want to if the container space is not sufficient, the item(s) are wrapped to the next row
but keep the items placement symmetrical (centered).
See the illustration below:
Update: the alone box is might in somewhere row:
It works for space-around & space-evenly but not for space-between.
Any idea for making this behavior? Maybe using display: grid can archive similar result.
html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<p>symmetrical => works:<p/>
<div class="container long">
<div></div>
<div></div>
<div></div>
</div>
<hr />
<p>non symmetrical => fail:<p/>
<div class="container short">
<div></div>
<div></div>
<div></div>
</div>
<hr />
<p>symmetrical => works:<p/>
<div class="container med">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<hr />
<p>non symmetrical => fail:<p/>
<div class="container med">
<div></div>
<div></div>
<div></div>
<div class="weird"></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
css:
.container>*{
inline-size: 100px;
block-size: 50px;
background: blue;
}
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
row-gap: 10px;
background: orange;
margin: 20px;
}
.long {
inline-size: 400px;
}
.short {
inline-size: 250px;
}
.med {
inline-size: 350px;
}
.weird {
inline-size: 300px;
}
See the sandbox here
You can achieve this by putting an extra css rule on the last child of .short container, but this is a hack. space-between is expected to work like this.
.short div:last-child {margin:0 auto;}

CSS: How to style last grid row of a dynamic number of items?

I have my first row as 22px and using grid-auto-rows to make the subsequent rows 70px. Is there a way to make the last row also 22px without using template since I won't know how many div's are in it at the time?
.cont {
background: grey;
height: 600px;
display: grid;
grid-template-rows: 22px;
grid-auto-rows: 70px;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 3px;
}
.cont div {
background: red;
}
<div class="cont">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
If you will always have 3 columns keep the template row auto and define the height on the elements. All should have 70px except the first 3 and the last 3 under certain conditions.
.cont {
background: grey;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 3px;
margin:10px;
}
.cont div {
background: red;
height:70px;
}
.cont div:nth-child(1), /* 1st */
.cont div:nth-child(2), /* 2nd */
.cont div:nth-child(3), /* 3rd */
.cont div:nth-last-child(1), /* last one */
.cont div:nth-last-child(2):not(:nth-child(3n + 3)), /* before the last if not the last one of a row*/
.cont div:nth-last-child(3):nth-child(3n + 1){ /* before the two last only if the fisrt one of a row*/
height:22px;
}
<div class="cont">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="cont">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="cont">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
If you know how many columns your layout is going to have (in my example, it has 3 like yours), you can use the :nth-child() and :last-child() psuedo-class CSS selectors and do something like this:
.cont > div:nth-child(3n+1):nth-last-child(-n+3),
.cont > div:nth-child(3n+1):nth-last-child(-n+3) ~ div {
height:22px;
}
This CSS will always target the individual divs in the last row of your 3 column grid.
Good article on this technique here: https://keithclark.co.uk/articles/targeting-first-and-last-rows-in-css-grid-layouts/

Add an overlay div inside nested flex containers (3x3 grid) in a specific cell

I have a 3x3 grid with flex-box concept, inside of each cell it has another 3x3 grid.
I was trying to put an Overlay over the Inner grid in one cell, but I didn't find how to do it.
I found some examples like this one
Overlay / hover a div in flexbox container div
but it don't work in nested flex-box, or I don't know how to set them up.
here is the html, the grid has just two cell to take up less space, it actually is done with JQuery but for the example lets use only 2.
.Region{
position: absolute;
top: 10px;
left: 10px;
width: 500px;
height: 500px;
border: 5px double black;
display: flex;
}
.FlexContainer{
display: flex;
flex-direction: column;
flex-grow: 1;
}
.FlexContainer > div{
flex-grow: 1;
flex-basis: 0;
border: 3px solid blue;
display: flex;
flex-direction: row;
margin: 5px;
}
.FlexContainer > div > div{
flex-grow: 1;
flex-basis: 0;
border: 1px solid red;
margin: 3px;
display:flex;
flex-direction: row;
}
.Overlay{
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(013, 130, 230, 0.5);
cursor: not-allowed;
}
<div class="Region">
<div class="FlexContainer">
<div>
<div>
<div class="FlexContainer">
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div>
<div class="FlexContainer">
<div class="Overlay"></div>
<div>
<div>
</div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<div></div>
<div></div>
</div>
</div>
</div>
I have tried with the Overlay inside and outside the Inner FlexContainer, but didn't work.
Finally got it to work, indeed the parent container must have relative position for it to work, so there is two change, one in the FlexContainer and other in the Overlay
.FlexContainer{
position:relative; <-- ADD THIS
display: flex;
flex-direction: column;
flex-grow: 1;
}
.FlexContainer .Overlay {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0px;
width: 100%;
height: 100%;
background-color: rgba(013, 130, 230, 0.5);
cursor: not-allowed;
}
Code Pen solution https://codepen.io/anon/pen/dKaXqg
Credits to user Pogany from the css-tricks web site
CSS-TRICKS thread: https://css-tricks.com/forums/topic/add-and-overlay-div-in-nested-flex-box-container/#post-273437

Resources