I am trying to build a basic user interface using flexbox, I have this so far..
body,html {
margin:0;
padding:0;
height:100%;
}
.container {
height:100%;
display:flex;
flex-direction:column;
}
.top {
flex:4;
display:flex;
background:wheat;
align-items: center;
justify-content: center;
}
.bottom {
flex:1;
background:teal;
}
.bottom_content {
display:flex;
flex-direction:column;
}
.section1 {
flex:1;
font-size:20px;
text-align:center;
}
.section2 {
flex:1;
}
.btn {
background:red;
color:white;
padding:20px;
}
<div class="container">
<div class="top">
<span>TOP CONTENT</span>
</div>
<div class="bottom">
<div class="bottom_content">
<div class="section1">
<span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam lacus quam, blandit non lacus in, venenatis tempor dolor. Aliquam in lectus lacus. </span>
</div>
<div class="section2">
<div class="btn">
THIS IS A BUTTON
</div>
</div>
</div>
</div>
</div>
I am trying to achieve this...
How can I make the bottom section with equal height and make the content within it vertically and horizontally centered?
I am also planning on using fittext.js or similar to make the button and the text above fit into the flex item.
Where am I going wrong?
The problem
The issue with your current code is that .bottom is not filling the available space and that the default alignment and justification is being used.
The fix
The desired output can be achieved by doing the following:
Remove flex:1; from .section1 and .section2. This stops these divs from expanding to fill the available space
Add align-items: center; and justify-content: space-evenly; to.bottom_content. This will center align and evenly space out the .section1 and .section2 divs
Add display: flex; to .bottom. This will make .bottom expand to fit the available space
Change flex: 1; to flex: 1 0 auto; on .bottom. This will stop .bottom from reducing in size when the height of the window is small
body,
html {
margin: 0;
padding: 0;
height: 100%;
}
.container {
height: 100%;
display: flex;
flex-direction: column;
}
.top {
flex: 4;
display: flex;
background: wheat;
align-items: center;
justify-content: center;
}
.bottom {
/*Change*/
flex: 1 0 auto;
background: teal;
/*Add*/
display: flex;
}
.bottom_content {
display: flex;
flex-direction: column;
/*Add*/
align-items: center;
justify-content: space-evenly;
}
.section1 {
/*Remove*/
/*flex:1;*/
font-size: 20px;
text-align: center;
}
.section2 {
/*Remove*/
/*flex:1;*/
}
.btn {
background: red;
color: white;
padding: 20px;
}
<div class="container">
<div class="top">
<span>TOP CONTENT</span>
</div>
<div class="bottom">
<div class="bottom_content">
<div class="section1">
<span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam lacus quam, blandit non lacus in, venenatis tempor dolor. Aliquam in lectus lacus. </span>
</div>
<div class="section2">
<div class="btn">
THIS IS A BUTTON
</div>
</div>
</div>
</div>
</div>
I have commented some of your code. Please Check
body,
html {
margin: 0;
padding: 0;
height: 100%;
}
.container {
height: 100%;
display: flex;
flex-direction: column;
}
.top {
flex: 4;
display: flex;
background: wheat;
align-items: center;
justify-content: center;
}
.bottom {
flex: 1;
background: teal;
}
.bottom_content {
display: flex;
flex-direction: column;
}
.section1 {
<!-- flex: 1;
-->font-size: 20px;
text-align: center;
}
.section2 {
flex: 1;
}
.btn {
background: red;
color: white;
padding: 20px;
margin-top: 25px;
}
<div class="container">
<div class="top">
<span>TOP CONTENT</span>
</div>
<div class="bottom">
<div class="bottom_content">
<div class="section1">
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam lacus quam, blandit non lacus in, venenatis tempor dolor. Aliquam in lectus lacus. </div>
<button class="btn">
THIS IS A BUTTON
</button>
</div>
<!-- <div class="section2"> -->
<!-- <div class="btn"> -->
<!-- THIS IS A BUTTON -->
<!-- </div> -->
<!-- </div> -->
</div>
</div>
</div>
justify-content:center and display:flex is the key.
you can adjust margin as you wish,besides it should do the trick.
.bottom_content {
display: flex;
flex-direction: column;
margin-top: 20px;
}
.section2 {
flex: 1;
display: flex;
justify-content: center;
}
.btn {
background: red;
color: white;
padding: 20px;
width: fit-content;
position: absolute;
margin-top: 10px;
}
Related
As the title says, here's my example
I've already tried doing this using flex with position absolute but the problem is the responsiveness. How do I make this better? Is there a way that I could do this with just flexbox and not use position absolute while making the first row of the first and last column have equal height?
Here's my initial code:
<div class="block uk-width-1-1">
<div class="content-wrapper">
<div class="content uk-position-relative">
<div>
<div class="uk-grid uk-child-width-1-4 uk-flex-between">
<div class="card--wrapper">
<div class="card">
<h3>Lorem Ipsum</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis tortor ut ante rhoncus placerat. Nam at placerat tellus, a accumsan nisi.</p>
</div>
</div>
<div class="card--wrapper">
<div class="card">
<h3>Lorem Ipsum</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis tortor ut ante rhoncus placerat. Nam at placerat tellus, a accumsan nisi.</p>
</div>
</div>
</div>
<div class="uk-grid uk-child-width-1-4 uk-flex-between">
<div class="card--wrapper">
<div class="card">
<h3>Lorem Ipsum</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis tortor ut ante rhoncus placerat. Nam at placerat tellus, a accumsan nisi.</p>
</div>
</div>
<div class="card--wrapper">
<div class="card">
<h3>Lorem Ipsum</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis tortor ut ante rhoncus placerat. Nam at placerat tellus, a accumsan nisi.</p>
</div>
</div>
</div>
</div>
<div class="image--wrapper uk-position-absolute uk-width-1-3">
<div class="image">
<!-- Image here (middle column)-->
<img src="/../images/hero-sample.png" alt="image">
</div>
</div>
</div>
</div>
</div>
CSS
.image--wrapper {
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 0;
}
.block {
background: green;
}
h3, p.description {
color: white;
font-family: 'Poppins';
}
p.description {
font-weight: 400;
font-size: 14px;
line-height: 21px;
color: rgba(255,255,255,0.7);
margin-bottom: 0;
}
h3 {
font-weight: 600;
font-size: 16px;
line-height: 28px;
}
.card {
max-width: 240px;
padding: 20px;
box-sizing: border-box;
border: 1px solid rgba(255,255,255, 0.3);
}
.child-width-1-4 > div {
width: 25%;
}
.width-1-3 {
width: 33%;
}
.grid {
display: flex;
flex-wrap: wrap;
margin: 18.12px 0 0 0;
padding: 0;
}
.flex-between {
justify-content: space-between;
}
.position-absolute {
position: absolute !important;
}
.position-relative {
position: relative !important;
}
#media screen and (max-width: 1200px) {
.content-wrapper {
padding: 60px 25px
}
}
In this solution, the outer container is a grid with 12 columns. The middle column (.col2) takes up twice the space of col1 and col3. The -1 in grid-column: 10 / -1 means to span to the end of the grid, wherever it is.
Inside, I make the first and last columns into flexboxes, so that their children can take up an even amount of space in their respective containers. All spacing between columns and rows is accomplished using gap.
.container {
display: grid;
grid-template-columns: repeat(12, 1fr);
min-height: 100vh;
min-height: 100dvh;
gap: 1rem;
padding: 1rem;
}
/* 3 columns */
.col1 {
grid-column: 1 / 4;
}
/* 6 columns */
.col2 {
grid-column: 4 / 10;
}
/* 3 columns */
.col3 {
grid-column: 10 / -1;
}
.col1,
.col3 {
display: flex;
flex-direction: column;
gap: 1rem;
}
.col1 > *,
.col3 > * {
flex: 1;
}
body { margin: 0; }
* { box-sizing: border-box; }
.col2, .container > * > * { border: 1px solid; }
<div class="container">
<div class="col1">
<div></div>
<div></div>
</div>
<div class="col2"></div>
<div class="col3">
<div></div>
<div></div>
</div>
</div>
jsFiddle
there is more than one way to do that. I personally prefer using flex for such situations because it's more flexible for adjustment.
so basically, I used three containers in a row flex-direction then in the containers on the sides, I put 2 divs in each with column flex-direction. that's it.
you can control max and min width as you wish.
body {
background: lightgrey;
display: flex;
justify-content: center;
}
#container {
/* background: lightcoral; */
width: 100%;
height: 400px;
display: flex;
flex-direction: row;
}
.middle {
width: 60%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.left, .right{
width: 20%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.left div,
.right div {
border: 1px solid;
width: 100%;
height: 50%;
margin: 10px;
}
.middle div {
border: 1px solid;
width: 95%;
height: 100%;
margin: 10px;
}
<body>
<div class="container" id="container">
<div class="left">
<div></div>
<div></div>
</div>
<div class="middle">
<div></div>
</div>
<div class="right">
<div></div>
<div></div>
</div>
</div>
</body>
In your problem its better to display grid instead of flex
div1: middle
div2: left-top
div3: left-bottom
div4: right-top
div5: right-bottom
.parent {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 0px;
grid-row-gap: 0px;
}
.div1 { grid-area: 1 / 2 / 3 / 5; }
.div2 { grid-area: 1 / 1 / 2 / 2; }
.div3 { grid-area: 2 / 1 / 3 / 2; }
.div4 { grid-area: 1 / 5 / 2 / 6; }
.div5 { grid-area: 2 / 5 / 3 / 6; }
I'm trying to get even space between the font awesome icon and the paragraph of text to it's right, which is separated by a divider (in this the case, the right-border of the icon).
How can I make the space between the icon and it's border even, the same as the space between icons border and paragraph of text? I'm using flex's space-between at the moment, as well as some padding, but the space isn't evenly distributed, and it gets worse as the screen resizes.
body {
height: 100vh;
width: 100%;
}
#container {
height: 90%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
#display {
height: 76%;
width: 100%;
background-color: #ECECEC;
overflow: hidden;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.content {
display: flex;
justify-content: space-evenly;
align-items: center;
flex-direction: row;
height: 100%;
width: 95%;
}
.content i {
width: 25%;
display: flex;
justify-content: center;
align-items: center;
border-right: 1px solid black;
}
.text {
width: 50%;
justify-content: center;
align-items: center;
padding: 0 6%;
}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
<div id="container">
<div id="display">
<div class="content">
<i class="fas fa-balance-scale fa-7x"></i>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut scelerisque volutpat libero, at venenatis dolor rutrum vel. Donec fermentum eleifend tortor, at sollicitudin est rutrum nec. Fusce eget vehicula ex. Vestibulum semper gravida nulla, in aliquam ipsum dignissim nec.</p>
</div>
</div>
</div>
</div>
Try this.
.content i {
padding-right: 35px;
}
I have a jsfiddle below of 3 divs, 2 of which service-box-one & service-box-two the child service-details needs to be half the size of the parent div service-box and positioned at the bottom of the parent div service-box.
This works fine in IE, Firefox and Chrome, however, with safari, the divs empty-details and service-details don't inherit the 50% height and sit at the top of the parent div service-box instead of the bottom.
If you load the jsfiddle in IE, Firefox and Chrome you can see how it's supposed to look.
jsfiddle
.service-3col {
-ms-box-orient: horizontal;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
-ms-flex-wrap: wrap;
-moz-flex-wrap: wrap;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
list-style-type: none;
padding: 0;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.service-3col>li {
overflow: hidden;
}
.service-box {
width: 33.33333%;
max-width: 33.33333%;
-webkit-box-flex: 1 1 33.33333%;
-moz-box-flex: 1 1 33.33333%;
-webkit-flex: 1 1 33.33333%;
-ms-flex: 1 1 33.33333%;
flex: 1 1 33.33333%;
padding: 0 10px;
-ms-box-orient: horizontal;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.service-box .service-img {
min-height: 250px;
position: relative;
transition: all 0.5s ease-in-out;
background-image: url('https://wallpaperbrowse.com/media/images/random-pictures-1.jpg');
}
.service-box .service-img {
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
width: 100%;
}
.service-box .service-img .empty-details {
height: 50%;
background: transparent;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
width: 100%;
flex-direction: column;
}
.service-box-one .service-img .service-details,
.service-box-two .service-img .service-details {
height: 50%;
}
.service-box .service-img .service-details {
background: rgba(0, 102, 0, 0.8);
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
width: 100%;
flex-direction: column;
}
.service-box .service-img .service-details h1 {
text-align: center;
color: #FFF;
font-family: 'Times New Roman', Arial, Helvetica, sans-serif;
text-transform: uppercase;
margin-top: 15px;
margin-bottom: 0;
font-size: 1.6em;
}
h1 {
font-size: 2em;
margin: .67em 0;
}
.service-box-one .service-img .service-details p,
.service-box-two .service-img .service-details p {
font-size: 1.2em;
}
.service-box .service-img .service-details p,
.service-box .service-img .service-details b {
text-align: center;
color: #FFF;
margin: 0 1em 1em 1em;
}
.service-box-three .service-img .service-details {
height: 100%;
}
<div class="Zebra-section">
<div class="container">
<ul class="service-3col">
<li class="service-box service-box-one">
<div class="service-img">
<div class="empty-details">
</div>
<div class="service-details">
<h1>NO VAT!</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut commodo, odio sit amet interdum porttitor</p>
</div>
</div>
</li>
<li class="service-box service-box-two">
<div class="service-img">
<div class="empty-details">
</div>
<div class="service-details">
<h1>Surveys</h1>
<p>Buying a house?
<br> You need a survey.
</p>
<a class="Btn Btn--big">READ MORE</a>
</div>
</div>
</li>
<li class="service-box service-box-three">
<div class="service-img">
<div class="service-details">
<h1>Testimonials</h1>
<div class="testimonial-fade">
<div class="testimonial-text">
<p><em>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut commodo, odio sit amet interdum porttitor, nibh elit tempus mi, ac consequat tortor sem vitae sapien. Mauris tempus leo neque, in sollicitudin lorem venenatis ac. Vestibulum imperdiet mollis dignissim. Suspendisse vitae posuere tellus.</em></p>
<b>Chris</b>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
Add these two lines of code to your CSS:
.service-box .service-img .empty-details
{
position:relative; <-------- this
float:left; <-------- this
width:100%;
height: 50%;
background: transparent;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
flex-direction: column;
}
Those two lines should force the empty-details div and service-details div to each take a position relative to their container div and since they both have width:100% they should both occupy the whole width meaning the latter will have to go to the bottom since the top is taken.
There are other approaches, for example, if the top example didn't work you could set the service-details div to be position:absolute and bottom:0 since its parent container element now has position: relative (leave the new CSS we just addded above). And add the class .service-details under the old statement (don't erase the old CSS) like this:
.service-box-one .service-img .service-details, .service-box-two .service-img .service-details
{
height: 50%;
}
.service-details
{
position:absolute; // Container div must have position:relative
bottom:0; // No need to write px in 0px when value is 0
}
I have a layout built using flexbox, but there is one aspect I just can't seem to get to work.
I have panels which have anchor tags in them that I want to be vertically and horizontally centered, but I want the anchor tags to be 100% of the width and height of the panel so that when you click anywhere in the panel it will link you, as opposed to just clicking the link text.
Here is the HTML for a panel:
<div class="panel--link panel--one">
<a href="#" class="link">
Panel 1
</a>
</div>
And the SCSS:
.panel {
box-sizing: content-box;
flex: 1;
border: 3px solid #fff;
padding: 0px;
text-align: center;
}
.panel--link {
#extend .panel;
display: flex;
flex: 1;
justify-content: center;
align-items: center;
a.link {
text-decoration: none;
color: #fff;
text-transform: uppercase;
font-weight: 600;
font-size: 1rem;
letter-spacing: 3px;
flex: 1;
}
}
See my Codepen for the entire layout so you understand it better!
http://codepen.io/zauber/pen/BpRJQG
Thanks for the help
Don't be afraid, make anchor flexbox too:
a {
display: flex;
justify-content: center;
align-items: center;
}
and you should add align-items: stretch to parent of anchor.
Remove align-items: center from .content .panel--link and make .content .panel--link a.link a flexbox too and align it vertically using:
display: flex;
justify-content: center;
align-items: center;
See demo below:
body {
height: 800px;
}
.main {
height: 100%;
}
.content {
height: 100%;
border: 20px solid #fff;
display: flex;
box-sizing: border-box;
}
.content .column {
flex-direction: column;
width: 33.33333%;
background: #374550;
display: flex;
}
.content .panel,
.content .panel--link {
box-sizing: content-box;
flex: 1;
border: 3px solid #fff;
padding: 0px;
text-align: center;
}
.content .panel .logo,
.content .panel--link .logo {
margin: 7.5% 0px 0% 0%;
width: 80%;
}
.content .panel .blurb,
.content .panel--link .blurb {
width: 80%;
margin: 7.5% auto 0% auto;
}
.content .panel .blurb h1,
.content .panel--link .blurb h1 {
text-decoration: none;
color: rgba(255, 255, 255, 0.6);
font-weight: lighter;
line-height: 220%;
font-size: 0.85rem;
margin: 0px;
}
.content .panel .tel,
.content .panel--link .tel {
margin: 7.5% auto 5% auto;
}
.content .panel .tel h2,
.content .panel--link .tel h2 {
text-decoration: none;
color: #fff;
font-weight: 500;
font-size: 1.2rem;
margin: 0px;
}
.content .panel--link {
display: flex;
flex: 1;
justify-content: center;
/*align-items: center;*/
text-align: center;
}
.content .panel--link a.link {
text-decoration: none;
color: #fff;
text-transform: uppercase;
font-weight: 600;
font-size: 1rem;
letter-spacing: 3px;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
#media (max-width: 768px) {
.content .column--two {
order: -1;
}
.content .column--two .panel--two {
order: -1;
}
}
.content .column--two .panel--one {
flex-grow: 1;
}
.content .column--two .panel--two {
flex-grow: 2;
background: #374550;
}
.content .column--two .panel--three {
flex-grow: 1;
}
<main class="content">
<div class="column column--one">
<div class="panel--link panel--one">
<a href="#" class="link">
Panel 1
</a>
</div>
<div class="panel--link panel--two">
<a href="#" class="link">
Panel 2
</a>
</div>
</div>
<div class="column column--two">
<div class="panel--link panel--one">
<a href="" class="link">
Panel 3
</a>
</div>
<div class="panel panel--two">
<div class="blurb">
<h1>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin lectus orci, imperdiet ac auctor non, tristique eget augue. Curabitur quis gravida lorem, sed maximus purus. Nunc sit amet mollis turpis.</h1>
</div>
<div class="tel">
<h2>123 456 789</h2>
</div>
</div>
<div class="panel--link panel--three">
<a href="#" class="link">
Panel 4
</a>
</div>
</div>
<div class="column column--three">
<div class="panel--link panel--one">
<a href="#" class="link">
Panel 5
</a>
</div>
<div class="panel--link panel--two">
<a href="#" class="link">
Panel 6
</a>
</div>
</div>
</main>
This question already has answers here:
How to stretch children to fill cross-axis?
(3 answers)
Closed 4 years ago.
I feel a little silly asking this, but I've sort of exhausted my knowledge of Flexboxes, so I'm hoping maybe someone else can come in and help me out here.
My overall goal is to just have the two items in the middle row stretch to fill the space between the header and the items, and I have searched around and honestly can't figure out what it is that I should do. I forked the code from the CSS Tricks Guide, the one at the very bottom, and I've made some alterations. The code I currently have is (open it in full screen mode to make it more clear):
body,
html {
height: 100%;
}
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
justify-content: flex-start;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
height: 100%;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 1 100%;
}
.header {
background: tomato;
height: 50px;
flex: 1 1 100%;
}
.footer {
background: lightgreen;
height: 50px;
}
.main {
text-align: left;
align-self: stretch;
background: deepskyblue;
}
.aside-1 {
background: gold;
}
.aside-2 {
background: hotpink;
}
#media all and (min-width: 600px) {
.aside {
flex: 1 auto;
}
}
#media all and (min-width: 800px) {
.main {
flex: 3 0px;
}
.aside-1 {
order: 1;
}
.main {
order: 2;
}
.aside-2 {
order: 3;
}
.footer {
order: 4;
}
}
body {
padding: 2em;
}
<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<footer class="footer">Footer</footer>
</div>
Is it possible in flexbox to achieve this without changing the HTML, or should I just look for another way to accomplish this goal?
While people are telling you how to resolve the issue, they are not telling you why you don't have the result you expected. I think it's partly because most of them missed the actual question. Which I found really interesting.
Let me get some things out of the way first :
Flex-direction:: For practical purpose it means the direction in which the items are displayed. However it's not accurate.
For now let's say that if the direction is set to row, it means that each item must have the height of the container and they should be put next to each other. In other words the container has to be considered a row and the item are the columns.
.c{
display: flex;
width: 400px;
height:100px;
}
.c1{
flex-grow: 1;
background:gold;
}
.c2{
flex-grow: 1;
background:red;
}
<div class="c">
<div class="c1"></div>
<div class="c2"></div>
</div>
I didn't specify an height, the items filled the height of the row and stacked against each others like columns.
When you specify an height the item will take the height you defined but that does not change the height of the row :
.c{
display: flex;
width: 400px;
height: 100px;
}
.c1{
flex-grow: 1;
height: 40px;
background:gold;
}
.c2{
flex-grow: 1;
background:red;
}
<div class="c">
<div class="c1"></div>
<div class="c2"></div>
</div>
The red cube still spawn the vertical space because the height of the row hasn't changed.
flex grow: the amount of free space distributed to the different items.
.c{
display: flex;
width: 400px;
}
.c1{
flex-grow: 1;
background:gold;
}
.c2{
flex-grow: 1;
background:red;
}
<div class="c">
<div class="c1">AAAAAAAAAAAAA</div>
<div class="c2"></div>
</div>
Despite having the same flex-grow value, those two items aren't the same size, that is because the free space is distributed among them but the yellow rectangle was bigger to begin with.
First let's use flex-wrap : wrap:
.c{
display: flex;
flex-wrap: wrap;
border: 1px solid black;
width: 400px;
height:100px;
}
.c1{
width:200px;
background:gold;
}
.c2{
width:200px;
background:red;
}
.c3{
width:100px;
background:orange;
}
.c4{
width:300px;
background:green;
}
<div class="c">
<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
<div class="c4"></div>
</div>
As we can see when we go beyond the amount of width available the items start under, effectively creating another row.
Now to address your question:
What if we took the example above and set the height of the first item ? Let's see:
.c{
display: flex;
flex-wrap: wrap;
border: 1px solid black;
width: 400px;
height:100px;
}
.c1{
width:200px;
height: 30px;
background:gold;
}
.c2{
width:200px;
background:red;
}
.c3{
width:200px;
background:orange;
}
.c4{
width:200px;
background:green;
}
<div class="c">
<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
<div class="c4"></div>
</div>
Like in your snippet.
Let's see another example:
.c{
display: flex;
flex-wrap: wrap;
border: 1px solid black;
width: 600px;
height:100px;
}
.c1{
width:400px;
height: 35px;
background:gold;
}
.c2{
width:200px;
background:red;
}
.c3{
width:200px;
background:orange;
}
.c4{
width:200px;
background:green;
}
.c5{
width:200px;
background:purple;
}
<div class="c">
<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
<div class="c4"></div>
<div class="c5"></div>
</div>
yellow cube of 400px X 35px is put and spans 2 columns, then red cube of 200px is put and spans 1 column.
At this point all the rectangles have 0 height except the first one which has 35px.
The remaining vertical space is divided between the rows as to spawn the whole vertical space. Thus the remaining vertical space is 100-35 = 65px.
divided in 2 rows = 32.5. The first row gets 35 + 32.5 and the second row gets 32.5px height.
Another example to make things clearer:
.c, .d{
display: flex;
flex-wrap: wrap;
border: 1px solid black;
width: 600px;
height:100px;
}
.c1{
flex-shrink: 0;
width:400px;
height: 0px;
background:gold;
}
.c2{
width:200px;
background:red;
}
.c3{
width:200px;
background:orange;
}
.c4{
width:200px;
background:green;
}
.c5{
width:200px;
background:purple;
}
.d1{
width:400px;
height: 50px;
background:gold;
}
.d2{
width:200px;
background:red;
}
.d3{
width:200px;
background:orange;
}
.d4{
width:200px;
background:green;
}
.d5{
width:200px;
background:purple;
}
First item has 0px height, the vertical space remaining (100px) is divided between the 2 rows. Both row have 50px height
<div class="c">
<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
<div class="c4"></div>
<div class="c5"></div>
</div>
First item has 35px height, the vertical space remaining (65px) is divided between the 2 rows.
<div class="d">
<div class="d1"></div>
<div class="d2"></div>
<div class="d3"></div>
<div class="d4"></div>
<div class="d5"></div>
</div>
To resolve this you can use calc() to calculate the other rows height like others suggested. The reason is that there is no more free vertical space to be shared.
.c{
display: flex;
flex-wrap: wrap;
border: 1px solid black;
width: 600px;
height:100px;
}
.c1{
width:400px;
height: 35px;
background:gold;
}
.c2{
width:200px;
background:red;
}
.c3{
height:calc(100% - 35px);
width:600px;
background:green;
}
<div class="c">
<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
</div>
The idea is to wrap them around a container and use flex-grow:1; on that container, this will make the container fill the space between the header and footer..
Then in the #media query, change the flex-direction of this container to row. This will make the .main and aside to come side by side on big screens.
body,
html {
height: 100%;
}
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
justify-content: flex-start;
flex-direction:column;
height: 100%;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
}
.header {
background: tomato;
height: 50px;
flex-shrink:0;
}
.footer {
background: lightgreen;
height: 50px;
flex-shrink:0;
}
.main {
text-align: left;
//align-self: stretch;
background: deepskyblue;
padding:10px;
}
.main p{
margin:0;
padding:0;
}
.aside-1 {
background: gold;
}
.aside-2 {
background: hotpink;
}
.container{
width:100%;
margin:0;
padding:0;
flex-grow:1;
flex-shrink:0;
}
#media all and (min-width: 600px) {
.aside {
flex: 1 auto;
}
}
#media all and (min-width: 800px) {
.container{
display:flex;
flex-direction:row;
}
.main {
flex: 3 0px;
flex-grow:1;
flex-shrink:0;
}
.aside-1 {
order: 1;
flex-grow:1;
flex-shrink:0;
}
.main {
order: 2;
}
.aside-2 {
order: 3;
}
.footer {
order: 4;
}
}
body {
padding: 2em;
}
<div class="wrapper">
<header class="header">Header</header>
<div class="container">
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
</div>
<footer class="footer">Footer</footer>
</div>
You can't fill the remaining space in the cross-axis direction when you are using a wrapping flexbox - I guess you need a column flexbox for that.
But you can do this as a quick fix:
Add align-content: center to the flexbox (for resetting the default stretch value)
Adjust the heights using calc (have removed the body padding and margin for illustration)
See demo below:
body,
html {
height: 100%;
}
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
justify-content: flex-start;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
height: 100%;
font-weight: bold;
text-align: center;
align-content: center; /* ADDED THIS */
}
.wrapper > * {
padding: 10px;
flex: 1 1 100%;
}
.header {
background: tomato;
height: 50px;
flex: 1 1 100%;
}
.footer {
background: lightgreen;
height: 50px;
}
.main {
text-align: left;
align-self: stretch;
background: deepskyblue;
height: calc(50vh - 90px); /* ADDED THIS */
}
.aside-1 {
background: gold;
height: calc(50vh - 90px); /* ADDED THIS */
}
.aside-2 {
background: hotpink;
}
#media all and (min-width: 600px) {
.aside {
flex: 1 auto;
}
}
#media all and (min-width: 800px) {
.main {
flex: 3 0px;
}
.aside-1 {
order: 1;
height: calc(100vh - 160px); /* ADDED THIS */
}
.main {
order: 2;
height: calc(100vh - 160px); /* ADDED THIS */
}
.aside-2 {
order: 3;
}
.footer {
order: 4;
}
}
body {
/* padding: 2em;*/
margin: 0; /* ADDED THIS */
}
<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<footer class="footer">Footer</footer>
</div>
Using calc is not very tidy and you would want to use a nested flexbox here (if it is ok to change the html):
Add a wrapper for the main and aside-1 and make it a wrapping flexbox in row direction
Add flex: 1 to this wrapper to fill the vertical space between the header and footer
See demo below:
body,
html {
height: 100%;
}
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
/*-webkit-flex-flow: row wrap;*/
/*flex-flow: row wrap;*/
flex-direction: column;
height: 100%;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
/*flex: 1 1 100%;*/
}
.header {
background: tomato;
height: 50px;
/*flex: 1 1 100%;*/
}
.footer {
background: lightgreen;
height: 50px;
}
.main {
text-align: left;
align-self: stretch;
background: deepskyblue;
}
.aside-1 {
background: gold;
flex: 1 auto;/* ADDED THIS */
}
.aside-2 {
background: hotpink;
}
.wrapper > section { /* ADDED THIS */
display: flex;
flex-flow:row wrap;
flex: 1;
padding: 0;
overflow: auto;
}
#media all and (min-width: 600px) {
.aside {
flex: 1 auto;
}
}
#media all and (min-width: 800px) {
.main {
flex: 3 0px;
}
.aside-1 {
order: 1;
}
.main {
order: 2;
}
.aside-2 {
order: 3;
}
.footer {
order: 4;
}
}
body {
/*padding: 2em;*/
margin: 0;
}
<div class="wrapper">
<header class="header">Header</header>
<section>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
</section>
<footer class="footer">Footer</footer>
</div>
After reading all the other answers, I decided to post my own.
I might have missed something already posted or misunderstood the question, though for me this should be the simplest solution, without any markup changed.
If this answers your question, I will add a short explanation why/how it works.
html, body {
margin: 0;
}
.wrapper {
display: flex;
flex-direction: column;
height: 100vh;
}
.header {
height: 50px;
}
.footer {
height: 50px;
}
.main {
text-align: left;
flex: 1;
}
#media (min-width: 600px) {
.aside {
flex: 1;
}
}
#media (min-width: 800px) {
.wrapper {
flex-direction: row;
flex-wrap: wrap;
}
.header {
flex-basis: 100%;
order: -1;
}
.main {
flex: 2;
}
.aside-1 {
order: -1;
height: calc(100% - 100px);
}
.footer {
flex-basis: 100%;
}
}
/* for styling */
.wrapper {
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
box-sizing: border-box;
}
.header {
background: tomato;
}
.footer {
background: lightgreen;
}
.main {
background: deepskyblue;
}
.aside-1 {
background: gold;
}
<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<footer class="footer">Footer</footer>
</div>
If you were able to change the markup, here is a version of mine, with a much simpler code base than others have given, and also the header and footer is without a fixed height.
html, body {
margin: 0;
}
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.innerwrapper {
flex: 1;
display: flex;
flex-direction: column;
}
.main {
flex: 1;
text-align: left;
}
#media (min-width: 600px) {
.aside {
flex: 1;
}
}
#media (min-width: 800px) {
.innerwrapper {
flex-direction: row;
}
.aside-1 {
order: -1;
}
}
/* for styling */
.wrapper {
font-weight: bold;
text-align: center;
}
.wrapper > *:not(.innerwrapper),
.wrapper .innerwrapper > * {
padding: 10px;
box-sizing: border-box;
}
.header {
background: tomato;
}
.footer {
background: lightgreen;
}
.main {
background: deepskyblue;
}
.aside-1 {
background: gold;
}
<div class="wrapper">
<header class="header">Header</header>
<div class="innerwrapper">
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
</div>
<footer class="footer">Footer</footer>
</div>