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>
Related
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>
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>
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've got a list of items, sorted by date.
Some of the items are in the future (green items), thus more interesting, some are in the past (brown items). I want the second group of items to start in a new row.
.grid{
width: 120px;
display:grid;
grid-template-columns: repeat(3,1fr);
grid-gap: 10px;
}
.item{
border:1px solid black;
height:50px;
width:50px;
}
.green{
background:green;
}
.brown{
background:brown;
}
<div class="grid">
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
</div>
The number of overall items / items per category is constantly changing, the number of Items per row depends on screen size - that might eliminate some possible solutions to this.
I could of course split the array containing all items at a certain point and organize the output into two separate grids, like so:
.grid{
width: 120px;
display:grid;
grid-template-columns: repeat(3,1fr);
grid-gap: 10px;
margin-bottom:10px;
}
.item{
border:1px solid black;
height:50px;
width:50px;
}
.green{
background:green;
}
.brown{
background:brown;
}
<div class="grid">
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
</div>
<div class="grid">
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
</div>
Probably that's the easiest option. Looks like what I want to achieve & isn't too difficult to do. But anyway, I'm curious: Is there a more elegant approach to this? I was thinking something like:
.item.green + .item.brown:before {
/* force new row */
}
You could target the first .brown after .green and set grid-column-start to 1.
.grid {
width: 120px;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
}
.item {
border: 1px solid black;
height: 50px;
width: 50px;
}
.green {
background: green;
}
.brown {
background: brown;
}
.green + .brown {
grid-column-start: 1;
}
<div class="grid">
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
</div>
Since you are using grid-template-columns, you won't be able to acheive this with before or after, you would need to set the grid-column-start to 1 with the item.green + .item.brown selection:
.grid{
width: 120px;
display:grid;
grid-template-columns: repeat(3,1fr);
grid-gap: 10px;
}
.item{
border:1px solid black;
height:50px;
width:50px;
}
.green{
background:green;
}
.brown{
background:brown;
}
.item.green + .item.brown {
grid-column-start: 1;
}
<div class="grid">
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item green"></div>
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
<div class="item brown"></div>
</div>
The approach that I came up with is definitely the longest one, but if for what ever reason you need to have a modular design I think this way would save you time in the end. Added grid-areas and added individual class for all your tiles.
.grid{
width: 120px;
display:grid;
grid-template-columns: repeat(3,1fr);
grid-template-areas: "green1 green2 green3"
"green4 green5 green6"
"green7 green8 green9"
"brown1 brown2 brown3"
"brown4 brown5 brown6";
grid-gap: 10px;
}
.item{
border:1px solid black;
height:50px;
width:50px;
}
.green1 {
background:green;
grid-area: green1;
}
.green2 {
background:green;
grid-area: green2;
}
.green3 {
background:green;
grid-area: green3;
}
.green4 {
background:green;
grid-area: green4;
}
.green5 {
background:green;
grid-area: green5;
}
.brown1{
grid-area: brown1;
background:brown;
}
.brown2{
grid-area: brown2;
background:brown;
}
.brown3{
grid-area: brown3;
background:brown;
}
.brown4{
grid-area: brown4;
background:brown;
}
<div class="grid">
<div class="item green1"></div>
<div class="item green2"></div>
<div class="item green3"></div>
<div class="item green4"></div>
<div class="item green5"></div>
<div class="item brown1"></div>
<div class="item brown2"></div>
<div class="item brown3"></div>
<div class="item brown4"></div>
</div>
Issue: So vertical alignment issue is I have two divs in the last column and I'm trying to get one to stay at top and one to stay at the bottom regardless of how the central column grows. I can work this out by using fixed heights but that's no good in this case.
Here is my code example : JS Fiddle
HTML:
<div class="row" class="property-bundle"><!-- (x) number of these -->
<div class="col-xs-11 wrapper">
<div class="row">
<div class="col-xs-2 pull-left vendor">
<img src="http://placehold.it/100x100" />
</div>
<div class="col-xs-8 properties-list">
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10"><p>Flat 1</p></div>
</div>
<div class="row"><hr/></div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10"><p>Flat 2</p></div>
</div>
<div class="row"><hr/></div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10"><p>Flat 3</p></div>
</div>
</div>
<div class="col-xs-2 costs"><!-- costs column -->
<div class="row total">
<h3 class="text-right">TOTAL: £1,2M</h3><!--stay at top-->
</div>
<div class="row" class="fees"> <!--stay at bottom-->
<div class="col-xs-12">
<hr/>
<p class="text-right">+ Materials £300K</p>
<p class="text-right">+ Build £100K</p>
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
.wrapper {border: 1px solid black; padding: 10px; margin: 15px;}
.vendor {min-width: 120px;}
.properties-list {background-color: aquamarine}
.costs {vertical-align: top; min-width: 150px; vertical-align: center}
.fees {vertical-align: bottom; }
h3 {font-weight: 400}
h4 {color: green}
.total { margin-right: 0px; }
Hi you can try using flexbox
I just change your html like this:
<div class="col-xs-2 costs">
<!--stay at top-->
<div class="total">
<h3 class="text-right">TOTAL: £1,2M</h3>
</div>
<hr/>
<div class="materials">
<p class="text-right">+ Materials £300K</p>
<p class="text-right">+ Build £100K</p>
</div>
</div>
</div>
Then I add on costs div display:flex;and on total div flex-grow: 1 This flex-grow will push materials on bottom of div.
You just need to add on body, html, row and costs div height:100%
Here is css:
.costs {
vertical-align: center;
display: flex;
flex-direction: column;
height: 100%;
}
.total {
flex-grow: 1;
}
You can see example on this link: https://jsfiddle.net/3L5Lbwhn/9/
Ok I simplified this a bit, but essentially flex did what I needed so many thanks to Edin Puzic for putting me on the right lines! It also allowed me to fix the 1st and last col width and make the middle one dynamic horiontally too.
JsFiddle
<div class="row-flex">
<div class="col-flex-1">
<img src="http://placehold.it/100x100" />
</div>
<div class="col-flex-2">
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10">
<p>Flat 1</p>
</div>
</div>
<div class="row">
<hr/>
</div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10">
<p>Flat 2</p>
</div>
</div>
<div class="row">
<hr/>
</div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10">
<p>Flat 3</p>
</div>
</div>
</div>
<div class="col-flex-3">
<div class="pos-top">
<div class="row right-text">
TOP right
</div>
</div>
<div class="pos-bottom">
<div class="row right-text">
<p>
BOTTOM right
</p>
</div>
</div>
</div>
</div>
CSS
.row-flex {
height: auto;
display: flex;
flex-flow: row column;
}
.col-flex-1 {
min-width: 200px;
border-left: 1px #ccc solid;
flex: 0 0;
}
.col-flex-2 {
width: 80%;
border-left: 1px #ccc solid;
flex: 1 1;
}
.col-flex-3 {
min-width: 200px;
border-left: 1px #ccc solid;
flex: 0 0;
}
.flex-container {
display: -webkit-flex;
display: flex;
width: 100%;
height: 100%;
background-color: lightgrey;
}
.pos-top {
display: -webkit-flex;
display: flex;
height: 50%;
width: 100%;
-webkit-align-items: flex-start;
align-items: flex-start;
background-color: yellow;
}
.pos-bottom {
display: -webkit-flex;
display: flex;
height: 50%;
width: 100%;
-webkit-align-items: flex-end;
align-items: flex-end;
background-color: green;
}
.right-text {
text-align: right;
width: 100%;
}