How to alternate grid pattern for unknown number of items - css

I want to create a repeating grid. Three items per row.
First row: item one spans 2 cols and 2 rows. Followed by item two and item three spanning 1 col and 1 row.
Second row would be inverse: item one and item two span 1 col and 1 row. item 3 spans 2 cols and 2 rows.
See image below for what I'm trying to do. I wanting this for an infinite amount of rows and items.
.container {
width: 100%;
margin: 0 auto;
max-width: 80%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
}
h2 {
font-size: 16px;
font-family: sans-serif;
font-weight: normal;
}
.item {
background: pink;
}
.item:nth-child(3n+1) {
grid-column: auto /span 2;
grid-row: auto /span 2;
}
.item:nth-child(3n+2),
.item:nth-child(3n+3) {
/* grid-area: 1 / 3 / 2 / 4; */
border: 1px solid red;
grid-column: auto /span 1;
grid-row: auto /span 1;
}
.container.two .item:nth-child(3n+1) {
border: 5px solid yellow;
grid-area: 1 / 1 / 2 / 2;
}
.container.two .item:nth-child(3n+2) {
border: 5px solid orange;
grid-area: 2 / 1 / 3 / 2;
}
.container.two .item:nth-child(3n+3) {
border: 5px solid red;
grid-area: 1 / 2 / 3 / 4;
}
img {
max-width: 100%;
}
<h2>
I have this using "grid-column" and "grid-row"...
</h2>
<div class="container">
<div class="item">
First
</div>
<div class="item">
Second
</div>
<div class="item">
Third
</div>
</div>
<hr />
<h2>
I want to alternate that, but I only understand how to with "grid-area"...
</h2>
<div class="container two">
<div class="item">
First
</div>
<div class="item">
Second
</div>
<div class="item">
Third
</div>
</div>
<hr/>
<h2>
But I want to have an unlimited amount of items alternate those patterns...
</h2>
<div class="container">
<div class="item">
First
</div>
<div class="item">
Second
</div>
<div class="item">
Third
</div>
<div class="item">
First
</div>
<div class="item">
Second
</div>
<div class="item">
Third
</div>
<div class="item">
First
</div>
<div class="item">
Second
</div>
<div class="item">
Third
</div>
<div class="item">
First
</div>
<div class="item">
Second
</div>
<div class="item">
Third
</div>
<div class="item">
First
</div>
<div class="item">
Second
</div>
<div class="item">
Third
</div>
</div>

You can do it like below:
.container {
display:grid;
grid-template-columns:repeat(3,1fr); /* 3 columns */
grid-auto-flow:dense; /* make sur to fill all the area */
grid-auto-rows:50px; /* height of one row */
grid-gap:5px;
}
.container * {
background:red;
}
/* the pattern repeat each 6 elements */
.container :nth-child(6n + 1),
.container :nth-child(6n + 6){
grid-area:span 2/span 2; /* 1 and 6 take 2 rows and 2 columns */
}
.container :nth-child(6n + 5){
grid-column:1; /* 5 at first column */
}
<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>

Related

Alternating rows using css grids and nth-child

I am working on a product grid with an alternating row pattern like this.
The color containers represent what I think the rows should look like.
Basically there are two products on the first row, and one product on the second row, repeating infinitely. I've been trying to do it with css grids + nth child, but I can't seem to get it right. Here's what I have so far:
.container {
display: grid;
grid-template-columns: 1fr 2fr;
grid-column-gap: 0;
width: 70vw;
margin: 0 auto;
}
.item:nth-child(3n+3) {
grid-column: auto / span 2;
background-color: #e2a7de;
}
/*just for debugging*/
.container{grid-gap:5px;}
.item{background-color: #ffa900;padding: 10px;text-align:center;}
<div class="container">
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
</div>
My brain can't wrap around combining grids and nth-child to create this layout. I'm also open to a better way of creating this 2-1-2 pattern if anyone has other suggestions. Thank you!
You can simplify your code like below:
.container {
display: grid;
grid-auto-columns: 1fr; /* all columns equal */
width: 70vw;
margin: 0 auto;
}
.item:nth-child(3n) {
grid-column: span 2; /* span and create two columns*/
background-color: #e2a7de;
}
/*just for debugging*/
.container{grid-gap:5px;}
.item{background-color: #ffa900;padding: 10px;text-align:center;}
<div class="container">
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
</div>
Update the grid-template-columns to be 1fr 1fr
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 0;
width: 70vw;
margin: 0 auto;
}
.item:nth-child(3n+3) {
grid-column: auto / span 2;
background-color: #e2a7de;
}
/*just for debugging*/
.container{grid-gap: 5px;}.item {background-color: #ffa900;padding: 10px;text-align: center;}
<div class="container">
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
<div class="item">
X
</div>
</div>

Bootstrap grid system 1 row with two columns into 2 rows

So I have this layout on my grid
But as the width goes smaller I want to change to this layout
So far I have it like this
.row > div {
border: 1px solid black
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class='row'>
<div class="col-md-6">
1
</div>
<div class="col-md-5">
<div class='row'>
<div class="col-md-12">
2
</div>
<div class="col-md-12">
3
</div>
</div>
</div>
</div>
I think best practice way CSS Grid layout to essay and customizable
.grid > div {
border: 1px solid black;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
#media (min-width: 768px) {
.one {
grid-row: 1/3;
}
}
.three {
grid-column: 1/3;
}
#media (min-width: 768px) {
.three {
grid-column: 2/3;
}
}
<div class='grid'>
<div class="one">
1
</div>
<div class="two">
2
</div>
<div class="three">
3
</div>
</div>
like this?
<div class='row'>
<div class="col-md-6 col-sm-6">
1
</div>
<div class="col-md-6">
<div class='row'>
<div class="col-md-12 col-sm-6">
2
</div>
<div class="col-md-12 col-sm-12">
3
</div>
</div>
</div>
</div>

I want a div of specific height to grow in width as necessary to accommodate text

As shown in the example bellow, I want a div of specific height to grow in width only as much as necessary to accommodate it's text, but I can't do it
I want it to look like this
body{
overflow-x: scroll;
}
.container{
display: flex;
flex-direction: row;
width: max-content;
}
.item{
width: min-content ;
max-height: 3em;
border: 1px solid red;
}
<body>
<div class="container" >
<div class="item"> sid jkodasjkadf kadsf kas</div>
<div class="item"> salkf hjahsadkjhfgadsakjsl</div>
<div class="item"> saf nasd kmfgdn skjdsj</div>
<div class="item"> sjfn sdnf sdmfosdj md faikmoa fia</div>
<div class="item"> siiojasd oiasdi </div>
<div class="item"> alksj fksdafja</div>
<div class="item"> sid jkodas jkadf kadsf kas</div>
<div class="item"> salkf hjahsadkjhfga dsakjsl</div>
<div class="item"> saf nasd kmfgdn skjdsj</div>
<div class="item"> sjfn sdnf sdmfosdj md faikmoa fia</div>
<div class="item"> siiojasd oiasdi </div>
<div class="item"> alksj fksdafja</div>
</div>
</body>
try this,
.container{
display:grid;
grid-template-columns:repeat(3,1fr);
}
.item{
max-height: 3em;
border: 4px solid red;
padding:1rem;
}

Automatic offset / alignment in CSS grid?

I've a five column grid, which has in some cases only content in three columns. The content should be right aligned, so that there will be an offset of two columns. Is there a possibility to do this automatically? Actually I'm doing it with grid-column-start: 3, grid-column-start: 4, grid-column-start: 5:
.grid {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 1rem;
margin: 2rem 0;
}
.col {
text-align: center;
padding: 2rem;
background-color: lightblue;
}
<div class="grid">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
</div>
<p>Actual syntax / layout:</p>
<div class="grid">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
<p>Should behave like this:</p>
<div class="grid">
<div class="col" style="grid-column-start: 3;">1</div>
<div class="col" style="grid-column-start: 4;">2</div>
<div class="col" style="grid-column-start: 5;">3</div>
</div>
Thought about something like justify-items: end but thats for the alignment of the content inside the column. For me I'm looking like even more a solution as it's behaviour in flexbox (justify-content), but I don't want to use flexbox ;)
Regards,
Markus
You can handle each case alone since they aren't a lot:
.grid {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 1rem;
margin: 2rem 0;
}
.col {
text-align: center;
padding: 2rem;
background-color: lightblue;
}
.col:nth-last-child(1):first-child {
grid-column-end: -1;
}
.col:nth-last-child(2):first-child {
grid-column-end: -2;
}
.col:nth-last-child(3):first-child {
grid-column-end: -3;
}
.col:nth-last-child(4):first-child {
grid-column-end: -4;
}
<div class="grid">
<div class="col">1</div>
</div>
<div class="grid">
<div class="col">1</div>
<div class="col">2</div>
</div>
<div class="grid">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
<div class="grid">
<div class="col" >1</div>
<div class="col" >2</div>
<div class="col" >3</div>
<div class="col" >4</div>
</div>
<div class="grid">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
</div>

remove margin bottom from the last line in wrapped elements

How can I keep the margin-bottom only for the elements that are not in the last line ?
.container {
display: flex;
flex-flow: row wrap;
background: green;
justify-content: space-between;
}
.block {
height: 60px;
max-width: calc((100% - (12px * 2)) / 3);
flex-basis: calc((100% - (12px * 2)) / 3);
background: orange;
box-shadow: inset 0 0 0 3px black;
margin-bottom: 12px;
}
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
Thanks in advance.
This is what you are looking for:
.container .block:nth-last-child(-n+3){
margin-bottom: 0px;
}
for flex and grid, you can use the gap propertie to avoid playing with margins:
https://developer.mozilla.org/en-US/docs/Web/CSS/gap
The gap CSS property sets the gaps (gutters) between rows and columns. It is a shorthand for row-gap and column-gap.
Applies to multi-column elements, flex containers, grid containers
see https://www.caniuse.com/?search=gap for support
to set 3 elements on a line, give a min-width bigger than 25% and set them to grow via flex-grow. for the demo i used 26%, should be small enough to leave room for the gaps .
Demo of your code witout margins but still a gap in between elements
.container {
display: flex;
flex-flow: row wrap;
background: green;
gap: 12px;
/* see https://www.caniuse.com/?search=gap for support */
}
.block {
height: 60px;
flex: 1 1 0; /* or flex:1; */
/* to stretch them at the most and even their sizes*/
min-width: 26%;
/* it cannot be more than 3 on a row */
background: orange;
box-shadow: inset 0 0 0 3px black;
padding:5px; /* padding is fine */
}
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
<hr>
<div class="container">
<div class="block">A single line
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
<hr>
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">a second and last line
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
<hr>
<div class="container">
<div class="block">2 blocks , is that okay ?
</div>
<div class="block">
</div>
</div>
You can also use CSS grid:
.container {
display: grid;
grid-template-columns:repeat(3,1fr);
grid-gap:12px;
background: green;
}
.block {
height: 60px;
background: orange;
box-shadow: inset 0 0 0 3px black;
}
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>

Resources