Reputation: 822
I have a CSS issue which perhaps is too specific for this forum but I think maybe other people will benefit from it as well. I have an element which has a max-height set, inside it there are two additional elements like so:
Code example:
<div class="container">
<div class="inner-element">...</div>
<div class="inner-element">...</div>
</div>
The the content of the two inner element has unknown height, which can be changed in runtime. I want the following behavior:
If the sum of the contents are less than max-height, they should each have their content's height, and the outer element should not be higher then their content:
If the sum of contents is more than max-height and both are more than half of it, each should get half the max-height:
If the sum of contents is more than max-height but one of the elements' content is less then 50%, the smaller one should have its content's height, and the bigger one should fill the remaining space:
I feel like that should be possible with pure CSS but I couldn't figure out a way to do it. Anyone has any idea?...
Upvotes: 7
Views: 8297
Reputation: 855
Here you go, a flexbox
is perfect for this case:
You can give the children also a max-height
.
The problem with that is that they cant be bigger of that value, if there is still space in the parent div.
If you dont have max-height
in the children they will fill all the available space if needed. But now you have the problem that if both if taller then half of the space, they won't share the space 50/50. They will share it proportional of their height.
If you really really want the condition of the 2. behavior you mentiont in your question you need to use javascript.
-> You can add both height from the children and if they the total is bigger than the max-height
you can set both to a spesific height.
#parent {
max-height: 180px;
width: 100px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
}
.child {
background: yellow;
border: 2px solid black;
overflow-x: hidden;
padding: 5px;
}
<body>
<div id="parent">
<div id="a" class="child">
test<br>te<br>sttes<br>ttes<br>ttes<br>tte<br>sttes<br>t<br>t<br>es<br>t<br>t<br>e<br>stt<br>e<br>s<br>t
</div>
<div id="b" class="child">
t<br>e<br>s<br>t
</div>
</div>
</body>
Upvotes: 1
Reputation: 18408
If you do not specify height
on container
then it's initial value is auto. Auto means it's height is determined by it's children. So height
will always be equal to it's content height.
max-height
is not same as height
, it is applied after height
is calculated ref. Setting max-height
doesn't mean you are setting height
also. You are just clipping the element height.
Your case 2 and 3 demands children to be dependent on parent containers
height. But the container's height is dependent on the children. That is why you'll need javascript to implement case 2 and 3.
In case if you decide to have fixed height to the container
then you can use grid with auto-fit
templet-rows to achieve all the test cases using pure CSS:
//the script is used only for increasing content heights for the demo
var c1, c2;
var r1, r2;
document.addEventListener('DOMContentLoaded', init);
function init() {
c1 = document.getElementById('c1');
c2 = document.getElementById('c2');
r1 = document.getElementById('r1');
r2 = document.getElementById('r2');
r1.addEventListener('change', update1);
r2.addEventListener('change', update2);
update1();
update2();
}
function update1() {
c1.style.height = r1.value + 'px';
c1.innerText = 'Content Height: ' + r1.value + 'px';
}
function update2() {
c2.style.height = r2.value + 'px';
c2.innerText = 'Content Height: ' + r2.value + 'px';
}
* {
box-sizing: border-box;
}
.container {
height: 200px;
border: 2px solid;
background-color: lemonchiffon;
display: grid;
grid-template-rows: repeat(auto-fit, minmax(0, min-content));
}
.container>div {
border: 1px dashed gray;
overflow: auto;
height: fit-content;
max-height: 100%;
}
.inner-element:nth-child(1) {
background: lightgreen;
}
.inner-element:nth-child(2) {
background: lightblue;
}
<div>
<label for="r1">Element one height: 0</label>
<input type="range" id="r1" name="r1" min="0" max="400" value="50">400
</div>
<div>
<label for="height2">Element two height: 0</label>
<input type="range" id="r2" name="r2" min="0" max="400" value="50">400
</div>
<div class="container">
<div class="inner-element">
<div id=c1></div>
</div>
<div class="inner-element">
<div id=c2></div>
</div>
</div>
Upvotes: 5
Reputation: 517
You do not need to put max-height
on any of the children.
Just put a max-height
on the parent, then the flexbox
will do the rest !
.grid {
--gutterH : 30px;
--gutterV : 30px;
display: flex;
flex-wrap: wrap;
flex-grow: 1;
width: calc(100% + var(--gutterV));
margin: calc(var(--gutterH) / -2) calc(var(--gutterV) / -2);
}
.grid-item {
--gridItemWidth : auto;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: flex-start;
margin: calc(var(--gutterH) / 2) calc(var(--gutterV) / 2);
width: calc(var(--gridItemWidth) - var(--gutterV));
}
.grid-item.grid-item--onethird {
--gridItemWidth : calc(100% / 3);
}
.container {
display: flex;
flex-direction: column;
width: 100%;
max-height: 250px;
border: solid 1px #000;
}
.inner-element {
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
overflow: hidden;
}
.inner-element:not(:last-child) {
border-bottom: solid 1px #000;
}
<div class="grid">
<div class="grid-item grid-item--onethird">
<!-- Case 1 -->
<div class="container">
<div class="inner-element">
1
</div>
<div class="inner-element">
2
</div>
</div>
</div>
<div class="grid-item grid-item--onethird">
<!-- Case 2 -->
<div class="container">
<div class="inner-element">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ut risus dapibus purus blandit tristique non vel purus. Nam bibendum elementum justo, rutrum tristique massa faucibus id. Integer ut metus justo. Etiam vitae congue risus. Nulla quis libero vel est fermentum efficitur. Cras mollis aliquet metus id rhoncus. Proin gravida, leo quis rhoncus lacinia, erat nulla consequat magna, at elementum dui tellus facilisis leo. Ut nec ex eleifend, scelerisque lorem nec, bibendum quam. Fusce quis sapien ut sapien lacinia congue.
</div>
<div class="inner-element">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ut risus dapibus purus blandit tristique non vel purus. Nam bibendum elementum justo, rutrum tristique massa faucibus id. Integer ut metus justo. Etiam vitae congue risus. Nulla quis libero vel est fermentum efficitur. Cras mollis aliquet metus id rhoncus. Proin gravida, leo quis rhoncus lacinia, erat nulla consequat magna, at elementum dui tellus facilisis leo. Ut nec ex eleifend, scelerisque lorem nec, bibendum quam. Fusce quis sapien ut sapien lacinia congue.
</div>
</div>
</div>
<div class="grid-item grid-item--onethird">
<!-- Case 3 -->
<div class="container">
<div class="inner-element">
1
</div>
<div class="inner-element">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ut risus dapibus purus blandit tristique non vel purus. Nam bibendum elementum justo, rutrum tristique massa faucibus id. Integer ut metus justo. Etiam vitae congue risus. Nulla quis libero vel est fermentum efficitur. Cras mollis aliquet metus id rhoncus. Proin gravida, leo quis rhoncus lacinia, erat nulla consequat magna, at elementum dui tellus facilisis leo. Ut nec ex eleifend, scelerisque lorem nec, bibendum quam. Fusce quis sapien ut sapien lacinia congue.
</div>
</div>
</div>
</div>
Upvotes: 1