Display: flex element wont grow vertically within parent - html

I have a webpage where I want to center one of the pages both vertically and horizontally, like that:
<main>
<div>
This has to be centered both vertically and horizontally.
</div>
</main>
I can't change display of main as it's widely used for all the pages, and using flex there breaks way too much stuff.
I assumed this should work but it does not, because div does not grow in height:
main {
min-height: 1000px;
border: solid 1px red;
}
div {
display: flex;
align-items: center;
justify-content: center;
align-content: stretch;
flex-grow: 1;
}
I'd rather not do position: absolute; top: 0; right: 0; bottom: 0; left: 0;.
Any hints how can I stretch my div to fill main? Why wouldn't it work out of the box, can't flex simply grow within elements with block/inline-block displays?
https://jsfiddle.net/wcu6fnz5/

It might helps you.
/* I cannot edit main, there are 100s of pages based on it, cant change its display etc. */
main {
min-height: 200px;
border: solid 1px red;
}
div {
display: flex;
min-height: inherit;
justify-content: center;
align-items: center;
}
<main>
<div>
<span>This has to be centered both vertically and horizontally.</span>
</div>
</main>

The thing about flexbox is that you should focus on instructing the parent, not the child.
In your example, justify-content and display: flex should be in the parent. You could also use flex-direction: column to tell the browser you want the child to grow vertically.
You could also use flex: 1 as a shorthand for flex-grow. This way, the child doesn't even need display: flex.
main {
min-height: 1000px;
border: solid 1px red;
display: flex;
flex-direction: column;
justify-content: stretch;
}
div {
flex: 1;
}
Update
To achieve what you mentioned in the comments, why don't you try this:
main {
min-height: 1000px;
border: solid 1px red;
}
section {
height: 1000px;
width: 100px;
background: gainsboro;
/* important stuff */
display: flex;
flex-direction: column;
justify-content: stretch;
}
div {
flex: 1;
width: 40px;
background: aquamarine;
}
Those sizes and colors are only for you to see the results.

Related

In container with flex-grow: 1 the content is overflowing when it should be scrollable

I have a container that is flex-grow sized to fill up the remaining space within a fixed size container.
Within the flex-grow container, I have another div that is a lot bigger than the flex sized container. How do I make it so that the content-wrapper element is scrollable instead of the child element overflowing.
Thank you!
.main-content-container {
padding: 0 20px;
display: flex;
flex-flow: column nowrap;
grid-gap: 10px;
height: 550px;
background: green;
}
.sub-content-container {
width: 300px;
background: grey;
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
}
.content-wrapper {
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
overflow: auto;
}
.content-container {
height: 10000px;
background: #555;
}
body {
background: black;
color: white;
padding-bottom: 30px;
}
<div class='main-content-container'>
<p>stuff</p>
<div class='sub-content-container'>
<p>header</p>
<div class='content-wrapper'>
<div class="content-container">I WANT THIS TO STAY WITHIN THE CONTENT-WRAPPER</div>
</div>
</div>
</div>
Generally speaking, for the overflow property to work, the container needs to be overflowed. That requires a fixed length on the container. Without a fixed length (height or width), there's nothing to trigger an overflow. The flex-grow property doesn't establish a fixed length, so it doesn't work.
Of course, setting a fixed height on your container is not an option if you want a dynamic layout.
So, to solve both problems, set the container to height: 1px.
this establishes the fixed length;
it doesn't interfere with the dynamic lengths; and,
the flex-grow property expands the container to full height
But there's one more problem. The nested flex container in column direction seems to be ignoring the overflow property. This is possibly because of the nesting in a flex formatting context. Hence, if possible, switch that container back to a block formatting context.
Make these adjustments to your code:
.content-wrapper {
height: 1px; /* new */
flex-grow: 1;
/* display: flex; */
flex-flow: column nowrap;
overflow: auto;
}
.main-content-container {
padding: 0 20px;
display: flex;
flex-flow: column nowrap;
grid-gap: 10px;
height: 550px;
background: green;
}
.sub-content-container {
width: 300px;
background: grey;
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
}
.content-wrapper {
height: 1px; /* new */
flex-grow: 1;
/* display: flex; */
flex-flow: column nowrap;
overflow: auto;
}
.content-container {
height: 10000px;
background: #555;
}
body {
background: black;
color: white;
padding-bottom: 30px;
}
<div class='main-content-container'>
<p>stuff</p>
<div class='sub-content-container'>
<p>header</p>
<div class='content-wrapper'>
<div class="content-container">I WANT THIS TO STAY WITHIN THE CONTENT-WRAPPER</div>
</div>
</div>
</div>
jsFiddle demo

Flex div has height of 228px even though there is no content inside of it and I haven't specified size anywhere

For some reason, a div whose parent has a display: flex property is having a height of 228px even though there's no content inside of it.
Image example
.sights-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
flex: 1;
background-color: #ffffff;
}
.sights-list div {
flex-basis: 48%;
flex-shrink: 0;
display: flex;
padding: 10px;
}
<div class='sights-list'>
<div>
</div>
<div>
</div>
</div>
you can use
{
min-height: 100%;
}

2x2 Grid equal height despite box content amount

I am trying to create a 2x2 grid where the height of the four individual boxes (red, blue, green, yellow) are all equal despite how much content they contain.
#rowTwo {
background-color: pink;
min-height: 25%;
display: flex;
flex-direction: column;
align-items: center;
}
#grid2x2 {
display: flex;
flex-direction: row;
flex-wrap: wrap;
background-color: orange;
width: 80%;
justify-content: center;
}
.box {
display: flex;
flex-basis: calc(50% - 20px);
margin: 5px;
justify-content: center;
padding-top: 5%;
overflow: hidden;
}
<div id={styles.rowTwo}>
<Heading title="My Title"/>
<div id={styles.grid2x2}>
<div id={styles.boxOne} className={styles.box}>
<DescriptionBoxItemWithHeading item={this.state.sectionTwoItems[0]}/>
</div>
<div id={styles.boxTwo} className={styles.box}>
<DescriptionBoxItemWithHeading item={this.state.sectionTwoItems[1]}/>
</div>
<div id={styles.boxThree} className={styles.box}>
<DescriptionBoxItemWithHeading item={this.state.sectionTwoItems[2]}/>
</div>
<div id={styles.boxFour} className={styles.box}>
<DescriptionBoxItemWithHeading item={this.state.sectionTwoItems[3]}/>
</div>
</div>
</div>
The issue I face is that a box expands to the height of the largest content in a row.
Here is an image outlining my problem:
Would anyone know how I could achieve this?
You can do this in CSS by using padding-top to add the height and then absolute positioning to draw your content on top of this padding.
Here is an example: https://codepen.io/anon/pen/xpwooz
#grid2x2 {
display: flex;
flex-wrap: wrap;
background-color: orange;
}
.box {
display: flex;
flex-basis: calc(50% - 20px);
margin: 5px;
justify-content: center;
overflow: hidden;
background: red;
padding-top: 100px;
position: relative;
}
.content {
position: absolute;
background: green;
top: 0;
width: 100%;
}
The problem is you can't change this height dynamically based on the content height. You can either set it to a fixed size or set it to a percentage and have it change size based on it's parents width. I think you'll need to use javascript if you want the height to change based on the largest content element.

Adjusting the height of images in flex layout

I've developed the following layout using the Flexbox CSS model:
html {
box-sizing: border-box;
overflow-y: none;
}
*,
*:before,
*:after {
margin: 0;
padding: 0;
box-sizing: inherit;
}
#all {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background: #03a9f4;
}
#app {
width: 500px;
background: #ffffff;
border: solid 6px yellow;
}
header {
display: flex;
justify-content: center;
align-items: center;
border: solid 4px blue;
}
#header-para-container {
flex: 1;
}
#header-image-container {
flex: 0.6;
background: #888;
}
#header-image-container > img {
display: block;
width: 100%;
height: auto;
}
section {
display: flex;
flex-wrap: wrap;
border: solid 4px tomato;
}
figure {
display: flex;
justify-content: center;
align-items: center;
flex-basis: 50%;
border: solid 4px green;
}
figure > img {
max-width: 80%;
height: auto;
}
<div id="all">
<div id="app-container">
<div id="app">
<header>
<div id="header-para-container">
<p>Hello, this is CSS flexbox layout. Thank you for visiting this page.</p>
</div>
<div id="header-image-container">
<img src="http://placekitten.com/g/300/300" />
</div>
</header>
<section id="grid-images">
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
</section>
</div>
</div>
</div>
https://jsfiddle.net/petebere/fsLpw1vb/.
Would you know how to reduce responsively the height of the images and the main display element (in yellow frame) as the viewport height decreases?
The idea is that the element in yellow frame should be always fully visible and there should be no need for vertical scrolling.
At the moment when the viewport height drops, the height of the yellow container stays constant. This is probably because the browser wants to keep the sizes that I've applied to the container of the header image:
#header-image-container {
...
flex: 0.6;
...
}
and to the containers of the grid images:
figure {
...
flex-basis: 50%;
...
}
I've produced this graphic to show what I'm trying to achieve when the window height is reduced:
The images aren't scaling because they aren't bound by a fixed height on their immediate containers.
For example, the first image in the layout (in the header section), has neither a parent (.header-image-container) nor a grandparent (header) with a defined height. Here's the actual code:
header {
display: flex;
justify-content: center;
align-items: center;
border: solid 4px blue;
}
#header-image-container {
flex: 0.6;
background: #888;
}
With the code above, the image has no need to be responsive. There is no height confinement.
Try this instead:
header {
display: flex;
justify-content: center;
align-items: center;
border: solid 4px blue;
height: 20vh; /* NEW */
}
#header-image-container {
flex: 0.6;
background: #888;
height: 100%; /* NEW */
}
#header-image-container > img {
/* display: block; */
/* width: 100%; */
/* height: auto; */
height: 100%; /* NEW */
}
revised demo
The same concept above applies to the #grid-images section:
section {
display: flex;
flex-wrap: wrap;
border: solid 4px tomato;
height: 60vh; /* NEW */
}
figure {
display: flex;
justify-content: center;
align-items: center;
flex-basis: 50%;
border: solid 4px green;
height: 50%; /* NEW */
}
figure > img {
/* max-width: 80%; */
/* height: auto; */
height: 100%; /* NEW */
}
revised demo
Additional notes:
In your original code you're trying to make your images responsive with width: 100%; height: auto (in the header section) and max-width: 80%; height: auto (in the grid section). This set-up (using percentage widths) is more suited for horizontal screen re-sizing. Your question seeks vertical re-sizing, so use percentage heights instead.
In your original layout, you may have noticed that when you reduce the screen height, the layout disappears at the top of the screen, with no access via vertical scroll. This is a known issue with flexbox. The solution is to use margin: auto on the centered flex item, instead of justify-content: center; align-items: center on the flex container. Full details here: Can't scroll to top of flex item that is overflowing container

Align divs vertically using flexbox

I'm trying to align three div blocks vertically using flexbox.
I can get them horizontally aligned correctly, however not vertically.
What am I doing wrong?
.banner {
padding-top: 10px;
padding-bottom: 10px;
background-color: #01b9d5;
color: white;
height: 55px;
}
.banner-align {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid green;
}
.banner-hero {
flex: 1;
align-self: center;
max-width: 50%;
border: 1px solid red;
text-align: center;
display: inline-block;
}
.banner-left {
align-self: flex-start;
flex: 1;
border: 1px solid green;
display: inline-block;
}
.banner-right {
align-self: flex-end;
flex: 1;
text-align: right;
border: 1px solid yellow;
display: inline-block;
}
<div class="banner">
<div class="container banner-align">
<div class="banner-left">
Left Block
</div>
<div class="banner-hero">
<b>Title</b>
</div>
<div class="banner-right">
Right block
</div>
</div>
</div>
Here is a fiddle: https://jsfiddle.net/zqc1qfk1/1/
You are missing the flex-direction:column attribute of flex.
By default any flex container has a flex-direction: row & that is the reason its moving horizontally & not vertically. You need to specify this explicitly.
Here is more about it
.banner-align {
display: flex;
align-items: center;
justify-content: center;
border:1px solid green;
flex-direction: column;
}
Updated the Fiddle.
Simply enable wrap on the container and give each flex item a width: 100%:
.banner-align {
display: flex;
flex-wrap: wrap;
}
.banner-align > * {
flex: 0 0 100%;
}
Now each flex item consumes all the space in the row, forcing other elements to create new rows.
revised fiddle
align-items: center on your flex parent centers everything vertically. However, using align-self: [anything but center] on the children overrides this.
Edit:
oops, as someone else pointed out, you're not getting the align-self effect in the original fiddle because the parent's height wasn't set and so it was only as tall as it needed to be to contain the children. If the children hadn't all been the same height, you would've seen them staggered.
If you're trying to have them all centered, you can get rid of the align-self properties and let the one align-items: center on the parent do that work. If you wanted them staggered, you don't need the one align-items: center on the parent.