Component to take all available height with Flexbox (in Quasar/Vue) - css

I'm building a component with header/main content/ footer where the main content will be scrollable. While I can do this in Js, I need the component to take all available space on height and footer to be at the bottom.
I can't get it to take the whole height, even if the code is correct.
Here is a pen with the not-working code: https://codepen.io/SharpBCD/pen/MNgxgY
.panel {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
flex-grow: 1;
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
background-color: #00acc1;
}
.panel-header{
flex: 0 1 auto;
/*max-height: fit-content;*/
}
.panel-main{
/*margin-bottom: auto;*/
display: flex;
flex-direction: column;
flex: 1; /* same as flex: 1 1 auto; */
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
background-color: #0d47a1;
}
.panel-footer{
margin-top: auto;
max-height: fit-content;
}
Here is a jsfiddle with the working code that I tried: https://jsfiddle.net/MadLittleMods/LmYay/
.flexbox-parent
{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
background: rgba(255, 255, 255, .1);
}
.flexbox-item-grow
{
flex: 1; /* same as flex: 1 1 auto; */
}
.fill-area
{
display: flex;
flex-direction: row;
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
}
So... what's the problem? What do i do wrong?

Give responsibility to the parent
Making the component responsible for taking the whole space has not been successful for me without extra tinkering. A simpler solution is to use the items-stretch class for a row, then put a col in to be streched.
This might be more intuitive for others.
Shown below with q-card as an example. This should work with whatever child component you choose, provided you use appropriate row / col classes.
<q-page id="addressesOverview" class="q-pa-md row items-stretch">
<q-card class="col-12">
<q-card-section> ... </q-card-section>
</q-card>
</q-page>
If you have a common component to display the q-page, you can change it to :class and add the items-stretch class dynamically.
Link: Quasar Docs - Flexbox - Alignment

If you want to use the flex model and lay your #q-app on the whole height of the window, you need to start building the flex layout from the root.
you can use the following styles :
/* update */
#q-app {
height:100vh;/* or min-height:100vh if you want it to grow */
display:flex;
}
.q-pa-md{
flex:1;
display:flex;
flex-direction:column;
}
/* end update */
Demos (snippet to run or forked codepens):
/* update */
body {
margin:0;
}
#q-app {
min-height:100vh;
display:flex;
}
.q-pa-md{
flex:1;
display:flex;
flex-direction:column;
}
/* end update */
.panel {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
flex-grow:1;
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
background-color: #00acc1;
}
.panel-header{
flex: 0 1 auto;
/*max-height: fit-content;*/
}
.panel-main{
/*margin-bottom: auto;*/
display: flex;
flex-direction: column;
flex: 1; /* same as flex: 1 1 auto; */
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
background-color: #0d47a1;
}
.panel-footer{
margin-top: auto;
max-height: fit-content;
}
<!--
Forked from:
https://quasar.dev/layout/grid/column#Example--Equal-Height-Example
-->
<div id="q-app">
<div class="q-pa-md">
<p> irelevant text to ocupy space before panel</p>
<div class=" panel">
<div class=" panel-header">
I'm a header
</div>
<div class = "panel-main">
Main content
</div>
<div class=" panel-footer">
I'm a footer
</div>
</div>
</div>
</div>
or play with the fork https://codepen.io/gc-nomade/pen/RXbmYj
another version with overflow to keep footer at bottom and let main content scroll https://codepen.io/gc-nomade/pen/rXBgRV

simply your <html> and <body> were not occupying the whole page and the same for the children nodes ...just add this to your css :
html,body,#q-app,.q-pa-md {
height:100%;
width: 100%;
}
codepen

Related

Not able to vertically align items in flexbox

I am learning to use flexbox and I am not able to align content vertically inside of the class .headercontent. it seems to honor everything else like justify-content but ignores align-content. I searched and found this thread and this seems to suggest that the parent should have height explicitly set. I have set height by setting flex-basis and flex-grow and a min-height. But still by div containing the h1 is stuck to the top of the header. I want that green div to be in the vertical center of the header. what am I doing wrong?
html {
box-sizing: border-box;
margin: 0;
padding: 0;
font-size: 100%;
line-height: 1.2em;
}
body {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
height: 100vh;
background-color: #cdc9c1;
}
header {
background-color: #a99879;
flex-basis: 10%;
flex-grow: 1;
min-height: 20px;
}
main {
background-color: #5b431a;
flex-basis: 80%;
flex-grow: 8;
}
footer {
background-color: #77613c;
flex-basis: 10%;
flex-grow: 1;
}
.headercontent {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background-color: green;
min-height: 20px;
}
.navstyle {
list-style-type: none;
}
<html>
<head>
</head>
<body>
<header>
<div class="headercontent">
<h1>This is the header</h1>
</div>
</header>
<nav>
<ul>
<li>section1</li>
<li>section2</li>
<li>section3</li>
</ul>
</nav>
<main>
<p> this is the main body</p>
</main>
<footer>
<p> this is the footer </p>
</footer>
</body>
</html>
Here is the codeine link to my work https://codepen.io/knows_not_much/pen/rNxXoOM
I want that green div to be in the vertical center of the header. what
am I doing wrong?
Your header element is taking up 10% height of body. Your .headercontent does not take up the entire defined height of the header. Therefore, it is going to sit at the top. To address this, you can assign the header element to be a flex container and that is where you assign align-items: center; justify-content: center properties
header {
background-color: #a99879;
flex-basis: 10%;
flex-grow: 1;
display: flex; /* add these */
align-items: center; /* add these */
justify-content: center; /* add these */
}
Assign width: 100% to the .headercontent afterwards (as needed) if you must have the green background take up the space

Unwanted space between wrapping flex-items

When I set flex-container height larger than what flex-items would occupy, items that wrap, have space between them. Mind you - justify-content and align-items are both set to flex-start. Here is snippet (click on full page after run)
.flex-container {
min-height: 100vh;
position: relative;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
}
header,
main,
aside,
footer {
padding: 1rem;
background-color: tomato;
}
header,
footer {
width: 100%;
}
main {
width: 75%;
}
aside {
flex-grow: 1;
}
<div class="flex-container">
<header>Header Content</header>
<main>Main content here.</main>
<aside>Sidebar content</aside>
<footer>Footer Content</footer>
</div>
Here's the pen
This can be reproduced with flex-direction: column; if you reversed all the properties. Is this expected behavior? If so, why? Is there a way I came around this and get something like that:
with the flex-container height set to 100vh ?
The correct answer without adding extra markup, is align-content: flex-start; - default is stretch, that's why wrapping elements have extra space between them, when the flex-container's size exceeds the size of the elements in it.
If I good understand your question - you can add following div .wrappper inside flex-container
.wrapper {
position: relative;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
flex-basis: 100%;
}
body {margin: 0}
.wrapper {
position: relative;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
flex-basis: 100%;
}
.flex-container {
min-height: 100vh;
position: relative;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
}
header,
main,
aside,
footer {
padding: 1rem;
background-color: tomato;
}
header,
footer {
width: 100%;
background-color: blue;
}
main {
flex-basis: 75%;
flex-grow: 1;
background-color: yellow;
}
aside {
flex-grow: 1;
}
<div class="flex-container">
<div class="wrapper">
<header>Header Content</header>
<main>Main content here.</main>
<aside>Sidebar content</aside>
<footer>Footer Content</footer>
</div>
</div>
Explanation what previous solution doesn't wokrs: because the height of your flex items was set to 1rem+font size, and the align-items: flex-start; was set so flex not change items height but put them on proper place (flex-start). But if you would use align-items: streth; then flex will stretch elements. Because you want to have 100vh for .flex-container, we need to use wrapper which was not stretched to full height of container because container has still align-items: flex-start;. And that wrapper height is sum of his chidren height without extra space.

Flex auto margin not working in IE10/11

I have a complex layout where I center various elements vertically and horizontally with flexbox.
The last element then has margin-right:auto; applied to push the elements left (and negate centering them).
This works correctly everywhere except on IE10/11 and has been driving me crazy.
HTML/CSS sample:
#container {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-flow: row wrap;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-ms-flex-line-pack: center;
-webkit-align-content: center;
align-content: center;
}
#second-item {
margin-right: auto;
}
/* just some colors - not important */
#container {
height: 200px;
width: 100%;
background: red;
}
#container > div {
background: blue;
padding: 10px;
outline: 1px solid yellow;
}
<div id='container'>
<div id='first-item'>first item</div>
<div id='second-item'>second item</div>
</div>
http://codepen.io/anon/pen/NrWVbR
You'll see two items on the screen that should be left-aligned on the side of the red parent (i.e. they should both be centered, but the last item has margin-right:auto; applied and is filling the entire line, pushing the other item and itself on the side) - this is the correct behaviour. Except in IE10/11 where both items are incorrectly centered i.e. the second item's margin-right:auto; is ignored.
Any IE/flexbox experts out there that have encountered something like this before?
This appears to be an IE bug.
According to the flexbox specification:
8.1. Aligning with auto margins
Prior to alignment via justify-content and align-self, any positive free space is distributed to auto margins in that dimension.
Note: If free space is distributed to auto margins, the alignment properties will have no effect in that dimension because the margins will have stolen all the free space left over after flexing.
In other words, auto margins take precedence over justify-content.
In fact, if an element has auto margins applied, then keyword alignment properties such as justify-content and align-self have no effect (because the auto margins have taken all the space).
Your code works as expected in Chrome and Firefox because those browsers are in compliance with the spec.
IE10 and IE11 appear to not be in compliance. They are not applying the auto margin as defined in the spec.
(Note that IE10 is built on a previous version of the spec.)
Solutions
Method #1: Use auto margins only
If justify-content is removed, auto margins work fine in IE10/11.
So don't use justify-content. Use auto margins all the way through. (See examples of alignment with auto margins).
Method #2: Use an invisible spacer div
Create a third div with visibility: hidden and flex-grow:1. This will naturally shift #first-item and #second-item to the left edge, with no need for auto margins.
#container {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: center;
align-content: center;
}
#third-item {
flex-grow: 1;
visibility: hidden;
}
/* just some colors - not important */
#container {
height: 200px;
width: 100%;
background: pink;
}
#container > div {
background: cornflowerblue;
padding: 10px;
outline: 1px solid yellow;
}
<div id='container'>
<div id='first-item'>first item</div>
<div id='second-item'>second item</div>
<div id='third-item'>third item</div>
</div>

Using flexbox to align one element to the top left and one to the center on a page

When I try to put one element in the top left and one in the center, the top element doesn't go all the way to the left. How do I accomplish this?
.Aligner {
background-color: blue;
display: flex;
align-items: center;
justify-content: center;
height: 200px;
}
.Aligner-item {
max-width: 50%;
background-color: green;
}
.Aligner-item--top {
align-self: flex-start;
}
<div class="Aligner">
<div class="Aligner-item Aligner-item--top">…</div>
<div class="Aligner-item">…</div>
<div class="Aligner-item Aligner-item--bottom">…</div>
</div>
http://codepen.io/anon/pen/EVjzzo
From MDN:
flex-start
The cross-start margin edge of the flex item is flushed with the cross-start edge of the line.
This means align-self: flex-start; will align the top edge of your top box with the top edge of the flex box (the beginning of the cross axis).
The left/right values are along the main axis. You can read more about it in the W3C spec: https://drafts.csswg.org/css-align/#align-self-property
One way to accomplish your desired layout is to use position properties.
Note that the addition of position will change the flex behavior; it's sort of an "override" property. align-self on absolutely-positioned boxes applies along the containing block's block axis (in this case, the y-axis).
You can see more info about absolutely-positioned flex items here: http://www.w3.org/TR/css3-flexbox/#abspos-items
.Aligner {
background-color: blue;
display: flex;
align-items: center;
justify-content: center;
height: 200px;
position: relative; /* new */
}
.Aligner-item {
max-width: 50%;
background-color: green;
}
.Aligner-item--top {
align-self: flex-start;
left: 0; /* new */
top: 0; /* new */
position: absolute; /* new */
}
<div class="Aligner">
<div class="Aligner-item Aligner-item--top">…</div>
<div class="Aligner-item">…</div>
<div class="Aligner-item Aligner-item--bottom">…</div>
</div>

percentage height in nested flex box

I've got a pretty good adjustable interface working with flexbox where a user can adjust the height and width of panels.
However, I want to change the panel heights, which currently use pixels, to use percentage, so when they change one panel, the other panels flow.
Everything works fine for widths, but when I use height % it breaks.
Here's a fiddle showing the broken %.
http://jsfiddle.net/59trW/1/
This fiddle has a 50% height set on the red element, but it isn't visible at all.
here's the css
.outer-flex {
position: absolute;
top: 0;
bottom: 0;
left:0;
right:0;
display: flex;
-webkit-box-align: stretch;
flex-direction: row;
}
.left-panel {
width: 30px;
background-color: #5eddd8;
}
.flex {
display: flex;
flex:1;
-webkit-box-align: stretch;
flex-direction: column;
background-color: #64b92a;
min-height: 1px;
}
.fixed {
height: 20px;
background-color: #ecf0f1;
}
.top-box {
height: 30%;
background-color: red;
}
.bottom-box {
flex: 1;
}
And the html
<div class="outer-flex">
<div class="left-panel">
this is ok.
</div>
<div class="flex">
<div class="fixed">doesn't move</div>
<div class="top-box">top box</div>
<div class="bottom-box">bottom box</div>
</div>
</div>
I'm hoping there is a small change I can make to have the div be adjustable by %.
You need to add a height to your right column:
http://jsfiddle.net/59trW/2/
.flex {
display: flex;
flex:1;
flex-direction: column;
background-color: #64b92a;
height: 100%; /* here */
}
Also, -webkit-box-align: stretch is doing nothing for you because it comes from the old 2009 draft (which you aren't even using here), not the current spec (also, stretch is the default value for that property).

Resources