ie 11: flex grow parent issue - css

I have such code:
https://plnkr.co/edit/ZAEzfAOCO0ZcSq2OR4Lp?p=preview
but this isn't working in ie, until I add height:0 (it's a very bad idea on parent element)
<body>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</body>
body, html {
min-height: 100%;
height: 100%;
}
.container {
width: 100%;
min-height: calc(100% - 80px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.container-item {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
content: "someText";
border-bottom: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
everything works fine in chrome and ff
(my parents should expand to fit parent)
Important!
I need a flexible solution, my code can have a lot of nested div's (not a constant value) between body and content divs.
for example:
<body>
<div>
<div>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</div>
</div>
</body>
or
<body>
<div>
<h3>text</h3>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</div>
</body>

If you have an unknown or nested markup before the container, you could add an extra wrapper within it (here inner), to overcome IE's min-height bug.
Fiddle sample 1 -- Fiddle sample 2
Stack snippet sample 1
html, body {
margin: 0;
}
.container {
display: flex;
}
.container .inner {
width: 100%;
min-height: calc(100vh - 100px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: flex;
flex-direction: column;
}
.container-item {
flex-grow: 1;
border: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
<div>
<h3>text</h3>
<div class="container">
<div class="inner">
<div class="container-item container-item-1">
</div>
<div class="container-item container-item-2">
</div>
<div class="container-item container-item-3">
</div>
</div>
</div>
</div>
Stack snippet sample 2
html, body {
margin: 0;
}
.container {
display: flex;
}
.container .inner {
width: 100%;
min-height: calc(100vh - 100px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: flex;
flex-direction: column;
}
.container-item {
flex-grow: 1;
border: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
<div>
<div>
<div class="container">
<div class="inner">
<div class="container-item container-item-1">
</div>
<div class="container-item container-item-2">
</div>
<div class="container-item container-item-3">
</div>
</div>
</div>
</div>
</div>

Related

Element does not expand to fill parent flex div

html,
body {
margin: 0;
height: 100%;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
height: 50px;
background-color: #2D4256;
}
.nav-centre {
margin: 0 auto;
width: 40%;
height: 100%;
}
.nav-container {
display: flex;
height: 100%;
align-items: center;
/* vertically centre */
}
.nav-item {
color: white;
width: 40px;
text-align: center;
}
.main-content {
height: calc(100% - 50px);
width: 100%;
position: absolute;
bottom: 0;
overflow-y: overlay;
display: flex;
justify-content: center;
}
.main-wrap {
width: 40%;
border-left: 1px solid black;
border-right: 1px solid black;
}
.box {
width: 200px;
height: 200px;
background: white;
border: 1px solid black;
margin: 10px;
}
<body>
<div class="navbar">
<div class="nav-centre">
<div class="nav-container">
<div class="nav-item">1</div>
<div class="nav-item">2</div>
<div class="nav-item">3</div>
<div class="nav-item">4</div>
</div>
</div>
</div>
<div class="main-content">
<div class="main-wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>
The main-wrap div is not expanding to fill the parent main-content div, how can I get the main-wrap element to expand to the full height of the parent?
https://codepen.io/woooof/pen/VwBLprj
The .main-wrapper is getting by default display:block, which doesn't match with the display:flex parent.
To get the value from the parent, you can use display: inherit. Once done, the elements inside won't respect their width. To fix that, you must wrap the elements, and for making it total height, You can use max-content.
.main-wrapper {
display: inherit;
flex-wrap: wrap;
height: max-content;
}
Result:
html,
body {
margin: 0;
height: 100%;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
height: 50px;
background-color: #2D4256;
}
.nav-centre {
margin: 0 auto;
width: 40%;
height: 100%;
}
.nav-container {
display: flex;
height: 100%;
align-items: center;
/* vertically centre */
}
.nav-item {
color: white;
width: 40px;
text-align: center;
}
.main-content {
height: calc(100% - 50px);
width: 100%;
position: absolute;
bottom: 0;
overflow-y: overlay;
display: flex;
justify-content: center;
}
.main-wrap {
width: 40%;
border-left: 1px solid black;
border-right: 1px solid black;
display: inherit;
flex-wrap: wrap;
height: max-content;
}
.box {
width: 200px;
height: 200px;
background: white;
border: 1px solid black;
margin: 10px;
}
<body>
<div class="navbar">
<div class="nav-centre">
<div class="nav-container">
<div class="nav-item">1</div>
<div class="nav-item">2</div>
<div class="nav-item">3</div>
<div class="nav-item">4</div>
</div>
</div>
</div>
<div class="main-content">
<div class="main-wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>
I am not a huge fan of making the size of one element (navbar) determine the position of the second element main-content (margin-top). where you have height: calc(100% - 50px); I would rather if the style of the first changes. Say for example we increase navbar font size, you would not need to adjust the second manually.
Here in this example I set the font-size on an ancestor block to change the nav buttons size and not have to change the content. font-size: 1.5rem;
Change it even larger; again no change to the content CSS;
I put a lot of comments in and some borders just to show where things line - that can and should all be removed for a production version.
html,
body {
margin: 0;
height: 100%;
/* stack the nav and the content blocks */
display: grid;
grid-template-rows: 1fr auto;
}
.navbar {
/* put the navbar at the top */
position: sticky;
top: 0;
background-color: #2D4256;
/* flex, default vertical/horizontal centers nav-centre in the flex */
display: flex;
}
.nav-centre {
margin: 0 auto;
display: flex;
}
.nav-container {
display: flex;
/* again these are the default here
flex-direction: row;
align-items: center;
justify-content: center;
*/
/* how much space above and below the yellow border nav container */
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.nav-item {
color: white;
/* 2 times font-size for cyan border items */
width: 2em;
text-align: center;
}
.main-content {
display: grid;
justify-content: center;
}
.main-wrap {
border-left: 1px solid black;
border-right: 1px solid black;
}
.box {
width: 200px;
height: 200px;
background: white;
border: 1px solid black;
margin: 10px;
}
/* below here is just for visual clarification and can be removed */
.navbar {
/* just to show you can style and not effect content block *
/* this can be on any of the three containers */
font-size: 1.5rem;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
.nav-centre {
border: 1px solid magenta;
padding: 2px;
}
.nav-container {
border: 1px solid yellow;
}
.nav-item {
border: 1px solid cyan;
/* you can space out the nav buttons */
margin: 0 0.25rem;
}
.main-content {
/* just to show it is below the navbar and separate */
border: solid red 1px;
margin-top: 0.25rem;
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.box {
background-color: #ffffdd;
}
<body>
<div class="navbar">
<div class="nav-centre">
<div class="nav-container">
<div class="nav-item">1</div>
<div class="nav-item">2</div>
<div class="nav-item">3</div>
<div class="nav-item">4</div>
</div>
</div>
</div>
<div class="main-content">
<div class="main-wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>

Have child span the full height of a growing flex item

EDIT: This may be a problem with Safari 14.0.x for macOS.
I’m trying to make the .block element in the middle .flex-item span the full height of its parent, but it instead just collapses.
body {
height: calc(100vh - 2 * 4px);
margin: 4px;
}
div {
box-sizing: border-box;
border-width: 0.8vh;
border-style: solid;
padding: 2vh;
}
.flex {
height: 100%;
border-color: red;
display: flex;
flex-direction: column;
}
.flex-item {
border-color: blue;
}
.box {
height: 15vh;
border-color: green;
padding: 0;
}
.flex-item:last-child > .box {
height: 8vh;
}
.grow {
flex-grow: 1;
}
.grow > .box {
height: 100%;
}
<div class="flex">
<div class="flex-item">
<div class="box"></div>
</div>
<div class="flex-item grow">
<div class="box two"></div>
</div>
<div class="flex-item">
<div class="box"></div>
</div>
</div>
I could edit the last of the code to what’s below to make it work, but I’d rather not have one child be displayed as flex while the others are displayed as block. Is there another way I could go about doing this?
.grow {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.grow > .box {
flex-grow: 1;
}
body {
height: calc(100vh - 2 * 4px);
margin: 4px;
}
div {
box-sizing: border-box;
border-width: 0.8vh;
border-style: solid;
padding: 2vh;
}
.flex {
height: 100%;
border-color: red;
display: flex;
flex-direction: column;
}
.flex-item {
border-color: blue;
}
.box {
height: 15vh;
border-color: green;
padding: 0;
}
.flex-item:last-child > .box {
height: 8vh;
}
.grow {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.grow > .box {
flex-grow: 1;
}
<div class="flex">
<div class="flex-item">
<div class="box"></div>
</div>
<div class="flex-item grow">
<div class="box"></div>
</div>
<div class="flex-item">
<div class="box"></div>
</div>
</div>
You could set it as follow:
.grow {
flex-grow: 1;
height: 100%;
}
.grow > .box {
height: 100%;
}
This does seem to the trick for me in Safari.
If you don't want to use flexbox on the .grow element.

Flexbox flex-grow property not respected when flex item contains an input element

I am using flexbox to make a chat UI. First using the flex-grow property I divide the layout in 2 columns with a ratio 2/5 and then I divide those 2 columns in rows with a ratio 1/9 for the first column and 5/1 for the second one.
This is what I have when I haven't added the input elements to the HTML code:
https://codepen.io/thenr/pen/PoooyEN
#chat {
display: flex;
width: 100%;
height: calc(100vh - 2em);
overflow-y: hidden;
}
#friends {
flex-grow: 2;
display: flex;
flex-direction: column;
border: 1px solid black;
}
#messages {
flex-grow: 5;
display: flex;
flex-direction: column;
border: 1px solid black;
}
#searchfriend {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 120px;
border: 1px solid black;
background-color: blue;
}
#searchfriend input[type="text"] {
margin: 0;
padding: 1em;
border: 0;
border-radius: 0px;
background-color: #d1d1d1;
}
#friendslist {
flex-grow: 9;
border: 1px solid black;
overflow-y: auto;
}
.friend {
height: 100px;
border: 1px solid black;
}
#chatmessages {
flex-grow: 5;
border: 1px solid black;
}
#writemessage {
flex-grow: 1;
border: 1px solid black;
}
<div id="chat">
<!-- friends -->
<div id="friends">
<div id="searchfriend">
</div>
<div id="friendslist">
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
</div>
</div>
<!-- chat -->
<div id="messages">
<div id="chatmessages">
</div>
<div id="writemessage">
</div>
</div>
</div>
The problem is that when I add the input elements to the HTML code the ratios I had set are not respected and the flex items containing those input elements make bigger, and I don't want that to happen. Same HTML code but with the input elements added:
https://codepen.io/thenr/pen/RwwweQN
#chat {
display: flex;
width: 100%;
height: calc(100vh - 2em);
overflow-y: hidden;
}
#friends {
flex-grow: 2;
display: flex;
flex-direction: column;
border: 1px solid black;
}
#messages {
flex-grow: 5;
display: flex;
flex-direction: column;
border: 1px solid black;
}
#searchfriend {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 120px;
border: 1px solid black;
background-color: blue;
}
#searchfriend input[type="text"] {
margin: 0;
padding: 1em;
border: 0;
border-radius: 0px;
background-color: #d1d1d1;
}
#friendslist {
flex-grow: 9;
border: 1px solid black;
overflow-y: auto;
}
.friend {
height: 100px;
border: 1px solid black;
}
#chatmessages {
flex-grow: 5;
border: 1px solid black;
}
#writemessage {
flex-grow: 1;
border: 1px solid black;
}
<div id="chat">
<!-- friends -->
<div id="friends">
<div id="searchfriend">
<input type="text" name="" id="searchtext" placeholder="Search friend...">
</div>
<div id="friendslist">
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
<div class="friend"></div>
</div>
</div>
<!-- chat -->
<div id="messages">
<div id="chatmessages">
</div>
<div id="writemessage">
<form action="" id="formchat">
<input type="text" name="msgtext" id="msgtext" autocomplete="off">
<button id="msgsend">Send</button>
</form>
</div>
</div>
</div>
You may use the flex shorthand flex:2 / flex: 5 instead flex-grow:2 / flex-grow:5 .
It will avoid to have to set flex-shrink and flex-basis too.

flexbox item 100% of remaining width

I want to achieve the following scenario with flexbox
the green element is a text element and the width is flexible. The blue elements should have 100% of the remaining width beside the green element.
My current solution looks like this:
<div class="container">
<span class="title">title</span>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
and the css:
.container {
display: flex;
align-items: center;
flex-wrap: wrap;
background-color: #EAEBEF;
.title {
padding: 20px;
background-color: #48CFAE;
}
.fullwidth {
background-color: #87BDFF;
flex: 0 0 100%;
height: 60px;
margin: 10px 0;
}
}
But it looks currently like this
here is a codepen example
Without changing the HTML this can be managed with CSS-Grid as an alternative to flexbox.
.container {
display: grid;
grid-template-columns: max-content 1fr;
grid-gap: 1em;
background-color: #EAEBEF;
margin-bottom: 1em;
}
.title {
padding: 10px;
grid-row: 2;
background-color: #48CFAE;
}
.fullwidth {
grid-column: 2;
background-color: #87BDFF;
height: 40px;
}
<div class="container">
<div class="title">title</div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
<div class="container">
<div class="title">Longer title</div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
Try this HTML and CSS markup. Basically You need to keep the left side in one div and the right side elements in another div.
.container {
display: flex;
align-items: center;
flex-wrap: nowrap;
background-color: #eaebef;
}
.container .title {
padding: 20px;
background-color: #48cfae;
}
.container .div1 {
width: 20%;
}
.container .div2 {
width: 80%;
}
.container .fullwidth {
background-color: #87bdff;
height: 60px;
margin: 10px 0;
}
<div class="container">
<div class="div1">
<span class="title">title</span>
</div>
<div class="div2">
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
</div>
See code below:
You have to warp fullwidth in div and set width to this div
also set width and margin to title
.container {
display: flex;
align-items: center;
flex-wrap: wrap;
background-color: #EAEBEF;
}
.title {
width: 20%;
padding: 20px;
background-color: #48CFAE;
margin-left: 15px;
}
.fullwidth {
background-color: #87BDFF;
flex: 0 0 100%;
height: 60px;
margin: 10px 0;
}
.a{
margin: 50px;
width: 50%;
}
<div class="container">
<span class="title">title</span>
<div class="a">
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
</div>
If you want to achive this without change your html but only your less, try this:
.container {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
background-color: #EAEBEF;
justify-content: flex-end;
.title {
padding: 20px;
background-color: #48CFAE;
margin-right: 20px;
flex-grow: 1
}
.fullwidth {
background-color: #87BDFF;
height: 60px;
margin: 10px 0;
width: 80%;
}
}
your codepen edited

CSS Flexbox - varying height of elements on wrap

I have a simple layout with varying size elements that I am trying to put together for a dashboard.
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
display: flex;
}
div.first {
border: 1px dotted lightpink;
}
div.second {
border: 1px dotted orange;
}
div.third {
border: 1px dotted green;
}
div.fourth {
border: 1px dotted fuchsia;
}
<div style="display: flex; height: 500px">
<div class="first" style="flex: 0 60%;flex-wrap: wrap;align-items;stretch;align-content:stretch">
<div class="first" style="flex: 1 100%; align-self: flex-start">
Title text
</div>
<div class="second" style="flex: 2 auto">
Content A
</div>
<div class="third" style="flex: 1 auto">
Content B
</div>
<div class="fourth" style="flex: 1 auto">
<div style="height: 66px; align-self:flex-end">
<div style="align-self: flex-end">
Content C
</div>
</div>
</div>
</div>
<div class="second" style="flex: 1 auto; align-items: flex-end">
Content D
</div>
</div>
Codepen link:
http://codepen.io/korgmatose/pen/qqKzry?editors=1100
I want to fill the second row (Content A,B,C) so that it starts just beneath Title Text.
But making align-items flex-start will not allow the second row to fill the remaining space, and setting a height to 100% on one of the items in that row only sets the height to the parent container, thus rendering the div's outside the bottom border.
Like #kukkuz said I would also recommend doing it this way. Just put the content A, B, C in a separate container, in this case #content and add display: flex, flex-direction: column and flex: 1 to it and please do not use inline styling for styling your HTML since it makes your code muss less readable. Most recommended way is to put your CSS code into a separate file and link it to your HTML.
The following code is an example of how you could do the markup of your desired layout without any inline styles.
HTML
<div id="wrapper">
<div class="left">
<div class="title">Title text</div>
<div id="content">
<div class="second">Content A</div>
<div class="third">Content B</div>
<div class="fourth">Content C</div>
</div>
</div>
<div class="right">Content D</div>
</div>
CSS
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
}
#wrapper {
display: flex;
height: 500px;
}
.left {
flex: 3;
display: flex;
flex-direction: column;
}
#content{
flex: 1;
display: flex;
padding: 0;
}
.second,
.third,
.fourth {
flex: 1;
}
.third {
border: 1px dotted green;
}
.fourth {
display: flex;
align-items: flex-end;
border: 1px dotted fuchsia;
}
.right {
flex: 2;
}
.left,
.title {
border: 1px dotted lightpink;
}
.right,
.second {
border: 1px dotted orange;
}
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
}
#wrapper {
display: flex;
height: 500px;
}
.left {
flex: 3;
display: flex;
flex-direction: column;
}
#content {
flex: 1;
display: flex;
padding: 0;
}
.second,
.third,
.fourth {
flex: 1;
}
.third {
border: 1px dotted green;
}
.fourth {
display: flex;
align-items: flex-end;
border: 1px dotted fuchsia;
}
.right {
flex: 2;
}
.left,
.title {
border: 1px dotted lightpink;
}
.right,
.second {
border: 1px dotted orange;
}
<div id="wrapper">
<div class="left">
<div class="title">Title text</div>
<div id="content">
<div class="second">Content A</div>
<div class="third">Content B</div>
<div class="fourth">Content C</div>
</div>
</div>
<div class="right">Content D</div>
</div>
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
display: flex;
}
div.first {
border: 1px dotted lightpink;
}
div.second {
border: 1px dotted orange;
}
div.third {
border: 1px dotted green;
}
div.fourth {
border: 1px dotted fuchsia;
}
<div style="display: flex;">
<div class="first" style="flex: 0 60%;flex-wrap: wrap;align-items;stretch;align-content:stretch">
<div class="first" style="flex: 1 100%; align-self: flex-start">
Title text
</div>
<div class="second" style="flex: 2 auto">
Content A
</div>
<div class="third" style="flex: 1 auto">
Content B
</div>
<div class="fourth" style="flex: 1 auto">
<div style="height: 66px; align-self:flex-end">
<div style="align-self: flex-end">
Content C
</div>
</div>
</div>
</div>
<div class="second" style="flex: 1 auto; align-items: flex-end">
Content D
</div>
</div>
Something like this?

Resources