Getting CSS grid areas to stack on mobile (single column layout) - css

I am trying to get CSS Grid blocks to stack on top of each other when viewed on small screens. I know I can write media queries to change two columns to one. But I thought Grid could handle this without them?
I thought I could achieve this with auto-fit on columns. However, I think I may of misunderstood how this works?
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
grid-template-rows: 1fr 1fr;
grid-template-areas: "leftCol rightTop" "leftCol rightBottom";
height: 100vh;
}
.leftCol {
grid-area: leftCol;
background-color: pink;
width: 100%;
height: 100;
}
.rightBottom {
grid-area: rightBottom;
background-color: yellow;
width: 100%;
height: 100;
}
.rightTop {
grid-area: rightTop;
background-color: blue;
width: 100%;
height: 100;
}
<div class="grid-container">
<div class="leftCol"></div>
<div class="rightBottom"></div>
<div class="rightTop"></div>
</div>
When the screen is below 400px, the right hand column just disappears. I was expecting them to stack on top of each other.
For example:
CodePen Example

I am trying to get CSS Grid blocks to stack on top of each other when viewed on small screens. I know I can write media queries to change two columns to one. But I thought Grid could handle this without them? I thought I could achieve this with auto-fit on columns.
You can.
Here you go:
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
grid-auto-rows: 50%;
height: 100vh;
}
.leftCol { background-color: pink; }
.rightBottom { background-color: yellow; }
.rightTop { background-color: blue; }
body { margin: 0; }
<div class="grid-container">
<div class="leftCol"></div>
<div class="rightBottom"></div>
<div class="rightTop"></div>
</div>
revised codepen
Here's the problem with your original code:
The repeat() function allows you to render a pattern of tracks in the grid container.
With auto-fit or auto-fill, the repeat() function will render as many tracks as possible without overflowing the container.
By itself, your code works as you expect, as illustrated above.
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr))
With this rule, the grid items stack into a single column on smaller screens.
However, when you introduce explicit columns and rows, this interferes with the ability of repeat() and auto-fit to do their job.
grid-template-areas: "leftCol rightTop" "leftCol rightBottom"
This rule tells grid items where they need to be, stunting repeat().
grid-template-rows: 1fr 1fr
This rule creates a two-row limit in the container, pushing the third item off-screen.
In a nutshell, don't add rules that interfere with repeat() / auto-fit. If you need a more sophisticated layout, then use media queries.

try using
css:
.grid-container div {
display: inline-block;
float: left;
}

Related

How to stack unknown number of generic content items in a CSS Grid template area

I haven't quite got my head around grid-template-areas, I suspect. Or maybe I do, but it is the behaviour of direct Grid descendant nodes that do not have a grid-area assigned.
Here is visually what I am trying to achieve:
Codepen is here: https://codepen.io/davewallace/pen/abYxWxE
Similar code example:
html, body , .container {
height: 100%;
margin: 0;
}
.container {
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 1fr max-content;
gap: 40px 40px;
grid-template-areas:
"header header"
". graphic";
}
.header { grid-area: header; }
.graphic { grid-area: graphic; }
/* For presentation only, no need to copy the code below */
.container * {
border: 1px solid red;
position: relative;
}
<div class="container">
<div class="header">Full-width title</div>
<div class="graphic">Graphic</div>
<h4>Random element here</h4>
<p>Random element here</p>
<p>Random element here</p>
</div>
I seem to be able to only achieve two things currently:
Everything is in the right place, but all "generic content items" overlap on top of each other, where instead I want them stacked.
The title is in the right place, the image is sort of in the right place, but columns and/or rows are added automatically and do things like wrap under the image
The MDN docs for grid-template-area haven't really cleared the mix of behaviours up for me. I also tried using https://grid.layoutit.com/ to visualise the layout, and that seemed to get me off to a good start, but the default behaviour of the generic nodes has me confused.
You can approximate it like below:
body {
margin: 0;
}
.container {
min-height: 100vh;
display: grid;
grid-template-columns: 1fr max-content;
grid-auto-flow: dense;
gap: 0 40px; /* set only column gap */
}
.header {
grid-row: 1;
grid-column: 1/-1;
}
.graphic {
grid-column: 2;
grid-row: 2/ span 100; /* this will do the trick */
}
.container *:not(.graphic,:last-child) {
margin-bottom: 40px; /* replace the row gap */
}
/* For presentation only, no need to copy the code below */
.container * {
border: 1px solid red;
position: relative;
margin: 0;
}
<div class="container">
<div class="header">Full-width title</div>
<div class="graphic">Some Graphic here</div>
<h4>Random element here</h4>
<p>Random element here</p>
<p>Random element here</p>
</div>
I was trying to solve your CSS problem but it looks like there is no straightforward solution to it. According to the CSS spec, You cannot span a grid item to occupy all the rows/columns in an implicit grid.
Refer to this answer for more info - span grid item to all rows/columns
But I've come to a solution that could fix your grid by introducing a parent container for the random elements. In that way, you will only need two rows and two columns.
.container {
display: grid;
grid-template-columns: 1fr max-content;
gap: 40px 40px;
grid-template-areas: "header header" ". graphic";
}
.header {
grid-area: header;
}
.graphic {
grid-area: graphic;
}
/* Just to highlight */
.container * {
border: 1px solid;
}
<div class="container">
<div class="header">Full-width title</div>
<div class="graphic">Graphic</div>
<div class="random">
<h4>Random element here1</h4>
<p>Random element here2</p>
<p>Random element here3</p>
<p>Random element here4</p>
<p>Random element here4</p>
<p>Random element here4</p>
</div>
</div>

Display grid center child elements horizontally

I'm sure this has been answered before but I can't seem to get it working. I'm trying to horizontally center grid items with a display:grid parent. I've got a 12 column grid (76px column / 56px gap at full screen), with various column width child elements (for this example I'll just use span 8 1000px).
.main-container{
max-width:1528px;
margin: 0 auto;
}
.parent{
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
grid-column-gap: 56px;
justify-items: center;
}
.grid-8{
grid-column: span 8;
background: red;
opacity: 0.6;
width: 100%;
}
<div class="main-container">
<div class="parent">
<div class="grid-8">8</div>
</div>
</div>
Also once the child element is centred is it possible for it to keep its width (1000px) until the .main-container starts to touch either side? once the browser starts to get pulled smaller (horizontally). Sorry, this is a little tricky for me to explain what I mean. The .main-container if the browser window is pulled in so this is at say 1200px wide the span 8 column will no longer be 1000px wide it will have shrunk (I'm guessing because it is relative to the main container size). But ideally, I'd like it to stay 1000px until the .main-container hits it and then the span 8 can start reducing in width.
Thanks
You can't align items in grid automatically with justify/align props.
You can try using grid-column-end: -N; syntax for each child nodes, but it's not best way to do that.
Much better to use flex - in this case you can align child nodes as you wish.
Anyway, if you want to continue working with grid, you can do something like this (like an option):
.main-container {
max-width: 1528px;
margin: 0 auto;
}
.parent {
--columns-amount: 12;
display: grid;
/*grid-template-columns: repeat(12, minmax(0, 1fr));*/
grid-template-columns: repeat(var(--columns-amount), 1fr);
grid-column-gap: 56px;
/*justify-items: center;*/
}
.grid-8 {
/* edit --column-size to see changes */
--column-size: 8;
grid-column: calc((var(--columns-amount) - var(--column-size)) / 2 + 1) / span var(--column-size);
background: red;
opacity: 0.6;
/*width: 100%;*/
}
/* flex */
.parent--flex {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.parent--flex>.grid-8 {
flex: 0 0 auto;
width: 66.66667%;
}
<div class="main-container">
<div class="parent">
<div class="grid-8">Grid</div>
</div>
</div>
<hr />
<div class="main-container">
<div class="parent--flex">
<div class="grid-8">Flex</div>
</div>
</div>

CSS Grid not converting from a single column to a single row as a result of a media query

<div class="container">
<div class="wrapper">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
</div>
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
background: red;
}
.wrapper {
display: grid;
grid-template-columns: 1fr;
justify-items: center;
align-items: space-around;
min-width: 300px;
height: 70vh;
background: whitesmoke;
}
#media screen and (min-width: 1100px) {
.container {
height: auto;
display: grid;
grid-template-columns: 1fr repeat(2, minmax(auto, 30rem)) 1fr;
background: pink;
}
.wrapper {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column: 2/4;
justify-content: center;
background: cyan;
}
}
I've created a column that contains three circles in it, each stacked on top of the other in a column, which all looks fine when the screen is narrow. But when the browser is widened and I add a media query for when the screen gets wider than 1100px, I want the column of circles to flip to become a single row of circles.
But when I do this using CSS Grid, it doesn't work, and two circles appear on one row, and the third circle appears below the first circle on a second row. You can see it at https://codepen.io/HorrieGrump/pen/ZEKxJgv
I can get it to work if I use flexbox instead (as shown below) by swapping out the current .wrapper block in CSS and using this new one with flexbox, but I'd like to know if it's possible to use CSS Grid instead of flexbox to do this.
Can someone please let me know how to get the media query to flip the column into a single row using CSS Grid – and not have to resort to flexbox?
.wrapper {
display: flex;
flex-direction: row;
grid-template-columns: repeat(2,1fr);
justify-content: space-around;
align-items: center;
grid-column: 2/4;
background: cyan;
}
Edit your media query for .wrapper
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
align-items: center;
grid-column: 2/4;
background: cyan;
}

CSS fr / fractional units minimum too large

I have a jsfiddle.
What I have:
What I want:
Problem:
The hopefully relevant section is:
grid-template-columns: repeat(auto-fit, 1fr);
where both elements in my section have width: max-content;.
This (and the expanded but technically identical form of repeat(auto-fit, minmax(auto, 1fr));) do not do what I expect - it creates picture 1, I expect it to look like picture 2. It looks like the minimum width for these elements is too large, so instead of being on one row, it puts them in columns.
I made picture 2 by changing the code to repeat(auto-fit, minmax(200px, 1fr));. This is not a great solution as I want the minimum element size to be based on the grid elements' widths, not some arbitrary value.
I do want to have the elements able to be on different rows (for instance, if the browser is very narrow), so CSS grid seems useful for this task. I'm obviously just misunderstanding some key aspect.
Question
What value can I use in my grid-template-columns to make my elements work the way I expect with CSS grid? Is there a way to do it with repeat(auto-fit, X); or do I have to specify the number?
Answer
As stated below, you cannot use repeat(auto-fit with fr as it does not specify an absolute minimum or maximum, which the spec says is invalid.
Michael_B gave the answer (in his jdfiddle example comment) of using
display: flex;
flex-wrap: wrap;
which does exactly what I expected repeat(auto-fit, 1fr); to do.
This rule won't work.
grid-template-columns: repeat(auto-fit, 1fr)
The problem is explained here: minmax fails (invalid property value)
This rule won't work:
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr))
The problem is explained here: minmax() defaulting to max
You can use min-content
.page-container {
display: grid;
grid-gap: 0.5rem;
grid-template-columns: 20% 80%;
grid-template-rows: auto auto 20rem;
grid-template-areas: "header header" "sidebar content" "footer footer";
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 25px;
padding: 50px;
}
.header {
grid-area: header;
display: grid;
grid-template-columns: repeat(2, min-content);
grid-gap: 10px;
}
.header>* {
background-color: lightgreen;
}
.header a:link {
color: inherit;
text-decoration: none;
}
.header a:hover {
/* https://html.spec.whatwg.org/multipage/rendering.html#phrasing-content-3 */
text-decoration: underline;
}
.header h1,
h2 {
margin: 0;
width: max-content;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.footer {
grid-area: footer;
}
<div class="page-container">
<section class="box header">
<h1><a href="https://jeremy.richards.dev">
Jeremy.Richards.dev
</a></h1>
<h2>
and this on the
</h2>
</section>
<div class="box sidebar">
Sidebar
</div>
<div class="box content">
Content
</div>
<div class="box footer">
<h2 style="font-size: 2rem;">
Something
</h2>
<h3 style="font-size: 1.5rem;">
My name underneath
</h3>
<p>
Linkedin/github/SO
</p>
</div>
</div>

Css - auto grid list of photos(angular 6)

I want to create a grid list that dynamically works with Angular 6 *ngFor directive. My question/problem is that I have Array of 105 objects in firebase. Structure of object is like:
{src: 'some url', alt: 'title'}
Now I have 2 different type of photos, one horizontal, one vertical. I want to create auto filling section that will fill up empty space, I know that can be do with grid list in css3. But how to connect that with :
<div class="row">
<div class="imageGallery1 " *ngFor="let image of galleryList">
<a [href]="image.src" [title]="image.alt">
<img [src]="image.src" [alt]="image.alt" style="max-width: 300px; max-height: 300px; object-fit: contain; padding-right: 20px;" />
</a>
</div>
styles are only for create temp thumbnails
Is there any way to check what kind of type each photo has? (vertical, horizontal) and later auto sortu out them ? Please point me if there's any other way to do this
I found solution on youtube course of grid css.
https://www.youtube.com/watch?v=t6CBKf8K_Ac
css:
.row {
display: grid;
grid-gap: 5px;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-template-rows: auto;
grid-auto-flow: dense;
}
.imageGallery1 {
text-align: center;
position: relative;
& img {
width: 100%;
max-height: 510px;
height: 251px;
}
}
.vertical {
grid-row: span 2;
& img {
height: 510px;
}
}
and now each vertical photo has its own class with grid-row: span 2;
Maybe i could help someone

Resources