Unwanted space between wrapping flex-items - css

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.

Related

Equal width flex columns when the container has fluid width

Consider the following HTML code:
<div class="ungrouped-ordered-item">
<div class="information-container">
<div class="originating-order-id"> #00019405 </div>
<div class="placed-by"> Placed by: 18175 </div>
</div>
<div class="indicator-container">
<div class="indicator"> Unpaid </div>
<div class="indicator" >Pending </div>
</div>
</div>
with the following css:
.ungrouped-ordered-item {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.information-container {
display: flex;
flex-direction: column;
}
.indicator-container {
display: flex;
flex-direction: row;
align-items: center;
}
.indicator-container .indicator {
display: flex;
justify-content: space-between;
align-items: center;
flex: 1;
padding: 0 10px;
border: 1px solid #2e2240;
}
The design I am aiming for, is:
to let the outermost flex containers (.ungrouped-ordered-item) children, grow as they need, and leave space between them, so that they are aligned to the left and right respectively of their containers
to make the children of the inner flex container (.indicator-container .indicator) be equal-width, by taking up the width of the wider element (in this case, it being the element with the text "Pending")
My first goal is achieved, but it seems, that even if adding flex: 1 to the .indicator containers, the browser will not correctly calculate the width of the two elements, and they will have uneven widths. I am presuming that this is because that their container, .indicator-container, has a fluid width. Am I right in this? How can I achieve my desired effect with all fluid width containers? (preferably without javascript).
Here's a fiddle also!
What is the argument against a width:50% for the .indicatorbox?
.ungrouped-ordered-item {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.information-container {
display: flex;
flex-direction: column;
}
.indicator-container {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
}
.indicator-container > * {
border: 1px solid #2e2240;
padding: 0 10px;
flex-wrap: wrap;
}
.indicator-container .indicator {
width: 50%;
text-align: center;
}
<div class="ungrouped-ordered-item">
<div class="information-container">
<div class="originating-order-id"> #00019405 </div>
<div class="placed-by"> Placed by: 18175 </div>
</div>
<div class="indicator-container">
<div class="indicator"> Unpaid </div>
<div class="indicator" >Pending long long</div>
</div>
</div>
Changing the .indicator-container class from flex to grid and using automatic columns solves my problem. Although, it doesn't have as much coverage as flex, for my needs, this works:
.indicator-container {
display: grid;
grid-auto-columns: minmax(0, 1fr);
grid-auto-flow: column;
}
Here's the updated fiddle also.

Flex items not filling the height of its parent

I have a container with children items:
HTML
<div id="container">
<div className="item">1</div>
<div className="item">2</div>
<div className="item">3</div>
<div className="item">4</div>
</div>
CSS
#container {
display: flex;
flex-direction: row;
gap: 10px;
}
.item {
flex: 1;
text-align: center;
padding: 0px;
font-size: 30px;
background: #34ace0;
}
This flexbox container sits inside a grid layout, and the cell to the left of the one here has contents which cause the height of the flexbox shown here to be higher than the contents, as shown here:
I need the squares with the numbers inside to stretch/fill the height of its container, like this
...but with the text centered vertically as well.
I tried setting the height of the .item to 100% but it doesn't fill. Is there something like the free-remaining-space used in grid for flexbox?
Make sure the grid layout container has height of 100vh and the container you've shown also has height of 100%.
To center the text inside of each item, you can make each of them display: flex.
.grid-container {
height: 100vh;
}
#container {
height: 100%;
display: flex;
flex-direction: row;
gap: 10px;
}
.item {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
padding: 0px;
font-size: 30px;
background: #34ace0;
}

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

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

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

Flexbox Performance in Safari for Sticky Sidebar

I'm looking to display a sticky sidebar on my page, positioned relatively when the client is at the top of the document and fixed when the client scrolls.
My problem is with Safari (it seems to work fine with Chrome and Firefox).
I had it working with a set of floating divs (sidebar floats left) but when I changed to flexbox I found that fast scrolling was too fast for the sticky sidebar to keep up (whether detaching itself from its relative position or staying in a fixed position on the page.
Has anyone else encountered a similar issue and found a work around? I'll go back to floats if necessary but as I'm still learning this stuff it would be great to get to the bottom of why flexbox is causing problems.
Thanks! (Code/markup follows)
HTML:
<div class="order-form">
<div class="left-column" id="left-column">
<div class="sidebar" id="sidebar">
<ul id="courses"></ul>
</div>
</div>
<div class="menu" id="menu"><!-- content --></div>
<div class="right-column"> <!-- content --></div>
</div>
JQuery:
$(window).scroll(function() {
stickers();
});
function stickers() {
var sidebar = $(".sidebar");
if ($(window).scrollTop() > 300) {
sidebar.addClass("scrolling-sidebar");
} else {
sidebar.removeClass("scrolling-sidebar");
}
}
Old, unproblematic, CSS:
.order-form {
padding: 0 300px 0 120px;
}
.sidebar {
width: 150px;
font-weight: lighter;
text-transform: uppercase;
display: block;
}
.sidebar.scrolling-sidebar {
position: fixed;
top: 75px;
left: 5%
}
My current CSS file (compiled from Sass, with problems seemingly arising from my use of flexbox):
.order-form {
margin: 50px 0;
padding: 0 5%;
display: -webkit-box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: stretch;
align-items: stretch;
-webkit-flex-direction: row;
-moz-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: nowrap;
-moz-flex-wrap: nowrap;
flex-wrap: nowrap;
-webkit-justify-content: flex-start;
-moz-justify-content: flex-start;
justify-content: flex-start;
position: relative;
}
.order-form .left-column {
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-basis: 0;
-moz-flex-basis: 0;
flex-basis: 0;
-webkit-order: 1;
-moz-order: 1;
order: 1; }
#media (min-width: 992px) {
.order-form .left-column {
margin-right: 5%;
display: -webkit-box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-basis: 100px;
-moz-flex-basis: 100px;
flex-basis: 100px;
}
}

Resources