unexpected behavior with grid-template-rows and 1fr on chrome - css

I'm trying to build a grid with 2 rows inside a flex column. The flex container has a minimum height to fill the window. The first line of the grid should fill the available space, so I was thinking of the fr unit. A simplified version may look like that:
.container {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.grid {
flex-grow: 1;
background-color: red;
padding: 1rem;
grid-gap: 1rem;
display: grid;
grid-template-rows: 1fr auto;
}
.grid > * {
background-color: white;
}
<div class="container">
<h1>some title</h1>
<div class="grid">
<div>line 1</div>
<div>line 2</div>
</div>
</div>
This works perfectly fine with firefox:
But not with chrome:
What am I missing?

The grid container is interpreting the min-height: 100vh on the flex parent differently in Chrome and Firefox.
As you noted, in Firefox everything works as you expect. But in Chrome, the min-height is effectively ignored (even though flex-grow: 1 works on the same element).
If you switch to height: 100vh you'll see the 1fr work in Chrome, as well.
I would have to research more to tell you if this is a bug or not.
Consider nesting the grid inside another grid, as opposed to flex, container.
.container {
display: grid;
min-height: 100vh;
grid-template-rows: min-content 1fr;
}
.grid {
background-color: red;
padding: 1rem;
grid-gap: 1rem;
display: grid;
grid-template-rows: 1fr auto;
}
.grid>* {
background-color: white;
}
<div class="container">
<h1>some title</h1>
<div class="grid">
<div>line 1</div>
<div>line 2</div>
</div>
</div>
jsFiddle demo

Related

How to specify different size for each grid element and maintain wrapping?

Problem:
Right now both of the grid elements below are min: 250px, max: 1fr in size. They wrap on screen size <250px
I'm trying to achieve the following:
the first element to be min: 250px, max: 2fr
the second element to be min: 250px, max: 1fr
but also maintain wrapping to 1fr each on screen size <250px (the way they wrap now basically)
Code:
Codepen: https://codepen.io/anon/pen/dEBQgm?editors=1100
<div class="container">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
...
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-gap: 16px;
}
.child {
background: #aaa;
height: 32px
}
I tried this but I lost the wrapping:
grid-template-columns: minmax(250px, 2fr) minmax(250px, 1fr);
You can try flexbox for this:
.container {
display: flex;
flex-wrap: wrap;
margin:-8px; /*Pay attention to this! You may need overflow:hidden on a parent container*/
}
.child {
background: #aaa;
height: 32px;
min-width: 250px;
flex-basis: 0%;
margin: 8px;
}
.container> :first-child {
flex-grow: 2;
}
.container> :last-child {
flex-grow: 1;
}
.container-grid {
display: grid;
grid-template-columns: minmax(250px, 2fr) minmax(250px, 1fr);
grid-gap:16px;
}
.container-grid > .child {
margin:0;
}
flexbox with wrapping
<div class="container">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
grid without wrapping:
<div class="container-grid">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>

CSS grid equal size columns

I'm trying to create 3 divs each containing 1 <p>-tag and distribute all 3 on the same row with an equal width using CSS grid.
Most sources say that I should use grid-template-columns to achieve this. Some say to go for 1fr 1fr 1fr, some say repeat(3, 1fr), and yet more say repeat(3, auto).
The result is the same. The 3 divs end up on the same line, but their widths change depending on the width of their content. Is there a way to force all 3 divs to have the same width and simply use the next line if the content is too wide?
The snippet should show the situation I'm in.
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.content {
margin: 2em;
}
<div class="grid-container">
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
</div>
Your grid is fine - the content is the problem here.
You can try word-break or overflow as a workaround:
word-break solution:
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 2px dotted green;
}
.content {
margin: 2em;
border: 2px solid red;
}
.content p {
word-break: break-word;
}
<div class="grid-container">
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
</div>
overflow solution:
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 2px dotted green;
}
.content {
margin: 2em;
border: 2px solid red;
overflow: auto;
}
<div class="grid-container">
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
</div>
EDIT: Apparently, word-break: break-word; does not work in Firefox - thanks, #Yaakov Ainspan. Another reminder that you should test your code in multiple browsers. word-break: break-all; can be used instead.
#fen1x's answer was close, but not quite. I experimented with this a bit, and found that word-break: break-all worked, while break-word did not. (The overflow solution sort of works, but isn't what the OP asked for).
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
max-width: 100%;
}
.content {
margin: 2em;
word-break: break-all;
}
<div class="grid-container">
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
<div class="content">
<p>TESTESTTESTTESTTESTTESTTESTTESTTESTTESTTES</p>
</div>
</div>
Additionally, this solution does not need to be applied to individual elements inside the grid item, but can be applied directly to the item.
Try:
grid-template-columns: repeat(3, minmax(0, 1fr));

Make a grid expand to remaining height inside a flex item

There are lots of similar questions, I have reviewed all of them, but none solved my problem.
Premises:
I have a flexbox layout with flex column and the bottom flex-item filling the remainder of the page height. The flex-item gets stretched to the remainder of the page by flex 1.
Goal:
I need my grid (with its children) inside this flex-item to expand to the height of the flex-item.
Problem:
The html wrapper only has a min-height 100vh set. This makes the grid stretch to the flex-item, but not its children!
The only solution I can find is to also set height 100vh on the html wrapper, but I do not want to do this. Is there any way to solve my problem without setting height?
See the codepen here:
https://codepen.io/mesqueeb/pen/aGeKjm
See the animated GIF here to show you what I mean:
You can try this.
remove the flex-direction: column; in the .remaining and it will expand the height.
main{
min-height: calc(100vh - 51px);
display: flex;
flex-direction: column;
}
div{
border: solid goldenrod thick;
padding: 2px;
margin: 2px;
}
.full-page{
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
}
.top-row{
height: 100px;
}
.remaining{
flex: 1;
display: flex;
}
.grid{
border: solid teal thick;
flex: 1;
display: grid;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
.key{
border: thin green solid
}
.small{
font-size: .8em
}
<main>
<div class="full-page">
<div class="top-row">
grid below will take full height only if body height is set...
</div>
<div class="remaining">
<div class="grid">
<div class="key">1</div>
<div class="key">2</div>
<div class="key">3</div>
<div class="key">4</div>
<div class="key">5</div>
<div class="key">6</div>
<div class="key">7</div>
<div class="key">8</div>
<div class="key">9</div>
<div class="key">C</div>
<div class="key">0</div>
<div class="key">➕</div>
</div>
</div>
</div>
</main>
Not sure if it solves your problem in the best way, but this works:
.remaining {
flex: 1;
/* display: flex; */
flex-direction: column;
position: relative;
}
.grid {
border: solid #008080 thick;
/* flex: 1; */
display: grid;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}

Single-row grid with height 1fr not filling height in Chrome

I have a CSS Grid inside a Flexbox column, and the grid has flex-grow: 1.
In Chrome, the grid expands to fill available space, but its content does not, even with align-content: stretch on the grid. In Firefox and Edge, the content expands to fill the grid's height, as desired.
Here's a pen that reproduces the problem, and images of how it looks in different browsers. Is this a bug with Chrome, and if so, can anyone suggest a straightforward workaround?
Chrome
Firefox
Edge
#wrapper {
display: flex;
flex-direction: column;
height: 15rem;
background-color: #aaa;
}
#grid {
flex-grow: 1;
display: grid;
background-color: #ccf;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
align-content: stretch; /* "end" correctly puts the row to the bottom */
}
#left {
background-color: #fcc;
}
#right {
background-color: #cfc;
}
<div id="wrapper">
<div id="top">not in grid</div>
<div id="grid">
<div id="left">left</div>
<div id="right">right</div>
</div>
</div>
Is this a bug with Chrome, and if so, can anyone suggest a straightforward workaround?
It looks like a bug in Chrome. But I can't say for sure.
Here's what's happening:
You have the flex item grid container set to consume all available height with flex-grow: 1
Because you've only defined the flex-grow property, the other two flexibility properties – flex-shrink and flex-basis – remain at their default values.
The default value of flex-shrink is 1, and is not pertinent to this problem.
The default value of flex-basis is auto, and is the source of the problem.
If you add flex-basis: 0 to your code, the item takes full height in Chrome, as well.
revised codepen
#wrapper {
display: flex;
flex-direction: column;
height: 15rem;
background-color: #aaa;
}
#grid {
/* flex-grow: 1; */
flex: 1; /* fg:1, fs:1, fb:0 */
display: grid;
background-color: #ccf;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
}
#left { background-color: #fcc; }
#right { background-color: #cfc; }
<div id="wrapper">
<div id="top">not in grid</div>
<div id="grid">
<div id="left">left</div>
<div id="right">right</div>
</div>
</div>

How can I reorder a grid of columns?

What I have is a two-column layout with several items inside:
.grid {
column-count: 2;
}
.grid-item {
break-inside: avoid;
height: 50px;
margin-bottom: 10px;
background-color: green;
text-align: center;
line-height: 50px;
color: white;
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>
https://codepen.io/Deka87/pen/RgdLeZ
Now I need an ability to reorder those items inside the columns with CSS only (so they were in a different order on different screen resolutions), so I thought I can do this with:
.grid {
display: flex;
flex-direction: column;
column-count: 2;
}
.grid-item:nth-child(1) {
order: 5;
}
Obviously, this didn't work and broke the 2-column layout. Anybody tried to solve this before? Any chance I can get this working?
PS: Items on the same line should not be of the same height (I could have used simple floats in this case). Sorry for not specifying in the beginning.
Without a fixed height on the container, a column of flex items won't know where to wrap. There's nothing to cause a break, so items will continue expanding the single column.
Also, column-count and display: flex represent two different CSS technologies. column-count is not a valid property in a flex container.
CSS Grid Layout may be useful to you:
re-size the screen width to trigger the media query
revised codepen
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: repeat(3, auto);
grid-auto-rows: 50px;
grid-auto-flow: column;
grid-gap: 10px;
}
.grid-item {
background-color: green;
text-align: center;
line-height: 50px;
color: white;
}
#media ( max-width: 500px) {
.grid-item:nth-child(2) {
order: 1;
background-color: orange;
}
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>
I tend to use flexbox for this
.grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: flex-start;
}
.grid-item {
box-sizing: border-box;
width: calc( 50% - 5px );
min-height: 50px;
margin-bottom: 10px;
background-color: green;
text-align: center;
line-height: 50px;
color: white;
}
.grid-item:nth-child(1) {
order: 5;
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>
The flex syntax is widely supported and super flexible.

Resources