What CSS properties should I set so that the columns will wrap with pre-determined column breaks and ordering?
The columns will contain items of dynamic and varying height (so their height can't be specified in the CSS).
Desired responsive layout at various widths
Unsuccessful attempt
(I earlier attempted to do this with Grid layout, but that doesn't work because I don't have rigid row heights.)
I'm now attempting to do this with display: flex, but it doesn't behave how I want in most browsers. An example:
header {
height: 2.0rem;
background: PeachPuff;
}
footer {
height: 2.0rem;
background: PaleGreen;
}
header,
footer,
section.app-column {
padding: 1.0rem;
}
section.app-column {
display: inline-block;
flex: none;
page-break-inside: avoid;
break-inside: avoid;
width: 150px;
margin-right: 0.5rem;
}
section#main section#app-column-primary {
background: Cyan;
}
section#main section#app-column-secondary {
background: Thistle;
}
section#main section#app-column-tertiary {
background: Coral;
}
section#main {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
}
#media (max-width: 199px) {
section#main {
content: "<p>This application requires a wider graphical display.</p>";
}
section.app-column {
display: none;
}
}
#media (min-width: 200px) and (max-width: 399px) {
section#app-column-primary { order: 1; }
section#app-column-secondary { order: 2; }
section#app-column-tertiary { order: 3; }
section.app-column {
page-break-before: avoid;
break-before: avoid-column;
}
}
#media (min-width: 400px) and (max-width: 599px) {
section#app-column-primary { order: 1; }
section#app-column-secondary { order: 3; }
section#app-column-tertiary { order: 2; }
section.app-column {
page-break-before: always;
break-before: column;
}
section#app-column-tertiary {
page-break-before: avoid;
break-before: avoid-column;
}
}
#media (min-width: 600px) {
section#app-column-primary { order: 1; }
section#app-column-secondary { order: 2; }
section#app-column-tertiary { order: 3; }
section.app-column {
page-break-before: always;
break-before: column;
}
}
<header>Header ipsum, dolor sit amet.</header>
<section id="main">
<section class="app-column" id="app-column-primary">
Primary column
<br />Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</section>
<section class="app-column" id="app-column-secondary">
Secondary column
<br />Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur ac ornare justo. Sed vitae rhoncus nibh. Phasellus
venenatis, quam eu rutrum porta, velit dolor fermentum elit, eu
faucibus sapien ipsum in leo.
</section>
<section class="app-column" id="app-column-tertiary">
Tertiary column
<br />Lorem ipsum dolor sit amet.
</section>
</section>
<footer>Footer ipsum, dolor sit amet.</footer>
Correct result in Firefox
Firefox correctly interprets the requested break-before properties. For example, at 2 columns across:
Webkit and Chrome fail to break columns
But Chrome (and Webkit browsers) incorrectly refuse to insert a column break:
Note that CanIUse tells me that page-break-before should give the behaviour I'm wanting. Yet this example still fails, with page-break-before in the right places.
How can I get the correct result in all browsers that support Flexbox?
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; }
For a homepage designed in flexbox, I am encountering a problem which I cannot solve in CSS, unfortunately. I also wonder whether it is doable at all in CSS only. If not, then I will need to find a solution in JS.
The website is mobile first. In the flex container there are an H2 element, 3 divs: .intro, .image and .text. In .text there are paragraphs and a button.
In the mobile and tablet queries all works fine, except for the desktop version where the .text div should go underneath the .intro div, which both go to the right of the .image div. Left and right should be 50% both.
This is the code:
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
}
.flex-container > * {
padding: 10px;
flex: 1 100%;
}
.text {
text-align: left;
background: cornflowerblue;
}
.intro {
background: yellow;
}
.image {
background: moccasin;
height: 200px;
}
#media all and (min-width: 600px) {
.image { flex: 1 0px; }
.text { flex: 1 0px; }
.image { order: 1; }
.text { order: 2; }
}
#media all and (min-width: 769px) {
.flex-container :not(.image){
-webkit-flex-flow: column nowrap;
flex-flow: column nowrap;
}
.intro { flex: 1 50%; }
.image { flex: 12 0px; }
.text { flex: 1 50%; }
.image { order: 1; }
.intro { order: 2; }
.text { order: 3; }
}
</style>
</head>
<body>
<h2>Title</h2>
<div class="flex-container">
<div class="intro">
<p>Intro: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sed ex turpis.</p>
</div>
<div class="image">Image</div>
<div class="text">
<p>Text: Cras luctus nibh lectus, in ullamcorper ex tempor eleifend. Nulla bibendum, eros a consequat vestibulum, orci massa fermentum quam, sed commodo nunc ex vitae nisl.</p>
<button>click me</button>
</div>
</div>
</body>
</html>
Here's how it should look like:
how the desktop media query should look like
if you have nothing about grid, you may use it for the desktop layout :
.flex-container {
font-weight: bold;
text-align: center;
}
.flex-container>* {
padding: 10px;
flex: 1 100%;
}
.text {
text-align: left;
background: cornflowerblue;
}
.intro {
background: yellow;
}
.image {
background: moccasin;
height: 200px;
}
#media all and (min-width: 600px) {
.flex-container {
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
}
.image {
flex: 1 0px;
}
.text {
flex: 1 0px;
}
.image {
order: 1;
}
.text {
order: 2;
}
}
#media all and (min-width: 769px) {
.flex-container {
display: grid;
grid-template-columns: 1fr 1fr;
}
.intro,
.text {
grid-column: 2;
}
.image {
grid-row:1 / span 2
}
}
<h2>Title</h2>
<div class="flex-container">
<div class="intro">
<p>Intro: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sed ex turpis.</p>
</div>
<div class="image">Image</div>
<div class="text">
<p>Text: Cras luctus nibh lectus, in ullamcorper ex tempor eleifend. Nulla bibendum, eros a consequat vestibulum, orci massa fermentum quam, sed commodo nunc ex vitae nisl.</p>
<button>click me</button>
</div>
</div>
usefull link : https://css-tricks.com/snippets/css/complete-guide-grid/
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>
I'm trying to center a wrapper using flex box and fixed width. When I add a fixed width to the body like 100% and use margin: 0 auto; everything is thrown off center. I would like the wrapper to have a fixed width of 1000px and centered within the body (this is why I'm setting the body to 100%).
Any help is appreciated. HTML and CSS below.
HTML:
<!doctype html>
<html lang="eng">
<head>
<meta charset="utf-8" />
<title>Flex box layout</title>
<link rel="stylesheet" href="webtemp.css" />
</head>
<body>
<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>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>
</body>
</html>
CSS:
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.header {
background: tomato;
}
.footer {
background: lightgreen;
}
.main {
text-align: left;
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;
}
Apply fixed width and use margin:0px auto; to align center.
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
width:300px;
margin:0px auto;
}
DEMO
just set the width of .wrapper to 1000px;
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
width:1000px;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.header {
background: tomato;
}
.footer {
background: lightgreen;
}
.main {
text-align: left;
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>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>
emphasized text
I am experimenting with flexboxes and the tutorial from codebin and I want the layout to be a full screen flexbox layout.
The Jfiddle can't emulate the 100% stretch thing for some reason but the screenshot seems to make the issue clear.
But I want the header to have a predefined height without it stretching and there is a lot of empty space in the elements that don't seem to wrap itself to it's content.
This goes for all the items really. I would want a layout where I can define the height of items without creating non wrapped gaps in the process. % doesn't seem to be working.
http://jsfiddle.net/rhkahtaa/
<html>
<style>
body {
display:flex;
}
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
align-items:stretch;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
flex-basis: 1 auto;
}
.header {
height:20%;
flex-shrink:1;
background: red;
}
.footer {
background: green;
}
.main {
width:80%;
text-align: left;
background: blue;
}
.aside-1 {
width:10%;
background: gold;
}
.aside-2 {
width:10%;
background: pink;
}
#media all and (min-width: 600px) {
.aside { flex: 1 auto; }
}
#media all and (min-width: 800px) {
.main { flex: 2 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}
</style>
<body>
<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>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>
</body>