Alternating rows using css grids and nth-child - css

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>

Related

Css grid without subgrid [duplicate]

I have the following table design, laid out with CSS Grid (see first snippet).
Is it possible to make all columns of the same type/class (e.g. .Table_col_day) as wide as the column of that type/class with the widest content, with CSS/without JS? The solution doesn’t have to be CSS Grid based.
See the second code snippet for a quick JS-based solution, to illustrate what I'd like to do.
.Table__row {
background-color: plum;
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr;
}
.Table__row:nth-of-type(even) {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__day">Mon</div>
<div class="Table__time">10am</div>
<div class="Table__title">Some event</div>
</div>
<div class="Table__row">
<div class="Table__day">Tue</div>
<div class="Table__time">12:30pm</div>
<div class="Table__title">Another event</div>
</div>
<div class="Table__row">
<div class="Table__day">Wed</div>
<div class="Table__time">9:00am</div>
<div class="Table__title">A different event</div>
</div>
</div>
Javascript-based solution (determine widest column content, then manually set grid column styles of row element)
function resizeColumns(SELECTOR) {
const colElements = document.querySelectorAll(SELECTOR);
//////
const widths = [...colElements].map(el => el.querySelector('span').offsetWidth);
const width_max = Math.max(...widths);
//////
for(let col of colElements) {
col.parentNode.style.gridTemplateColumns = `${width_max}px 0.5fr 1fr`;
}
}
resizeColumns('.Table__col_day');
.Table__row {
background-color: plum;
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr;
}
.Table__row:nth-of-type(even) {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__col_day">
<span>Mon</span>
</div>
<div class="Table__col_time">
<span>10am</span>
</div>
<div class="Table__col_title">
<span>Some event</span>
</div>
</div>
<div class="Table__row">
<div class="Table__col_day">
<span>Tue</span>
</div>
<div class="Table__col_time">
<span>12:30pm</span>
</div>
<div class="Table__col_title">
<span>Another event</span>
</div>
</div>
<div class="Table__row">
<div class="Table__col_day">
<span>Wed</span>
</div>
<div class="Table__col_time">
<span>9:00am</span>
</div>
<div class="Table__col_title">
<span>A different event</span>
</div>
</div>
</div>
You said it at the beginning: "table design" so use table
.Table {
display: table;
width: 100%;
}
.Table__row {
background-color: plum;
display: table-row;
}
.Table__row > * {
display: table-cell;
white-space: nowrap;
}
.Table__row > *:not(.Table__day) {
width: 50%;
}
.Table__row:nth-of-type(even) {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__day">Mon</div>
<div class="Table__time">10am</div>
<div class="Table__title">Some event</div>
</div>
<div class="Table__row">
<div class="Table__day">Tue</div>
<div class="Table__time">12:30pm</div>
<div class="Table__title">Another event</div>
</div>
<div class="Table__row">
<div class="Table__day">Wed</div>
<div class="Table__time">9:00am</div>
<div class="Table__title">A different event</div>
</div>
</div>
Or consider display:contents if you want to keep display:grid;
.Table {
display: grid;
grid-template-columns: auto 1fr 1fr;
}
.Table__row {
display: contents;
}
.Table__row > * {
background-color: plum;
}
.Table__row:nth-of-type(even) > * {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__day">Mon</div>
<div class="Table__time">10am</div>
<div class="Table__title">Some event</div>
</div>
<div class="Table__row">
<div class="Table__day">Tue</div>
<div class="Table__time">12:30pm</div>
<div class="Table__title">Another event</div>
</div>
<div class="Table__row">
<div class="Table__day">Wed</div>
<div class="Table__time">9:00am</div>
<div class="Table__title">A different event</div>
</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>

How to alternate grid pattern for unknown number of items

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>

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>

Resources