Why nested flexboxes are not working in Chrome? [duplicate] - css

This question already has answers here:
Chrome / Safari not filling 100% height of flex parent
(5 answers)
Closed 4 years ago.
I have code with nested flexboxes: https://jsfiddle.net/tomrhodes/8pf1q706/ and I expect that "content 2" are always fills the remaining space. It works on Firefox, but it does not work in Google Chrome, why it is not working?
It is very important not to use one div element both as the item and as the parent of the flexbox, so - I have clearly separated these role.
html,
body {
height: 100%;
margin: 0;
border: solid magenta;
}
.row2 {
background: #f8f9fa;
margin-top: 20px;
flex: 0 1 auto;
-webkit-flex: 0 1 auto;
}
.container {
display: flex;
display: -webkit-flex;
flex-flow: column;
-webkit-flex-flow: column;
height: 100%;
border: solid blue;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
border: solid blue;
}
.outsidebox {
display: flex;
flex-flow: column;
height: 100%;
border: solid purple;
}
.headerstyle {
flex: 0 1 auto;
border: solid green;
}
.contentstyle {
flex: 1 1 auto;
border: solid green;
}
.footerstyle {
flex: 0 1 40px;
border: solid green;
}
.wrapper {
flex: 1 1 auto;
border: solid yellow;
}
<div class="outsidebox">
<div class="box">
<div class="headerstyle">header</div>
<div class="contentstyle">
<div class="outsidebox">
<div class="headerstyle">header 2</div>
<div class="contentstyle">content 2</div>
<div class="footerstyle">footer 2</div>
</div>
</div>
<div class="footerstyle">footer</div>
</div>
</div>

I think this is what you are after - I have made the content style flex with a column direction and flex grow so it fills the parent container:
* {box-sizing:border-box;}
html,
body {
height: 100%;
margin: 0;
border: solid magenta;
}
.row2 {
background: #f8f9fa;
margin-top: 20px;
flex: 0 1 auto;
-webkit-flex: 0 1 auto;
}
.container {
display: flex;
display: -webkit-flex;
flex-flow: column;
-webkit-flex-flow: column;
height: 100%;
border: solid blue;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
border: solid blue;
}
.outsidebox {
flex-grow:1;
display: flex;
flex-flow: column;
height: 100%;
border: solid purple;
}
.headerstyle {
flex: 0 1 auto;
border: solid green;
}
.contentstyle {
flex-grow:1;
display:flex;
flex-direction:column; /* make this flex and column */
border: solid green;
width:100%;
}
.footerstyle {
flex: 0 1 40px;
border: solid green;
}
.wrapper {
flex: 1 1 auto;
border: solid yellow;
}
<div class="outsidebox">
<div class="box">
<div class="headerstyle">header</div>
<div class="contentstyle">
<div class="outsidebox">
<div class="headerstyle">header 2</div>
<div class="contentstyle">content 2</div>
<div class="footerstyle">footer 2</div>
</div>
</div>
<div class="footerstyle">footer</div>
</div>
</div>
Or simplified:
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
border: solid magenta;
}
.outsidebox {
display: flex;
flex-flow: column;
flex-grow: 1;
height: 100%;
border: solid purple;
}
.headerstyle {
flex: 0 1 auto;
border: solid green;
}
.contentstyle {
flex-grow: 1;
display: flex;
flex-direction: column;
border: solid green;
width: 100%;
}
.footerstyle {
flex: 0 1 40px;
border: solid green;
}
<div class="outsidebox">
<div class="headerstyle">header</div>
<div class="contentstyle">
<div class="outsidebox">
<div class="headerstyle">header 2</div>
<div class="contentstyle">content 2</div>
<div class="footerstyle">footer 2</div>
</div>
</div>
<div class="footerstyle">footer</div>
</div>

Related

How to remove the empty space between elements?

I have made a calculator using one parent div and plenty of child divs, the children are in html. After that I styled it using flex-box and it is almost done; nevertheless there is an empty space between first div (.result) and the rest of the divs (.btn).
I want to remove that empty space which is shown in picture below:
I tried to use flex-box method to arrange these div elements like blocks.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
.kalkulator {
display: flex;
flex-wrap: wrap;
height: 50vh;
width: 30vw;
margin: 0 auto 0 auto;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
Apply align-content: flex-start to the flex container.
The default setting is align-content: stretch, which will spread the items across the container. With flex-start, they'll be packed together at the top.
Your code:
.kalkulator {
display: flex;
flex-wrap: wrap;
height: 50vh;
width: 30vw;
margin: 0 auto 0 auto;
border: 2px dashed red;
background-color: yellow;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
Modified code:
.kalkulator {
display: flex;
flex-wrap: wrap;
height: 50vh;
width: 30vw;
margin: 0 auto 0 auto;
border: 2px dashed red;
background-color: yellow;
align-content: flex-start;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
It seems too much* for one flexbox. Create the layout with two nested ones: one for the vertical partition of the calculator to the result and the buttons, and another one for the fluid positioning of the buttons within the buttons div:
<div class="kalkulator">
<div class="result">wynik</div>
<div class="buttons">[...]</div>
</div>
.kalkulator {
display: flex;
flex-direction: column;
}
.result {
flex-basis: 10vh;
}
.buttons {
flex-grow: 1; /* Fill the rest */
display: flex;
flex-wrap: wrap;
}
.btn {
flex-grow: 1;
flex-basis: 33%;
justify-content: center;
align-items: center;
display: flex;
}
For placing the buttons under the result box you need a flexbox with a vertical main axis (flex-direction: column). For placing the buttons in a row, a flexbox with a horizontal main axis (the default flex-direction: row).
See the following code, here I removed height: 50vh; property from .kalkulator class:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
.kalkulator {
display: flex;
flex-wrap: wrap;
/* height: 50vh; */
width: 30vw;
margin: 0 auto 0 auto;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
Viewport Height (vh): This unit is based on the height of the viewport. A value of 1vh is equal to 1% of the viewport height.
Height of container is 50vh and height of result is 10vh. This leaves 40vh for button panel, or 6.67vh per row. If you want to preserve container height, you can just add height: 6.67vh; to .kalkulator div. This will set button height to fixed value, so there won't be any empty space.

Make child div fill parent div with scroll

I am having problems with flexbox layout parenting a child control.
html, body, .frame{
margin: 0;
height: 100%;
}
* {
box-sizing: border-box;
}
.frame{
display: flex;
flex-flow: column;
}
.header{
background-color: yellow;
height: 40px;
}
.body-outer{
background-color: green;
flex: 1;
display: flex;
flex-flow: column;
}
.body-inner{
border: 1px solid red;
flex: 1;
}
.big-text{
height: 2000px;
border: 1px solid lightblue;
overflow: auto;
margin: 5px;
}
<div class="frame">
<div class="header">header</div>
<div class="body-outer">
<div>subheader</div>
<div class="body-inner>">
<div class="big-text">big text</div>
</div>
</div>
</div>
The 'body-inner' div is meant to fill the remaining space with flex: 1 and the 'big-text' is supposed to fill the whole space of 'body-inner' without expanding it but showing scroll bars.
You have the overflow applied to the content. It should be applied to the container that will be overflowed.
Also, you need a fixed height, so that the overflow property has something to overflow.
Try this:
.frame {
display: flex;
flex-flow: column;
height: 100vh;
}
.header {
background-color: yellow;
height: 40px;
}
.body-outer {
height: calc(100vh - 40px); /* new */
background-color: green;
/* flex: 1; */
display: flex;
flex-flow: column;
}
.body-inner {
border: 1px solid red;
flex: 1;
overflow: auto; /* moved here */
}
.big-text {
height: 2000px;
border: 1px solid lightblue;
/* overflow: auto; */
margin: 5px;
}
body {
margin: 0;
}
* {
box-sizing: border-box;
}
<div class="frame">
<div class="header">header</div>
<div class="body-outer">
<div>subheader</div>
<div class="body-inner">
<div class="big-text">big text</div>
</div>
</div>
</div>

Centering flexbox content after a linebreak

I am trying to center text inside a parent element of limited width. However the text is set in a large font, which might cause a line-break. However the element line-break does not decrease the width of the element. Is there a way to center a text inside a parent wrapper if the text does not fit?
You can find a failing example in the stack-overflow code sample. The top box has a line-break and should still be centered.
.wrapper {
width: 900px;
margin: 0 auto;
background: lightgrey;
}
.box {
display: flex;
align-items: center;
justify-content: center;
width: 300px;
height: 200px;
border: 1px solid green;
}
.box:nth-child(1) {
background: green;
font-size: 45px;
}
.box:nth-child(2) {
background: orange;
}
<div class="wrapper">
<div class="box"><h3>Lorem Ipsum</h3></div>
<div class="box"><h3>Lorem Ipsum</h3></div>
</div>
Just add the text-align: center;
.wrapper {
width: 900px;
margin: 0 auto;
background: lightgrey;
}
.box {
display: flex;
align-items: center;
justify-content: center;
/* text-align: center; */
width: 300px;
height: 200px;
border: 1px solid green;
}
.box > * {
flex: 0 0 50%;
}
.box:nth-child(1) {
background: green;
font-size: 45px;
}
.box:nth-child(2) {
background: orange;
}
<div class="wrapper">
<div class="box"><h3>Lorem Ipsum</h3></div>
<div class="box"><h3>Lorem Ipsum</h3></div>
</div>
You can use width:min-content; with the first child (https://caniuse.com/#feat=intrinsic-width)
.wrapper {
width: 900px;
margin: 0 auto;
background: lightgrey;
}
.box {
display: flex;
align-items: center;
justify-content: center;
width: 300px;
height: 200px;
border: 1px solid green;
}
.box:nth-child(1) h3 {
width:-webkit-min-content;
width:-moz-min-content;
width:min-content;
border:1px solid;
}
.box:nth-child(1) {
background: green;
font-size: 45px;
}
.box:nth-child(2) {
background: orange;
}
<div class="wrapper">
<div class="box">
<h3>Loreme Ipsum</h3>
</div>
<div class="box">
<h3>Lorem Ipsum</h3>
</div>
</div>

Flexbox align column to the right if there is only one column

I have a two column flexbox layout. However, sometimes there is only one column, in which case the column should be aligned to the right. Currently the column is aligned to the left.
https://codepen.io/sleepydada/pen/rzVRxL
HTML:
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer">first answer</div>
</div>
SCSS:
* {
box-sizing: border-box;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
&:first-of-type {
background: #ccc;
}
.answer {
background: crimson;
margin: 20px 0;
border: 1px solid blue;
flex: 0 0 33.3333%;
}
}
You can add this CSS:
.answer:only-of-type {
margin-left: auto;
}
From MDN
The :only-of-type CSS pseudo-class represents an element that has no
siblings of the same type.
codepen
* {
box-sizing: border-box;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.answers:first-of-type {
background: #ccc;
}
.answers .answer {
background: crimson;
margin: 20px 0;
border: 1px solid blue;
flex: 0 0 33.3333%;
}
.answers .answer:only-of-type {
margin-left: auto;
}
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer">first answer</div>
</div>
You can add an invisible div with height set to 0
* {
box-sizing: border-box;
}
.invisible {
height: 0;
border: none !important;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.answers:first-of-type {
background: #ccc;
}
.answers .answer {
background: crimson;
margin: 20px 0;
border: 1px solid blue;
flex: 0 0 33.3333%;
}
<div class="answers">
<div class="answer">first answer</div>
<div class="answer invisible"><!--invisible div--></div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer invisible"><!--invisible div--></div>
<div class="answer">first answer</div>
</div>

Flexbox centering and overflow bug in IE10?

What I want to do basically is have a header and a container always centered if they're small than the screen (body with 100% height). In case the content and header are bigger than the screen, then allow to scroll inside its container (notice that the header shouldn't be scrollable).
I managed to make it work in Chrome but not in IE10. This is the JSFiddle.
var p = $('p');
$('button').click(function(){
for(var i=0; i<30; i++){
$('.content').append(p.clone());
}
});
.screen{
border: 1px solid red;
padding: 3px;
height: 300px;
display: flex;
display: -ms-flexbox;
justify-content: center;
-ms-flex-pack: center;
flex-direction: column;
-ms-flex-direction: column;
}
.header{border: 1px solid blue; padding: 10px;}
.content{ border: 1px solid green; background: #aaa; overflow: auto;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Add more content</button>
<div class="screen">
<div class="header">
Header
</div>
<div class="content">
<p>This is the content</p>
</div>
</div>
http://jsfiddle.net/w8zg8hr2/2/
You need to add flex: 0 1 auto; to the .content div and overflow: auto; to the .screen container. IE10 uses the 2012 syntax which defaults to flex: 0 0 auto instead of the modern value of flex: 0 1 auto;
var p = $('p');
$('button').click(function () {
for (var i = 0; i < 30; i++) {
$('.content').append(p.clone());
}
});
.screen {
border: 1px solid red;
padding: 3px;
height: 300px;
display: flex;
display: -ms-flexbox;
justify-content: center;
-ms-flex-pack: center;
flex-direction: column;
-ms-flex-direction: column;
overflow: auto;
}
.header {
border: 1px solid blue;
padding: 10px;
}
.content {
border: 1px solid green;
background: #aaa;
overflow: auto !important;
flex: 0 1 auto; /* Add this property value */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Add more content</button>
<div class="screen">
<div class="header">Header</div>
<div class="content">
<p>This is the content</p>
</div>
</div>
Browserstack screenshot of Win7/IE10:

Resources