I am trying to work a little with the css grids. Until now I have managed to stack these contents on top of each other, and when the screen gets smaller, I want to display them in 2 rows with 2 columns each.
The problem is that when doing so, the grid is slicing up the content? How can I prevent this from happening?
Here is the code I used:
#top-story {
grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
column-count: 4;
}
#top-story .top-news {
grid-row-start: 1;
grid-column-start: 1;
grid-column-end: 4;
}
#top-story .news-rows {
grid-row-start: 2;
column-count: 2;
}
Here is the HTML:
<div id="top-story">
<a href="#">
<div class="top-news">
<img src="images/test.jpg" />
<div id="gradient">
<div id="headline">
<div id="category">
Galleri
</div>
Forårstopscorer Jung: Fortjener ikke at blive sammenlignet med Kamil – endnu
</div>
</div>
</div>
</a>
<div class="news-rows">
Nyheder
<div style="width: 100%; height: 10px;"> </div>
<a href="#">
<div id="story">
<img src="images/test.jpg" />
<div id="seperator"> </div>
<div id="info">
<div id="inside-content">
<div id="category">
Galleri
</div>
Forårstopscorer Jung: Fortjener ikke at blive sammenlignet med Kamil – endnu
</div>
</div>
</div>
</a>
<br />
<a href="#">
<div id="story">
<img src="images/test.jpg" />
<div id="seperator"> </div>
<div id="info">
<div id="inside-content">
<div id="category">
Galleri
</div>
Forårstopscorer Jung: Fortjener ikke at blive sammenlignet med Kamil – endnu
</div>
</div>
</div>
</a>
<br />
<a href="#">
<div id="story">
<img src="images/test.jpg" />
<div id="seperator"> </div>
<div id="info">
<div id="inside-content">
<div id="category">
Galleri
</div>
Forårstopscorer Jung: Fortjener ikke at blive sammenlignet med Kamil – endnu
</div>
</div>
</div>
</a>
<br />
<a href="#">
<div id="story">
<img src="images/test.jpg" />
<div id="seperator"> </div>
<div id="info">
<div id="inside-content">
<div id="category">
Galleri
</div>
Forårstopscorer Jung: Fortjener ikke at blive sammenlignet med Kamil – endnu
</div>
</div>
</div>
</a>
</div>
</div>
top-news is the large image and news-rows is the one with the four contents.
See image of the issue here:
You have to design for Mobile first, then Desktop. You will use CSS3 #media but min-width i.e.: #media (min-width: 1024px){}. Remove column-count from your code. You have to design infinity column. You have to transfer the column where you want using grid-column-start and grid-row-start. Also you should use a CSS prefixer for browser support. Use classes instead of ids.
Here is the snippet.
.main-container{
display: grid;
grid-template-columns: repeat(1fr);
grid-row-gap: 30px;
margin-left: auto;
margin-right: auto;
max-width: 1024px;
width: 100%;
}
#media (min-width: 1024px){
.main-container{
grid-column-gap: 30px;
grid-template-columns: repeat(2, 1fr);
}
}
.child-item{
background-color: green;
border: 2px solid black;
border-radius: 3px;
color: white;
height: 100px;
padding: 15px;
text-transform: uppercase;
}
#media (min-width: 1024px){
.box-3{
grid-column-start: 2;
grid-row-start: 1;
}
.box-4{
grid-column-start: 2;
grid-row-start: 2;
}
}
<div class="main-container">
<div class="child-item box-1">Box 1</div>
<div class="child-item box-2">Box 2</div>
<div class="child-item box-3">Box 3</div>
<div class="child-item box-4">Box 4</div>
</div>
Explanation of the code:
First .main-container creates grid for Mobile view where use grid-template-columns: repeat(1fr);. No grid column-count property. Instead of margin-bottom I use grid-row-gap: 30px; for space between column in bottom. If browser window is more than or equal to 1024px, grid-template-columns: repeat(2, 1fr); /* Create two column in side by side */ and use grid-column-gap: 30px; for separated from side by side column.
At this point in Desktop your box will be look like this.
Second, if you want to transfer box-3 where is box-2 in Desktop view in #media box-3 will be grid-column-start: 2;, grid-row-start: 1; and box-4 grid-column-start: 2;, grid-row-start: 2;. Box 4 will be auto resize when you set column 3 specific CSS.
Now Desktop view change like this.
Please read about CSS Grid here.
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 am new to grid layouts in CSS and I want to have a simple layout with one column
and three rows but one of the rows has to be again divided into three columns
so it will be something like below where 2, 3, 4 have to be in the same row equally spaced
or controllable.
Here is my grid structure:
<div class="grid_container">
<div class="card" id="about_me">
<p>
1
</p>
</div>
<div class="card card-small" id="">
<p>
2
</p>
</div>
<div class="card card-small" id="">
<p>
3
</p>
</div>
<div class="card card-small" id="">
<p>
4
</p>
</div>
<div class="card" id="">
<p>
5
</p>
</div>
</div>
I feel like using flex-box for the three rows, but thats not probably what I should do
as grid probably has its own logic and control to generate such a layout.
using grid-column css
work fine also with gaps
only one div that contain all the cards
.grid_container {
display: grid;
gap: 0.5rem;
}
.card {
border: 1px dashed red;
display: grid;
place-items: center;
}
<div class="grid_container">
<div style="grid-column: 1/4" class="card" id="about_me">
<p>1</p>
</div>
<div style="grid-column: 1/2" class="card card-small" id="">
<p>2</p>
</div>
<div style="grid-column: 2/3" class="card card-small" id="">
<p>3</p>
</div>
<div style="grid-column: 3/4" class="card card-small" id="">
<p>4</p>
</div>
<div style="grid-column: 1/4" class="card" id="">
<p>5</p>
</div>
</div>
using flexbox
Another easier solution can be using grid when is necessary, or flexbox when is necessary.
so the 3, 4, 5 cards can be wrapped inside a <div> and make that div with flexbox
and the parent element grid
.grid_container {
display: grid;
}
.flex_container {
display: flex;
}
.flex_container>* {
flex: 1;
}
.card {
border: 1px dashed red;
display: grid;
place-items: center;
}
<div class="grid_container">
<div class="card" id="about_me">
<p>1</p>
</div>
<div class="flex_container">
<div class="card card-small" id="">
<p>2</p>
</div>
<div class="card card-small" id="">
<p>3</p>
</div>
<div class="card card-small" id="">
<p>4</p>
</div>
</div>
<div class="card" id="">
<p>5</p>
</div>
</div>
Maybe something like this would work for you if you want to use css grid:
.grid-container {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
row-gap: 10px;
text-align: center;
}
.full-row {
grid-column: span 3 / span 3;
border: dashed red;
}
.one-third-row {
grid-column: span 1 / span 1;
border: dashed red;
}
<div class="grid-container">
<div class="full-row" id="about_me">
<p>
1
</p>
</div>
<div class="one-third-row" id="">
<p>
2
</p>
</div>
<div class="one-third-row" id="">
<p>
3
</p>
</div>
<div class="one-third-row" id="">
<p>
4
</p>
</div>
<div class="full-row" id="">
<p>
5
</p>
</div>
</div>
Is there a CSS Grid configuration that will repeat (wrap) cells but dynamically shrink columns based on the size of the content, instead of using uniformly sized columns?
For example, here is a configuration using the following rules:
display: grid;
grid-template-columns: repeat(auto-fit, 186px);
grid-auto-columns: min-content;
grid example 1
notice that though the last column has narrower content, it uses the same width as the other columns (186px)
I'd like the columns to shrink to the width of the content, while still wrapping as screen size collapses.
grid example 2
notice the last column is now narrower that the others.
It seems grid-template-columns: repeat(); takes two arguments. The first of which can be auto-fit or auto-fill, but the second must be a specific width. Is there any way to allow this to be automatically computed based on content width?
Here is the codepen I've been playing with to try to achieve this.
Here is the real world scenario as well:
real world example
notice the first column should be wider to fill the content, and the second column should shrink to the content.
I'm familiar with flexbox, but I'm not super familiar with grid yet. Any guidance here would be much appreciated.
You can create repeating columns that to fit content, but for fixed a amount columns. When you use auto-fit, auto-fill grid generates all cells the same width.
In your case in look like 3x3.
display: grid;
grid-template-columns: repeat(3, min-content);
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
background-color: hsl(215, 100%, 98%);
position: relative;
overflow-x: hidden;
}
.container {
background-color: lightgray;
width: 760px;
display: grid;
grid-template-columns: repeat(3, min-content);
resize: horizontal;
overflow: hidden;
gap: 5px;
justify-items: center;
align-items: center;
}
.child {
background-color: gray;
display: flex;
flex-direction: column;
justify-content: center;
}
p {
text-align: center;
}
<div class="container">
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/80x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/120x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/160x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/80x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/120x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/160x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/80x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/120x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/160x75" alt="" />
</div>
</div>
It seems grid-template-columns: repeat(); takes two arguments. The first of which can be auto-fit or auto-fill, but the second must be a specific width. Is there any way to allow this to be automatically computed based on content width?
In repeat() function you can use another function minmax() as the second property. But this will not solve your problem, because the first parametr defines minimal width, example 186px and the second how large it will extend.
display: grid;
grid-template-columns: repeat(auto-fit, minmax(186px, 1fr));
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
background-color: hsl(215, 100%, 98%);
position: relative;
overflow-x: hidden;
}
.container {
background-color: lightgray;
width: 760px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(186px, 1fr));
resize: horizontal;
overflow: hidden;
gap: 5px;
justify-items: center;
align-items: center;
}
.child {
background-color: gray;
display: flex;
flex-direction: column;
justify-content: center;
}
p {
text-align: center;
}
<div class="container">
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/80x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/120x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/160x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/80x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/120x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/160x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/80x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/120x75" alt="" />
</div>
<div class="child">
<p>title</p>
<img src="https://via.placeholder.com/160x75" alt="" />
</div>
</div>
I have an image gallery with horizontal thumbnails below the featured image. I am adding padding-right:10px; to all but the last-child in an effort to equally space these elements. This works as intended on all but the last thumbnail, where it's slightly larger than the rest.
It makes sense why this is happening, but I am not sure how to fix it. This was the solution recommended on numerous other Stack Overflow posts. Any workaround would be appreciated.
<style>
.gallery-grid {
display: grid;
grid-template-columns: 50% 50%;
grid-template-rows: 1fr;
column-gap: 10px;
row-gap: 30px;
}
.image-thumb {
float: left;
width: 20%;
padding-right: 10px;
box-sizing: border-box;
}
.image-thumb:last-child {
padding-right: 0;
}
</style>
<div class="gallery-grid">
<img id="featured-image" src="featured.jpg" style="width:100%">
<div class="image-thumb">
<img src="featured_thumb.jpg" alt="Mountains" style="width:100%" onclick="myFunction(this);">
</div>
<div class="image-thumb">
<img src="thumb.jpg" alt="Nature" style="width:100%" onclick="myFunction(this);">
</div>
<div class="image-thumb">
<img src="thumb.jpg" alt="Snow" style="width:100%" onclick="myFunction(this);">
</div>
<div class="image-thumb">
<img src="thumb.jpg" alt="Lights" style="width:100%" onclick="myFunction(this);">
</div>
<div class="image-thumb">
<img src="thumb.jpg" alt="Lights" style="width:100%" onclick="myFunction(this);">
</div>
</div>
If you want to stick using float insteed of flex you could use margin insteed of padding. Then you can calculate the total space taken by the margin, divide it between the number of elements and rest it to the width using calc
(margin-right:10px * 4) / 5 = 8
Example:
* {box-sizing:border-box;}
.box {
height:100px;
background-color:blue;
float:left;
width:calc(20% - 8px);
margin-right:10px;
}
.box:nth-child(5) {margin-right:0;}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
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>