I want:
.parent has height based on content, but with max-height
children have height based on content
.second has height based on content, but with respect to .parent max-height
But IE do problems. Other browsers work good.
HTML:
<div class=buggedFix>
<div class=parent>
<div class=first>...</div>
<div class=second><div class=big>...</div></div>
<div class=third>...</div>
</div>
</div>
CSS:
/*.buggedFix{display:flex;}*/
.parent{display:flex;flex-direction: column;width:250px;max-height:200px;}
.first{background:pink;flex: 0 1 auto;}
.third{background:yellow;flex: 0 1 auto;}
.second{background:brown;flex: 1 1 auto;overflow: auto}
.big{background:red;height:600px;margin:10px}
Bad 1: https://jsfiddle.net/fpnjwp0j/3/
Bad 2: https://jsfiddle.net/j53ds1mb/3/
Change the first and third rule's flex-shrink value to 0
Updated fiddle
Stack snippet
.buggedFix {
display: flex;
}
.parent {
display: flex;
flex-direction: column;
width: 250px;
max-height: 200px;
}
.first {
background: pink;
flex: 0 0 auto; /* changed */
}
.third {
background: yellow;
flex: 0 0 auto; /* changed */
}
.second {
background: brown;
flex: 1 1 auto;
overflow: auto
}
.big {
background: red;
height: 600px;
margin: 10px
}
<div class=buggedFix>
<div class=parent>
<div class=first>This is OK. This is OK. This is OK. This is OK. This is OK. This is OK. This is OK. This is OK. </div>
<div class=second>
<div class=big>parent max-height is ignored!</div>
</div>
<div class=third>This is OK. This is OK. This is OK. This is OK.</div>
</div>
</div>
Related
image wireframe
I would like to recreate messaging phone app in html and css. So the app must be full frame without any overflow.
The trick is the bottom part (in red) must be resizable according to the child content. So I used flex (with flex-direction: column) to manage my layout.
The problem is : when the content (in yellow) grow up, the core part will compress the red part. My goal is to overflow, with a scrollbar, the content inside the core part and don't change the size of the red div.
index.html
<body>
<div id="header">
</div>
<div id="core">
<div class="conainer" style="">
<div class="row">
<div class="two columns"></div>
<div class="ten columns">
<div class="msgright">
.
</div>
</div>
</div>
<div class="row">
<div class="ten columns">
<div class="msgright">
.
</div>
</div>
<div class="two columns"></div>
</div>
</div>
</div>
<div id="footer">
</div>
index.css
html, body, div {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
max-height: 100%;
overflow: hidden;
}
body {
display: flex;
flex-direction: column;
}
#header {
height: 50px;
background: #2A9D8F;
flex: 0 0 auto;
}
#core {
background-color: #264653;
flex: 1;
display: flex;
align-items: flex-end;
}
#footer {
height: auto;
background-color: red;
min-height: 50px;
flex: 0 0 auto;
}
.conainer {
flex: 0 0 100%;
}
.row {
margin: 5px;
background-color: yellow;
height: 130px;
}
https://codepen.io/jln_brtn/pen/pobVZBv
Best regards and thank you for your help.
I'm not sure if I understand the problem correctly but since your .row elements have a fixed height: 130px, the element should not be able to grow any further. Overflow styling to .row elements can be added like this:
.row {
overflow-y: scroll;
}
If it is just the #core element, then you can do something like this:
#core {
overflow-y: scroll;
}
For this instance I would suggest to use CSS Grid instead of Flexbox, and giving both <header> and <footer> the space they need, while the <main> gets the rest. This means that both <header> and <footer> stay were they are, even if <main> needs more space for its content, meaning <main> will get a scrollbar.
You can achieve the same by using position: fixed and setting a margin to top and bottom, with fixed heights of <header> and <footer>, and sizing <main> with height: calc(100% - HEIGHT_OF_HEADER - HEIGHT_OF_FOOTER). The problem with this is maintenance, as you would always have to check and revalidate the heights when changing something.
html, body {
margin: 0;
width: 100%;
height: 100%;
}
body {
display: grid;
grid-template-rows: auto 1fr auto;
}
header {
height: 3.125rem;
background: #2A9D8F;
}
main {
padding: 0.3125rem;
display: flex;
flex-flow: column;
gap: 0.3125rem;
background: #264653;
overflow: hidden auto;
}
footer {
height: 3.125rem;
background: red;
}
main > div {
flex-shrink: 0;
height: 8.125rem;
background: yellow;
}
<header></header>
<main>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</main>
<footer></footer>
Imagine having this situation: a simple 3 rows layout made with flexbox, with the central row filling all the space available. Pretty standard stuff.
<body>
<div class="container">
<div class="flex-container">
<div>header</div>
<div class="content">
<div class="item red">asdasd</div>
<div class="item yellow">asdasd</div>
<div class="item green">asdasd</div>
</div>
<div>footer</div>
</div>
<div>
<body>
Here the CSS:
html,
body,
.container {
height: 100%;
}
.flex-container {
height: 100%;
display: flex;
flex-direction: column;
}
.flex-container .content {
flex: 1;
}
.flex-container .content .item {
height: 100%;
}
(omitting css for background colors, you can guess it).
The problem is that the "content" div does not push down the footer div, keeping it at the bottom of the page, like is position:fixed with bottom: 0.
Scrolling the page show, except for this problem, the correct behavior, with 3 div with different color all sizing 100% the browser window.
What I'm missing?
EDIT: look at this jsfiddle
https://jsfiddle.net/rq1xywng/
I am not sure about what you are looking for. May be it will be help for you.
html,
body {
margin: 0;
padding: 0;
box-sizing: border-box;
height: 100vh;
min-height: 100vh;
}
.container {
height: 100vh;
min-height: 100vh;
background-color: fuchsia;
}
.header, .footer {
height: 30px;
}
.flex-container .content {
display: flex;
height: 100%;
height: calc(100vh - 60px);
}
.flex-container .content .item {
width: 100%;
height: 100%;
}
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
.green {
background-color: green;
}
<div class="container">
<div class="flex-container">
<div class="header">header</div>
<div class="content">
<div class="item red">asdasd</div>
<div class="item yellow">asdasd</div>
<div class="item green">asdasd</div>
</div>
<div class="footer">footer</div>
</div>
<div>
So you have couple of errors here:
you set EVERY ITEM IN THE CONTAINER to be 100% - this amounts to 300% :)
their parent is "only" 100%
footer will be hidden unless given height
you used vh and % combined in an unhealthy way.
you should have 2 flex components:
.flex-container - to match to screen size
.flex-container .content - to be able to stretch the items
You should set .item to flex: 1;
Here is a working version: https://jsfiddle.net/oj0thmv7/5/
Here is a working example with scroll: https://jsfiddle.net/oyLbxsrc/
If you change the 100% to 100vh this works
.flex-container .content .item {
height: 100vh;
}
Or have I misunderstood the issue?
I'm trying to accomplish this design by using flexbox:
It's supposed to be a one page website.
.container {
display: flex;
}
.big {
flex: 2;
height: 70vh;
background: gray;
}
.small {
flex: 1;
height: 70vh;
background: gray;
}
<div class="container">
<div class="small">
</div>
<div class="smallest">
</div>
<div class="big">
</div>
</div>
I have no idea how to implement the "smallest" div to be 25% of the big, let alone make the "small" 75% of the big one.
Also the height really confuses me, I need them to always have the same height.
With flexbox you can wrap the small and the smallest into a separate div and use column flexbox on the left section.
I have no idea how to implement the "smallest" div to be 25% of the big
25% to 75% ratio means 1:3 ratio - and in flexbox language that is flex: 1 to the small element and flex: 3 to the big element.
Also the height really confuses me, I need them to always have the same height.
You can set the height of the container to the container element - your flexbox will fill to this height.
See demo below:
.container {
display: flex;
height: 70vh;
}
.big {
flex: 3;
background: gray;
margin-left: 5px;
}
.left {
flex: 1;
display: flex;
flex-direction: column;
}
.left .small {
background: gray;
flex: 3;
}
.left .smallest {
margin-top: 5px;
background: gray;
flex: 1;
}
<div class="container">
<div class="left">
<div class="small">
</div>
<div class="smallest">
</div>
</div>
<div class="big">
</div>
</div>
I have a html layout like this:
,-------------.
|,-----------.|
|| child 1 ||
|`-----------'|
|,-----------.|
|| child 2 ||
|| ||
|| ||
|| ||
|| ||
|`-----------'|
`-------------'
The container is given a height value, say 100vh, and child 1 has a fixed height. I want the child 2 to automatically fill the remaining height.
I know there is a flexbox solution:
.container {
display: flex;
flex-direction: column;
}
.child-1 {
flex-shrink: 0;
flex-grow: 0;
}
.child-2 {
flex-grow: 1;
}
The solution works as alone, but if I want a third child child 3 inside child 2 with a height: 100%, it fails. I need to make child 2 flex and set child 3 to flex-grow: 1.
This kind of flex-inheriting become really frustrating as the nesting goes deeper. Also it violates "Seperation of Concern" since the DOM structure only works when all the nodes are properly set to display: flex.
Below is jsfiddle demonstrating the problem.
html,
body {
margin: 0;
}
div {
width: 100%;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
.child-1 {
height: 50px;
flex-shrink: 0;
flex-grow: 0;
}
.child-2 {
flex-grow: 1;
}
.child-3 {
height: 80%;
}
/* irrelevant styles like background-color etc. */
.container.irrelevant {
width: 100px;
background: green;
float: left;
margin-right: 20px;
}
.child-1.irrelevant {
background: red;
}
.child-2.irrelevant {
background: magenta;
}
.child-3.irrelevant {
background: yellow;
}
<div class="container irrelevant">
<div class="child-1 irrelevant">
Child 1
</div>
<div class="child-2 irrelevant">
Child 2<br> Seems like it works
</div>
</div>
<div class="container irrelevant">
<div class="child-1 irrelevant">
Child 1
</div>
<div class="child-2 irrelevant">
Child 2
<div class="child-3 irrelevant">
But it doesn't, child 3 should fill 80% height of the child 2.
</div>
</div>
</div>
Oh you can use calc for this. Something like this;
.child-2 { height: calc(100vh - 100px); }
Assuming the fixed height for .child-1 is 100px.
If you want something more dynamic use #patelarpan's solution, but this is quick and easy (and not dirty).
Add height: 100% to child 2.
you can use CSS grid also but it's not supported in all browsers.
html,
body {
margin: 0;
}
div {
width: 100%;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
.child-1 {
height: 50px;
flex-shrink: 0;
flex-grow: 0;
}
.child-2 {
flex-grow: 1;
height: calc(100% - 50px); /* add this line */
}
.child-3 {
height: 80%;
}
/* irrelevant styles like background-color etc. */
.container.irrelevant {
width: 100px;
background: green;
float: left;
margin-right: 20px;
}
.child-1.irrelevant {
background: red;
}
.child-2.irrelevant {
background: magenta;
}
.child-3.irrelevant {
background: yellow;
}
<div class="container irrelevant">
<div class="child-1 irrelevant">
Child 1
</div>
<div class="child-2 irrelevant">
Child 2<br> Seems like it works
</div>
</div>
<div class="container irrelevant">
<div class="child-1 irrelevant">
Child 1
</div>
<div class="child-2 irrelevant">
Child 2
<div class="child-3 irrelevant">
But it doesn't, child 3 should fill 80% height of the child 2.
</div>
</div>
</div>
It seems that .child-3 cannot properly calculate parents height unless it has set flex-basis. So you can fix this by using flex: 1 on child-2 DEMO or by just adding flex-basis: 0% DEMO which is the same thing that the browser will do if you use flex: 1.
html,
body {
margin: 0;
}
div {
width: 100%;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
.child-1 {
flex: 1;
height: 50px;
flex-shrink: 0;
flex-grow: 0;
}
.child-2 {
flex: 1;
}
.child-3 {
height: 80%;
}
/* irrelevant styles like background-color etc. */
.container.irrelevant {
width: 100px;
background: green;
float: left;
margin-right: 20px;
}
.child-1.irrelevant {
background: red;
}
.child-2.irrelevant {
background: magenta;
}
.child-3.irrelevant {
background: yellow;
}
<div class="container irrelevant">
<div class="child-1 irrelevant">
Child 1
</div>
<div class="child-2 irrelevant">
Child 2<br> Seems like it works
</div>
</div>
<div class="container irrelevant">
<div class="child-1 irrelevant">
Child 1
</div>
<div class="child-2 irrelevant">
Child 2
<div class="child-3 irrelevant">
But it doesn't, child 3 should fill 80% height of the child 2.
</div>
</div>
</div>
.wrapper {
background: tomato;
width: 100px;
display: flex;
}
.left {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.right {
}
<div class=wrapper>
<div class="left">
title title title title
</div>
<div class="right">
123
</div>
</div>
I have a DIV (wrapper) with 2 DIVs inside: left and right.
wrapper's width is known. I want to truncate text in left DIV if it doesn't fit. Text in right should be always visible. I tried several techniques here, but the only one is working is based on flex box. Unfortunately it doesn't work on IE10. I used -ms- prefixes, without success.
Is there any way to make it work on IE10?
I can't test this on IE10 myself, though since its -ms-flex defaults to 0 0 auto, you will need to add -ms-flex: 0 1 auto to the left, so it is allowed to shrink.
And as the default on IE11 and the rest of the browsers is 0 1 auto, they work as is.
Fiddle demo
Stack snippet
.wrapper {
background: tomato;
width: 100px;
display: -ms-flexbox; /* IE10 */
display: flex;
}
.left {
-ms-flex: 0 1 auto; /* IE10 */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.right {
}
<div class=wrapper>
<div class="left">
title title title title
</div>
<div class="right">
123
</div>
</div>
Here is an idea without the use of flexbox but using display:table:
.wrapper {
background: tomato;
width: 100px;
display: table;
}
.left {
display: table-cell;
position: relative;
width: 100%;
}
.left span {
position: absolute;
top:0;
left:0;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.right {
display: table-cell;
}
<div class=wrapper>
<div class="left">
<span>
title title title title title title
</span>
</div>
<div class="right">
123
</div>
</div>