Problem with max-height not working in css grid element [duplicate] - css

This question already has an answer here:
Why does height: 100% on a child element not apply when the parent element has a min-height/max-height value but no height value?
(1 answer)
Closed 1 year ago.
Edit: I misunderstood my problem quite a bit, as #onkar-ruikar explained below. I still don't know exactly how to handle the consequences of the cyclic dependencies in a way which really works for me, but I would have had to completely rewrite my question here, so I'm treating both as separate problems, marked this one as solved and asked a follow up to it: Dealing with cyclic dependencies of percentage sized boxes css (specifically how to get a max-height)
I have a problem with max-height not working properly in grid elements. Basically I have a grid element with flexible size, and within it I am showing an iframe. I want to scale the iframe to its full size, and have a surrounding div which fits to the iframe size, with a maximum size equal to the grid element, and from there scroll. My problem is, that max-height somehow does not work properly. I prepared a jsfiddle for this:
For this code I get different results for using "height: 100%;" or "max-height: 100%" in #grid1:
#grid0 {
display: grid;
grid-template-rows: 50px;
grid-template-columns: 200px;
height: 500px;
}
#grid1 {
height: fit-content;
max-height: 100%;
background: blue;
/* it works using height instead of max-height
height: 100%;
*/
}
#out {
height: auto;
max-height: 100%;
overflow: hidden;
background: purple;
width: 150px;
}
#large {
height: 100px;
width: 100px;
background: red;
}
<div id='grid0'>
<div id='grid1'>
<div id='out'>
<div id='large'>
</div>
</div>
</div>
</div>
Compare the results between this and commenting in the "height: 100%;"-line in the css for #grid1. Interestingly when inspecting #grid1 with firefox its height gets shown as it should be even with max-width, but clearly it is not rendered this way.
I tried to introduce another container around #out, set its height to auto and max-height to 100% and #grid1's height to 100% fix, because I thought it might be the "fit-content", but it did not work either...
Does anyone have suggestions how to get around this, or am I doing something wrong?
I would be happy about every hint!

I think the issue not actually related to the grid. I can reproduce it using normal block element as well.
#div0 {
width: 200px;
height: 50px;
}
#div1 {
height: fit-content;
max-height: 100%;
background: blue;
/* it works using height instead of max-height
height: 100%;
*/
}
#out {
height: auto;
max-height: 100%;
overflow: hidden;
background: purple;
width: 150px;
}
#large {
height: 100px;
width: 100px;
background: red;
}
<div id='div0'>
<div id='div1'>
<div id='out'>
<div id='large'>
</div>
</div>
</div>
</div>
My explanation is based on following specs:
Percentages specify sizing of a box with respect to the box’s containing block.ref
Intrinsic sizing determines sizes based on the contents of an element, without regard for its context.
That is using min-content, max-content, and fit-content values.
In your case #grid1(blue) is working as expected it is getting 50px height because of max-height: 100%. height:fit-content has no effect, if it did then blue would be 100px high.
The problem is that #out(purple) is overflowing. It is because the container blue is saying my height is dependent on my children(because of fit-content). When you set height:100% you say it's height is dependent on container #grid0 and not #out(purple). When both #grid1(blue) and #out(purple) purple say they depend on each other then it creates a cyclic dependency.
Sometimes the size of a percentage-sized box’s containing block depends on the intrinsic size contribution of the box itself, creating a cyclic dependency. When calculating the intrinsic size contribution of such a box (including any calculations for a content-based automatic minimum size), a percentage value that resolves against a size in the same axis as the intrinsic size contribution (a cyclic percentage size) is resolved specially: ref
If the box is non-replaced, then the entire value of any max size property or preferred size property (width/max-width/height/max-height) specified as an expression containing a percentage (such as 10% or calc(10px + 0%)) that is cyclic is treated for the purpose of calculating the box’s intrinsic size contributions only as that property’s initial value. For example, given a box with width: calc(20px + 50%), its max-content contribution is calculated as if its width were auto.
That means percentage heights are treated as auto on purple. So it relies on it's children #large for height. As large has 100px height purple gets 100px height as well.
You said you added one more container around #out:
#div0 {
width: 200px;
height: 50px;
}
#div1 {
max-height: 100%;
background: blue;
/* it works using height instead of max-height*/
height: 100%;
}
#div2 {
height: auto;
/* uncomment following to get desired result */
/* height: inherit;*/
max-height: 100%;
}
#out {
height: auto;
max-height: 100%;
overflow: hidden;
background: purple;
width: 150px;
}
#large {
height: 100px;
width: 100px;
background: red;
}
<div id='div0'>
<div id='div1'>
<div id="div2">
<div id='out'>
<div id='large'>
</div>
</div>
</div>
</div>
</div>
In this code if you use inherit instead of auto it fixes the issue. Inherit makes it dependent on parent and auto on children.

Related

How to set height of flex row but still allow row to expand vertically?

Consider this very simple header:
.box {
height: 100%;
width: 50px;
background-color: blue;
}
.row {
display: flex;
height: 60px;
background-color: yellow;
}
<div class="row">
<div class="box"></div>
<h1>This string needs to be able to wrap</h1>
</div>
The blue box needs to be defined by the height of the row and the text needs to be able to wrap. But as you can see, when the text wraps it extends beyond the flexbox. The flexbox can't grow at all because I have defined its height. If I remove the height specification then text wrap works correctly but the blue box disappears. This is a quite frustrating problem that I have spent hours trying to figure out. Is there no way to say to the row "your height is 60px but you can go bigger if you need to".
What I've tried so far:
Use min-height: 60px. For some reason the blue box still doesn't show up when I do this.
Use max-height: 100px. The row defaults to that size which is too big for when the text doesn't wrap.
I guess I could write media queries to manually change the height of the row, but it seems like there should be a more flexboxy way of doing this. Any ideas?
Here is the JS Fiddle if you want to play with it.
You don't need height: 100%; on child element of flex element.
And if you want minimum height of 60px on parent element, use min-height: 60px; instead of height: 60px;
.box {
width: 50px;
background-color: blue;
}
.row {
display: flex;
background-color: yellow;
min-height: 60px;
}
Here is the fiddle
https://jsfiddle.net/3bzeht52/

button height in percent makes it flat [duplicate]

I am trying to set a <div> to a certain percentage height in CSS, but it just remains the same size as the content inside it. When I remove the HTML 5 <!DOCTYTPE html> however, it works, the <div> taking up the whole page as desired. I want the page to validate, so what should I do?
I have this CSS on the <div>, which has an ID of page:
#page {
padding: 10px;
background-color: white;
height: 90% !important;
}
I am trying to set a div to a certain percentage height in CSS
Percentage of what?
To set a percentage height, its parent element(*) must have an explicit height. This is fairly self-evident, in that if you leave height as auto, the block will take the height of its content... but if the content itself has a height expressed in terms of percentage of the parent you've made yourself a little Catch 22. The browser gives up and just uses the content height.
So the parent of the div must have an explicit height property. Whilst that height can also be a percentage if you want, that just moves the problem up to the next level.
If you want to make the div height a percentage of the viewport height, every ancestor of the div, including <html> and <body>, have to have height: 100%, so there is a chain of explicit percentage heights down to the div.
(*: or, if the div is positioned, the ‘containing block’, which is the nearest ancestor to also be positioned.)
Alternatively, all modern browsers and IE>=9 support new CSS units relative to viewport height (vh) and viewport width (vw):
div {
height:100vh;
}
See here for more info.
You need to set the height on the <html> and <body> elements as well; otherwise, they will only be large enough to fit the content. For example:
<!DOCTYPE html>
<title>Example of 100% width and height</title>
<style>
html, body { height: 100%; margin: 0; }
div { height: 100%; width: 100%; background: red; }
</style>
<div></div>
bobince's answer will let you know in which cases "height: XX%;" will or won't work.
If you want to create an element with a set ratio (height: % of it's own width), use the aspect-ratio property. Make sure height is not explicitly set on the element for it to work. https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio
.square {
width: 100%;
height: unset;
aspect-ratio: 1 / 1;
}
Historically, the best way to do this was to set the height using padding-bottom. Example for square:
<div class="square-container">
<div class="square-content">
<!-- put your content in here -->
</div>
</div>
.square-container { /* any display: block; element */
position: relative;
height: 0;
padding-bottom: 100%; /* of parent width */
}
.square-content {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
}
The square container will just be made of padding, and the content will expand to fill the container. Long article from 2009 on this subject: http://alistapart.com/article/creating-intrinsic-ratios-for-video
In order to use percentage(%), you must define the % of its parent element. If you use body{height: 100%} it will not work because its parent have no percentage in height. In that case in order to work that body height you must add this in html{height:100%}
In other cases to get rid of that defining parent percentage you can use
body{height:100vh}
vh stands for viewport height
You can use 100vw / 100vh. CSS3 gives us viewport-relative units. 100vw means 100% of the viewport width. 100vh; 100% of the height.
<div style="display:flex; justify-content: space-between;background-color: lightyellow; width:100%; height:85vh">
<div style="width:70%; height: 100%; border: 2px dashed red"></div>
<div style="width:30%; height: 100%; border: 2px dashed red"></div>
</div>
Sometimes, you may want to conditionally set the height of a div, such as when the entire content is less than the height of the screen. Setting all parent elements to 100% will cut off content when it is longer than the screen size.
So, the way to get around this is to set the min-height:
Continue to let the parent elements automatically adjust their height
Then in your main div, subtract the pixel sizes of the header and footer div from 100vh (viewport units). In css, something like:
min-height: calc(100vh - 246px);
100vh is full length of the screen, minus the surrounding divs.
By setting min-height and not height, content longer than screen will continue to flow, instead of getting cut off.
With new CSS sizing properties you can get away with not setting exact height on parent. The new block-size and inline-size properties can be used like this:
<!DOCTYPE html>
<style>
#parent {
border: 1px dotted gray;
height: auto; /* auto values */
width: auto;
}
#wrapper {
background-color: violet;
writing-mode: vertical-lr;
block-size: 30%;
inline-size: 70%;
}
#child {
background-color: wheat;
writing-mode: horizontal-tb;
width: 30%; /* set to 100% if you don't want to expose wrapper */
height: 70%; /* none of the parent has exact height set */
}
</style>
<body>
<div id=parent>
<div id=wrapper>
<div id=child>Lorem ipsum dollar...</div>
Resize the browser window in full page mode. I think the values are relative to viewport height and width.
For more info refer: https://www.w3.org/TR/css-sizing-3/
Almost all browsers support it: https://caniuse.com/?search=inline-size

Evaluating percentages to pixels in SASS

Currently, I'm setting a variable to correspond to a circle's width and height, like so:
$circle-diameter: 70%;
.circle {
width: $circle-diameter;
height: $circle-diameter;
}
However, the circle's width becomes 70% of the parent element's width, and the height becomes 70% of the parent element's height, which yields an oval that is wider than it is tall. Ideally, I'd like to convert .circle-diameter to a fixed size and assign the circle's width and height to that fixed size. Is there a solution for this in CSS/SASS?
You can use padding-top instead of height, it will work because padding is relative to parent width.
.circle{
width: 70%;
padding-top: 70%;
/* height: 0; */
}
http://codepen.io/yukulele/pen/PzGgNM
What you are looking for is to have a fixed ratio between width and height. For a circle tho, the width/height ratio is 1. There's a hacky way to accomplish that task. First I'd like to write a css class that always provides us a space that has width/height ratio of 1. To do so:
See Fiddle
Why this works? Because, If you use percentage based units on padding, It always be relative to element's width. See reference
Next I always like to use absolute hack to provide myself a workaround in that nicely 1/1 ratio square that we've create.
See Fiddle 2
Using position: absolute for our own good, we've created a element that has a fixed ratio and has a working width/height properties.
After It depends on what you need to do. In your case I've created a nice circle for to examine the situation.
See Fiddle 3
Working source code
**Css**
.ratio-1 {
position: relative;
width: 100%;
padding-top: 100%;
background-color: silver;
}
.im-something-has-some-width {
width: 200px;
border: 3px solid lime;
}
.space-provider {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.yay-i-have-a-square-field {
// lets use it for our own goods!
width: 100%;
height: 100%;
background-color: skyblue;
border-radius: 50%;
}
Html
<div class="im-something-has-some-width">
<div class="ratio-1">
<div class="space-provider">
<div class="yay-i-have-a-square-field">
</div>
</div>
</div>
</div>

Why Does The overflow-y Property Not Work With Percent Height

I'm trying to use percentage height with overflow-y:auto; and instead of creating a scroll bar on the side of the div, it's using the page scroll bar.
Here's an example of want I'm getting at: http://jsfiddle.net/hmwe2jty/
Is it possible to use this property with percent height?
TL;DR Use the viewport height/width instead of a percentage. Change 100% to 100vh, and you're done!
EDIT:
The percentages take the precentage of the parent element. For example:
console.log("Parent's width: " + document.getElementById("parent").offsetWidth);
console.log("Child's width: " + document.getElementById("child").offsetWidth);
#parent {
background: yellow;
width: 500px;
height: 150px;
}
#child {
background: orange;
width: 50%;
height: 100px;
}
<div id="parent">
<div id="child">
I am 250px wide!
</div>
</div>
The new CSS3 viewport units use the user's viewport as a base. For example:
console.log("Parent's width: " + document.getElementById("parent").offsetWidth);
console.log("Child's width: " + document.getElementById("child").offsetWidth);
#parent {
background: yellow;
width: 500px;
height: 150px;
}
#child {
background: orange;
width: 50vw;
height: 100px;
}
<div id="parent">
<div id="child">
My width is 50% of the user's viewport, regardless of the size of my parent!
</div>
</div>
Because the body element is a bit weird, it's default behaviour is to shrink to fit is contents. So:
body {
background: yellow;
border: 1px solid red;
}
The body element wraps around it contents, <br>
but the backgound just ignores this behaviour.
So, since the parent element is the body, you will need to use the new vw and vh units. Read a article on CSS Tricks
EDIT 2:
Another way to choose the viewport as parent would be to make the element's position either fixed or absolute. In that instance the parent would become the viewport, thus giving you the needed value.
use this css for div which height must dimensioned in percents of parent element:
.child {
position: absolute;
top: 10px;
bottom: 0px;
}
It is considering 100% of the parent, which is the body. Hence it occupies the height of complete space available. Specify height a lesser amount in % rather than 100 (if you specifically prefer percent). It is upto you what you chose.

Dynamically scale images by height using pure CSS in Chrome 27 and above

Thanks to James Montagne's solution I built a one-row-gallery which scales images in a specific behaviour just using CSS.
Works great - except in Chrome 27 and above. Here the images' width stay at the initial value while the heights scale properly.
Please check this Fiddle or the code below:
HTML:
<div>
<img src="http://placekitten.com/200/300" class="vert"/>
<img src="http://placekitten.com/500/200" class="horiz"/>
<img src="http://placekitten.com/200/300" class="vert"/>
<img src="http://placekitten.com/400/300" class="horiz"/>
<img src="http://placekitten.com/200/300" class="vert"/>
</div>
CSS:
body,html{
height: 100%;
}
div{
white-space: nowrap;
height: 100%;
}
img{
min-height: 200px;
height: 100%;
vertical-align: top;
}
.horiz{
max-height: 300px;
}
.vert{
max-height: 500px;
}
I already dug through the Chrome 27 changelog (~13MB) but didn't find any useful info on that matter.
Any ideas how to avoid the images to blur on a window resize in Chrome >= 27?
If you want to change the dimensions of images with CSS, you should choose one dimension to change and let the other adjust automatically.
In this case, if you're more concerned with the width of the images, you could get rid of min-height and do something like this:
body,html{
height: 100%;
}
div{
height: 100%;
width: 100%;
padding: 0;
}
img{
float: left;
height: auto;
vertical-align: top;
width: 19%;
margin: 0.5%;
}
See example here.
Since I know you have a row of 5 images, we can use a width of 19% of the div width and fit them nicely.
EDIT
On the other hand, if you're looking to control minimum and maximum heights, you can wrap your images in a container, specify an explicit height on that container, and position the images within the container. Here you lose the ability to control keeping all images on one line while maintaining the original aspect ratio.
This example is here.

Resources