CSS fr / fractional units minimum too large - css

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>

Related

fr units cannot be the minimin value of minmax() (css)

When I tried putting 1fr in the first slot of minmax()and the browser dev tools tells me that it is not valid.
The moment I take away the 1fr, it works.
Code that did not work:
.grid {
grid-template-rows: minmax(1fr, auto); /* this did not work */
}
Is there any work arounds to this?
1fr cannot be your minimum because 1fr takes
1 fraction of the leftover space in the grid container
Here is the doc
You can do something like this
.grid {
display: grid;
grid-template-columns: repeat( auto-fit, minmax(100px, 1fr));
grid-gap: 10px;
}
.bloc {
display: flex;
justify-content: center;
align-items: center;
background-color: teal;
color: white;
}
<div class="grid">
<div class="bloc">1</div>
<div class="bloc">2</div>
<div class="bloc">3</div>
<div class="bloc">4</div>
<div class="bloc">5</div>
<div class="bloc">6</div>
<div class="bloc">7</div>
<div class="bloc">8</div>
<div class="bloc">9</div>
</div>

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

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

How to make 2 css grid columns into 1 for mobile without media query?

As title says + I need to keep itemX and itemY in one cell on each device. Is media query the only solution? If there is more of a native css grid way I would love to learn it.
See fiddle:
https://jsfiddle.net/forusak/ctg3auh0/
.container {
display: grid;
grid-template: repeat(10, auto) / repeat(auto-fit, minmax(250px, 1fr));
column-gap: 30px;
color: white;
}
.container>* {
background-color: #b90011;
border: 1px solid black;
padding: 5%;
height: 20px;
}
.item1 {
grid-row: 1 / 10;
height: auto;
}
/* comment out part bellow to see mobile responsivity which is missing here */
.itemX,
.itemY {
grid-area: 3 / 2 / 3 / 2;
width: 40%;
}
.itemY {
margin-left: auto;
}
<div class="container">
<div class="item1"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="itemX"> itemX </div>
<div class="itemY"> itemY </div>
<div class="item"> </div>
<div class="item"> </div>
</div>
Checkout the below code. At screen-width < 464px itemX and itemY will reassemble vertically.
body {
padding: 1rem;
}
.res-grid-1 {
--min-size: 25rem;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--min-size), 1fr));
grid-gap: 1rem;
}
.res-grid-1 > div {
padding: 5rem 1rem;
text-align: center;
font-size: 2rem;
background: #557571;
color: #ffffff;
}
.res-grid-2 {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
grid-gap: 1rem;
}
<div class="res-grid-1">
<div>Item 1</div>
<div class="res-grid-2">
<div>Item X</div>
<div>Item Y</div>
</div>
</div>
However there is a small bug, between screen-width 1280px and 1328px itemX and itemY are reassembling horizontally(which should be vertically). This is due to nesting of grid;it is possible to achieve responsive CSS grid without media-queries but here you're trying achieve the same for a nested grid without media-queries.
If you wish to use media-queries, you can fix this bug by making following changes to CSS:
In class res-grid-2 replace line:
grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
with:
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
and add:
#media only screen and (max-width: 576px) {
.res-grid-2 {
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
}

Css grid minmax wrap

I have the following grid with 3 items:
<div class="grid">
<p> </p>
<p> </p>
<button> </button>
</div>
.grid {
display: grid;
justify-content: flex-start;
align-items: flex-end;
grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(100px, 1fr);
grid-gap: 2rem;
}
I want the paragraphs to be at least 200px as from css minmax and the button to be at least 100px and wrap as a decrease the browser window width.
but this doesnt happen.
The elements stay in one row.
Thank you
Close enough to what you wanted (without media queries and convoluted rules not worth the trouble):
HTML:
<div class="container">
<p>Lorem ipsum</p>
<p>Delor sit</p>
<button>Amet</button>
</div>
CSS:
// See the container's items:
.container > * { background: lightblue; }
A) Use grid; don't know if possible to set different minmax() while preserving repeat(auto-fit, ..) behavior:
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 2rem;
}
B) Use flexbox; the margins hack mimicks grid's gutters until CSS implements flexbox gutters natively:
.container {
display: flex;
flex-wrap: wrap;
margin-right: -2rem;
}
.container > * { margin-right: 2rem; }
p { flex: 1 1 200px; }
button { flex: 1 1 100px; }

CSS grid elements not aligned properly

seems like an easy task which Im trying to get done since hours. I cant get my grid elements vertical aligned properly. Please take a look at the fiddle to get the idea. Maybe someone could help me with this issue.
HTML
<section class="top">
<div></div>
<div></div>
</section>
<section class="bottom">
<div></div>
<div></div>
<div></div>
</section>
CSS
section {
display: grid;
grid-template-rows:auto;
margin: 40px 0 0 0
}
section.top {
grid-template-columns:2fr 1fr;
grid-column-gap: 50px;
}
section.bottom {
grid-template-columns:1fr 1fr 1fr;
grid-column-gap: 50px;
}
section div {
background:lightblue;
height:400px
}
https://jsfiddle.net/ecj1wrae/
Well, with some thinking and calculation this one here does the trick
CSS
section.top {
grid-template-columns:calc(66% + 2vw) 34%;
grid-column-gap: 2vw;
}
section.bottom {
grid-template-columns:33% 33% 34%;
grid-column-gap: 2vw;
}
https://jsfiddle.net/ecj1wrae/3/
I know this is an old question... But I had a similar problem and I thought I'd share my solution for anyone else that needs some help.
This comment helped push me in the right direction
But you're dividing space using fr units, which applies only free
space in the container. And the bottom section has 50px less free
space than the top. So they cannot be aligned in this manner
As the layout needs to consider the gaps between the columns I found it better to frame the problem as it needs to take up 2 columns of a 3 column layout instead of thinking it needs to take up 2fr of a 3fr layout.
Helpfully grid allows us to specify how many columns an element can span grid-column: span 2;
Using the html in the question we can use a span on the first div in the top section:
section {
display: grid;
margin: 40px 0 0 0;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-column-gap: 50px;
}
section.top div:first-child {
grid-column: span 2;
}
If you would like to do it with only 1 parent element, this may be a solution:
.wrapper {
display: grid;
grid-template-columns: auto auto auto auto;
grid-row-gap: 50px;
grid-column-gap: 10px;
grid-template-areas:
'item1 item1 item1 item1 item2'
'item3 item3 item4 item4 item5';
}
.wrapper > div {
background: red;
height: 400px;
}
.item1 {
grid-area: item1;
}
.item2 {
grid-area: item2;
}
.item3 {
grid-area: item3;
}
.item4 {
grid-area: item4;
}
.item5 {
grid-area: item5;
}
<div class="wrapper">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
<div class="item4"></div>
<div class="item5"></div>
</div>
A really simple solution is change the grid-column-gap by margin (if having space on the sides is not a problem):
HTML
<section class="top">
<div></div>
<div></div>
</section>
<section class="bottom">
<div></div>
<div></div>
<div></div>
</section>
CSS
section {
display: grid;
grid-template-rows:auto;
margin: 4px 0 0 0
}
section.top {
grid-template-columns:2fr 1fr;
}
section.bottom {
grid-template-columns:1fr 1fr 1fr;
}
section div {
background:lightblue;
height:400px;
margin: 5px;
}
https://codepen.io/fillsanches/pen/oNEpKWN

Resources