This question already has answers here:
Is it possible for flex items to align tightly to the items above them?
(5 answers)
Closed 4 years ago.
i'm trying to get to the layout from middle to left as shown in the picture.
How can i make the grey div to push itself up using flex? Should i just use fixed position for it? Thought about changing the html to create container div for the orange and grey boxes, but I want to see how to do it without changing the html.
#import 'general.css';
#import 'reg.css';
#import "768.css" screen and (min-width : 992px);
#import "992.css" screen and (min-width : 1200px);
/*general*/
body, html{
margin: 0;
padding:0;
height: 100%;
}
* {
box-sizing: border-box;
}
/*reg*/
.container{
background-color: red;
text-align: center;
display: flex;
height: 100%;
flex-wrap: wrap;
}
.box{
height: 10%;
width: 100%;
}
header{
background-color: black;
color: white;
width: 100%;
order:1;
}
footer{
background-color: navy;
color: white;
width: 100%;
order:5;
}
.main-content{
background-color: dodgerblue;
height: 60%;
width: 100%;
order:2;
}
.grey{
background-color: grey;
order:4;
}
.orange{
background-color: orangered;
order:3;
}
/*768*/
.box{
height: 11%;
}
.main-content{
height: 67%;
}
.grey{
width: 30%;
order:3;
}
.orange{
background-color: orangered;
width: 70%;
order:4;
}
/*992*/
.main-content{
width: 85%;
order:3;
align-self: flex-end;
height: 80%;
}
.grey{
width: 15%;
order:4;
align-self: flex-start;
height:20% ;
}
.orange{
width:15%;
order:2;
align-self: flex-start;
height: 60%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/index.css">
<title>Document</title>
</head>
<body>
<div class="container">
<header class="box">this is the header</header>
<div class="main-content box">this is main content</div>
<div class="orange box">this is the orange</div>
<div class="grey box">this is the grey</div>
<footer class="box">this is the footer</footer>
</div>
</body>
</html>
I don’t see any solution only using flex because boxes will flow in lines. So as you mentioned, using a positioning for the grey box would be the only way to achieve this.
This is a solution using grid though:
body, html {
height: 100%;
padding:0;
margin: 0;
}
* {
box-sizing: border-box;
}
.container {
display: grid;
grid-template-areas:
"a"
"b"
"c"
"d"
"e";
grid-template-rows: 1fr 60% 1fr 1fr 1fr;
height: 100%;
background-color: red;
}
.box {
display: flex;
justify-content: center;
align-items: center;
}
header {
grid-area: a;
color: white;
background-color: black;
}
.main-content {
grid-area: b;
background-color: dodgerblue;
}
.orange {
grid-area: c;
order: 4;
background-color: orangered;
}
.grey {
grid-area: d;
background-color: grey;
}
footer {
grid-area: e;
color: white;
background-color: navy;
}
#media ( min-width: 768px ) {
.container {
grid-template-areas:
"a a"
"b b"
"d c"
"e e";
grid-template-rows: 15% 4fr 1fr 15%;
grid-template-columns: 15% 1fr;
}
#media ( min-width: 992px ) {
.container {
grid-template-areas:
"a a"
"c b"
"d b"
"e e";
grid-template-rows: 15% 4fr 1fr 15%;
grid-template-columns: 15% 1fr;
}
}
<div class="container">
<header class="box">this is the header</header>
<div class="box main-content">this is main content</div>
<div class="box orange">this is the orange</div>
<div class="box grey">this is the grey</div>
<footer class="box">this is the footer</footer>
</div>
You can use the order style of flex children to affect what order they are rendered inside of a flex parent, however this does require some wrapping divs so you'd have to change your HTML slightly, otherwise you must use CSS grid. Snippet with working example of your images below:
:root {
--min-height: 80px;
}
* {
border-sizing: border-box;
padding: 0;
margin: 0;
}
html, body, .container {
height: 100%;
}
body {
padding: 10px;
}
div {
border-radius: 10px;
}
.container {
display: flex;
flex-direction: column;
}
.container > div {
margin-bottom: 10px;
}
.container > div:last-child {
margin: 0;
}
.main-content > div {
margin-bottom: 10px;
}
.main-content > div:last-child {
margin: 0;
}
.side-content > div {
margin-bottom: 10px;
}
.side-content > div:last-child {
margin: 0;
}
.header, .footer, .content {
min-height: var(--min-height);
}
.teal.content {
min-height: calc(5 * var(--min-height));
}
.black {
background: rgb(30, 32, 42);
}
.teal {
background: rgb(74, 161, 162);
}
.orange {
background: rgb(253, 170, 82);
}
.gray {
background: rgb(203, 187, 172);
}
.navy {
background: rgb(61, 94, 109);
}
#media screen and (min-width: 768px) {
.side-content {
display: flex;
flex-direction: row;
}
.side-content > div {
margin: 0;
}
.side-content > div:last-child {
margin-right: 10px;
}
.orange {
flex: 2 0 auto;
order: 1;
}
.gray {
flex: 1 0 auto;
order: 0;
}
}
#media screen and (min-width: 992px) {
.main-content {
display: flex;
flex-direction: row;
}
.main-content > div {
margin: 0;
}
.main-content > div:last-child {
margin-right: 10px;
}
.side-content {
order: 0;
flex: 1 0 auto;
flex-direction: column;
margin-right: 10px;
}
.side-content > div:last-child {
margin: 0;
}
.side-content > div:first-child {
margin-bottom: 10px;
}
.orange {
order: 0;
margin-bottom: 10px;
}
.teal {
order: 1;
flex: 7 0 auto;
}
}
<div class="container">
<div class="black header"></div>
<div class="main-content">
<div class="teal content"></div>
<div class="side-content">
<div class="orange content"></div>
<div class="gray content"></div>
</div>
</div>
<div class="navy footer"></div>
</div>
Related
Is it possible to prevent the overflow of a child in a css grid container set to height: 80% ?
When a css grid row is set to 1fr, it is easily overflown by its children.
My main goal is to limit the height of .bottom & .side,
and have the ul element fill the .side element, while having overflow-y: scroll
.side should always be full height of .bottom.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body,
html {
height: 100%;
}
.container {
height: 80%;
max-height: 300px;
width: 500px;
margin: 0 auto;
border: 1px solid #000;
display: grid;
grid-template-rows: 72px 1fr;
}
.top {
background-color: cyan;
}
.bottom {
background-color: #e9eaf4;
display: grid;
grid-template-columns: 224px 1fr;
grid-column-gap: 24px;
}
.bottom .side,
.bottom .main {
background-color: #fff;
}
ul {
list-style: none;
border: 1px dashed red;
}
ul span {
padding: 10px;
font-size: 20px;
}
<div class="container">
<div class="top">top</div>
<div class="bottom">
<div class="side">side
<ul>
<li><span>1</span></li>
<li><span>2</span></li>
<li><span>3</span></li>
<li><span>4</span></li>
<li><span>5</span></li>
<li><span>6</span></li>
<li><span>7</span></li>
<li><span>8</span></li>
<li><span>9</span></li>
<li><span>10</span></li>
</ul>
</div>
<div class="main">main</div>
</div>
</div>
Adjust the code like below (check the comments). Related question to understand the min-height trick Prevent content from expanding grid items
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body,
html {
height: 100%;
}
.container {
height: 80%;
max-height: 300px;
width: 500px;
margin: 0 auto;
border: 1px solid #000;
display: grid;
grid-template-rows: 72px 1fr;
}
.top {
background-color: cyan;
}
.bottom {
background-color: #e9eaf4;
display: grid;
grid-template-columns: 224px 1fr;
grid-column-gap: 24px;
min-height:0; /* added */
}
.bottom .side,
.bottom .main {
background-color: #fff;
display:flex; /* added */
flex-direction:column; /* added */
min-height: 0; /* added */
}
ul {
list-style: none;
border: 1px dashed red;
overflow:auto; /* added */
}
ul span {
padding: 10px;
font-size: 20px;
}
<div class="container">
<div class="top">top</div>
<div class="bottom">
<div class="side">side
<ul>
<li><span>1</span></li>
<li><span>2</span></li>
<li><span>3</span></li>
<li><span>4</span></li>
<li><span>5</span></li>
<li><span>6</span></li>
<li><span>7</span></li>
<li><span>8</span></li>
<li><span>9</span></li>
<li><span>10</span></li>
</ul>
</div>
<div class="main">main</div>
</div>
</div>
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I’m having issues tracking the problem of a div that contains a big table (a green div in the fiddle). I want this div to have a working overflow-x: auto.
On firefox I don’t see any issues, the table container when the windows is too little adds a scrollbar, with chrome or opera the browser scrollbar is shown alongside the block scrollbar, and the page content extends over the window length.
If I don’t use Grid, all browsers show the same behavior, with a scrollbar only in the parent block of the table.
Here's a fiddle and snippet:
.content {
grid-area: content;
display: block;
max-width: 1200px;
margin: 0 auto;
width: 100%;
box-sizing: border-box;
min-height: calc(100vh - 6em);
overflow: hidden;
}
.footer {
grid-area: footer;
height: 3em;
background-color: grey;
}
.sidemenu {
height: 3em;
grid-area: sidemenu;
background-color: grey;
}
.wrapper {
display: grid;
grid-template-areas:
"sidemenu"
"content"
"footer";
}
.big {
background-color: green;
width: 2980px;
height: 20px;
}
.blockWrapper { overflow-x: auto; }
#media (min-width: 500px) {
.wrapper {
grid-template-columns: 3em 1fr;
grid-template-areas:
"sidemenu content"
"sidemenu footer";
}
.sidemenu { height: 100%; }
}
<div class="wrapper">
<div class="sidemenu"></div>
<div class="content">
<div class="blockWrapper">
<div class="big"></div>
</div>
</div>
<div class="footer"></div>
</div>
You can remove width: 100% and margin: 0 auto on .content to get the same behavior in Chrome & Firefox - see demo below:
.content {
grid-area: content;
display: block;
max-width: 1200px;
/*margin: 0 auto;
width: 100%;*/
box-sizing: border-box;
min-height: calc(100vh - 6em);
overflow: hidden;
}
.footer {
grid-area: footer;
height: 3em;
background-color: grey;
}
.sidemenu {
height: 3em;
grid-area: sidemenu;
background-color: grey;
}
.wrapper {
display: grid;
grid-template-areas: "sidemenu" "content" "footer";
}
.big {
background-color: green;
width: 2980px;
height: 20px;
}
.blockWrapper {
overflow-x: auto;
}
#media (min-width: 500px) {
.wrapper {
grid-template-columns: 3em 1fr;
grid-template-areas: "sidemenu content" "sidemenu footer";
}
.sidemenu {
height: 100%;
}
}
<div class="wrapper">
<div class="sidemenu"></div>
<div class="content">
<div class="blockWrapper">
<div class="big"></div>
</div>
</div>
<div class="footer"></div>
</div>
Another fix can be to specify grid-template-columns: 100% and grid-template-columns: 3em calc(100% - 3em) for the media query above 500px - see demo below:
.content {
grid-area: content;
display: block;
max-width: 1200px;
margin: 0 auto;
width: 100%;
box-sizing: border-box;
min-height: calc(100vh - 6em);
overflow: hidden;
}
.footer {
grid-area: footer;
height: 3em;
background-color: grey;
}
.sidemenu {
height: 3em;
grid-area: sidemenu;
background-color: grey;
}
.wrapper {
display: grid;
grid-template-areas: "sidemenu" "content" "footer";
grid-template-columns: 100%; /* added */
}
.big {
background-color: green;
width: 2980px;
height: 20px;
}
.blockWrapper {
overflow-x: auto;
}
#media (min-width: 500px) {
.wrapper {
grid-template-columns: 3em 1fr;
grid-template-areas: "sidemenu content" "sidemenu footer";
grid-template-columns: 3em calc(100% - 3em); /* added */
}
.sidemenu {
height: 100%;
}
}
<div class="wrapper">
<div class="sidemenu"></div>
<div class="content">
<div class="blockWrapper">
<div class="big"></div>
</div>
</div>
<div class="footer"></div>
</div>
I'm trying to achieve a responsive layout as outlined in the image, left side would be mobile, right side desktop. This would be relatively easy using flexbox if I could set a fixed height for the wrapper, but because the content is dynamic this is not possible.
Another solution would be to use position absolute on element C, but this seems very hacky, I'm hoping to find a more elegant solution.
Here is a framework for the code:
.wrapper {
display: flex;
flex-direction: column;
}
#media(min-width: 800px) {
.wrapper {
flex-direction: row;
flex-wrap: wrap;
}
}
.section {
display: flex;
justify-content: center;
align-items: center;
font-size: 36px;
}
.section-a {
background: green;
height: 200px;
}
#media(min-width: 800px) {
.section-a {
flex-basis: 33%;
}
}
.section-b {
background: yellow;
height: 400px;
}
#media(min-width: 800px) {
.section-b {
flex-basis: 66%;
}
}
.section-c {
background: blue;
height: 200px;
}
#media(min-width: 800px) {
.section-c {
flex-basis: 33%;
}
}
<div class="wrapper">
<div class="section section-a">A</div>
<div class="section section-b">B</div>
<div class="section section-c">C</div>
</div>
Thanks for the help!
You can achieve this by using grid. I have simplified your code and removed unwanted css
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr;
grid-template-rows: [row1-start] auto [row2-start] auto [row2-end];
}
.section {
padding: 20px;
display: flex;
align-items: center;
}
.section-a {
height: 50px;
background-color: green;
}
.section-b {
grid-row: row1-start / row2-end;
grid-column: 2/-1;
background-color: yellow;
}
.section-c {
background-color: blue;
height: 180px;
}
<div class="wrapper">
<div class="section section-a">A</div>
<div class="section section-b">B</div>
<div class="section section-c">C</div>
</div>
Working fiddle here
Edit: it's an attempt, as I misunderstood OP's question. My answer has a given .wrapper height.
A solution using flex with the following properties:
order
flex-basis
This code applies for your desktop layout:
.wrapper {
width: 100%;
height: 100vh;
display: flex;
flex-flow: column wrap;
}
.section {
width: 50%;
border: 1px solid black;
box-sizing: border-box;
}
.section-a {
height: 25vh; // for example
}
.section-b {
order: 3;
flex-basis: 100%;
}
.section-c {
flex-grow: 1;
}
<div class="wrapper">
<div class="section section-a">A</div>
<div class="section section-b">B</div>
<div class="section section-c">C</div>
</div>
Can someone point me out how can I get a grid with Flexbox that is similar to the picture below. I have green column already done but have problem doing red section.
The problem is that I need to have an access to Flex Order just re-order it on mobile resolutions.
What I have already:
JSFiddle
HTML
* {
box-sizing: border-box;
}
main,
div {
display: flex;
padding: 1rem;
}
.desktop {
flex-direction: column;
flex-wrap: wrap;
height: 400px;
width: 100%;
}
.desktop div {
flex: 1;
}
div.orange {
background-color: #FFAD77;
width: 30%;
flex: 0 0 50%;
}
div.yellow {
flex: 0 0 100%;
width: 40%;
background-color: #FFE377;
}
div.purple {
flex: 0 0 50%;
width: 30%;
background-color: #FF77C8;
}
div.green {
background-color: green;
width: 30%;
}
#media(max-width: 480px) {
.desktop div {
flex: 1;
width: 100%;
}
div.orange {
order: 1;
}
div.yellow {
order: 2;
}
div.purple {
order: 3;
}
div.green {
order: 2;
}
}
<div class="desktop">
<div class="yellow">lorem1</div>
<div class="orange">lorem2</div>
<div class="purple">lorem3</div>
<div class="green">lorem4</div>
</div>
Please adjust the width, remove border and other things are per your requirement.
.redouter {
height: 200px;
border: 1px solid green;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.red {
background: red;
width: 50%;
min-height: 20px;
text-align: center;
color: white;
font-size: 30px;
}
.one {
border: 2px solid white;
}
.two {
border: 5px solid white;
min-height: 150px;
}
.three {
min-height: 144px;
border: 3px solid white;
}
.four {
min-height: 10px;
border: 3px solid white;
}
#media(max-width: 480px) {
.redouter {
height: 100%;
}
.red {
flex: 1;
width: 100%;
}
.one {
order: 1;
}
.two {
order: 2;
}
.three {
order: 3;
}
.four {
order: 2;
}
}
.desktop {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 300px;
width: 100%;
}
.yellow,
.green,
.purple,
.orange {
flex: 1;
}
div.orange {
background-color: #FFAD77;
width: 30%;
flex: 0 0 50%;
}
div.yellow {
flex: 0 0 100%;
width: 40%;
background-color: #FFE377;
}
div.purple {
flex: 0 0 50%;
width: 30%;
background-color: #FF77C8;
}
div.green {
background-color: green;
width: 30%;
}
#media(max-width: 480px) {
.desktop div {
flex: 1;
width: 100%;
}
div[orange] {
order: -1;
flex: 2;
}
div[yellow] {
flex: 5;
}
div[purple] {
flex: 1;
}
div[purple] {
flex: 6;
}
}
<div class="desktop">
<div class="yellow">lorem 1</div>
<div class="orange">lorem 2</div>
<div class="purple">lorem 3</div>
<div class="green">lorem 4</div>
</div>
<div class="redouter">
<div class="red one">1</div>
<div class="red two">2</div>
<div class="red three">3</div>
<div class="red four">4</div>
</div>
I need to have a layout that looks like this on mobile
-----
| 1 |
-----
| 2 |
-----
| 3 |
-----
And like this on desktop:
---------
| | 1 |
| 2 |---|
| | 3 |
| |----
| |
-----
I decided to use flexbox, my code so far:
<div class="row">
<div class="col-xl secound">2</div>
<div class="col-sm first">1<br>2<br>3<br>4</div>
<div class="col-xl third">3</div>
</div>
.row {
display: flex;
flex-flow: row wrap;
}
.col-sm,
.col-xl {
width: 100%;
}
.col-sm {
background: yellow;
}
.col-xl {
&.secound {
background: #ccc;
}
&.third {
background: #aaa;
}
}
#media (min-width: 700px) {
.col-sm {
width: 25%;
background: yellow;
order: 1;
}
.col-xl {
width: 75%;
&.secound {
background: #ccc;
order: 2;
}
&.third {
background: #aaa;
order: 3;
}
}
}
Unfortunately, I can't slide column "3" under "1". What should I do?
Codepen: http://codepen.io/tomekbuszewski/pen/PbprJP?editors=1100
You can try using float for desktop, and using flexbox with order set for mobile.
jsFiddle
.item-1 {background:aqua;}
.item-2 {background:gold;}
.item-3 {background:pink;}
.row {
overflow: hidden;
}
.item {
width: 50%;
}
.item-2 {
float: left;
}
.item-1,
.item-3 {
overflow: hidden;
}
#media (max-width: 768px) {
.row {
display: flex;
flex-direction: column;
}
.item {
width: auto;
float: none;
}
.item-1 {
order: -1;
}
}
<div class="row">
<div class="item item-2">2<br><br><br></div>
<div class="item item-1">1</div>
<div class="item item-3">3</div>
</div>
You could align .third on the right by using flex property justify-content.
You're CSS would look something like this:
.row{
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
}
.row > div{
flex: 0 0 50%;
}
For changing order you can use the order property:
.first{ order: 1; }
.second{ order: 2; }
.third{ order: 3; }
#media (min-width: 700px){
.first{ order: 2; }
.second{ order: 1; }
.third{ order: 3; }
}
Check the fiddle
On CSS-tricks you can find a great guide for using Flex properties.
There are few things I've given sizes too just for the sake of the demo but it will still work without the sizes.
You will need to give your container a size but that can be 100vh/100vw or even percentage rather than actual pixels.
body {
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 600px;
width: 100%;
}
.item-1,
.item-2,
.item-3 {
width: 100%;
font-size: 80px;
color: #fff;
text-align: center;
}
.item-1 {
line-height: 100px;
height: 100px;
background: #00bcd5;
}
.item-2 {
line-height: 200px;
height: 200px;
background: #8bc24a;
}
.item-3 {
line-height: 300px;
height: 300px;
background: #fec107;
}
#media (min-width: 700px) {
.item-1,
.item-2,
.item-3 {
width: 50%;
}
.item-1,
.item-3 {
order: 1;
}
.item-2 {
height: 100%;
line-height: 1em;
}
}
<div class="container">
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
</div>
Hope this is what you're looking for.
You could use float: right for all three elements instead. Together with the appropriate width definitions in media queries, this should work.
Grid:
/* Column */
.item {
width: 100%;
}
/* Wrap */
.row {
display: flex;
flex-flow: column wrap;
}
/* Responsive */
#media screen and (min-width: 700px){
.row {
flex-flow: row wrap;
justify-content: flex-end;
}
.item { width: 50%;}
.item-1 { order: 2; }
.item-2 { order: 1; }
.item-3 { order: 3; }
}
/* Custom style */
.item {
color: #fff;
display: block;
height: 200px;
text-align: center;
line-height: 200px;
font-size: 3rem;
}
.item-1 {
background: #00bcd5;
}
.item-2 {
background:#8bc24a;
}
.item-3 {
background:#fec107;
}
<div class="row">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
</div>
grid with hook:
/* Column */
.item {
width: 100%;
}
/* Wrap */
.row {
display: flex;
flex-flow: column wrap;
}
.sub-row {
display: none;
}
.item-1 { order: 1; }
.item-2 { order: 2; }
.item-3 { order: 3; }
/* Responsive */
#media screen and (min-width: 500px){
.row {
flex-flow: row wrap;
justify-content: flex-end;
}
.sub-row {
width: 50%;
display: flex;
flex-flow: column wrap;
}
.sub-row .item { width: 100%;}
.item { width: 50%;}
.hidden { display: none; }
.item-2 { order: 1; }
.sub-row { order: 2; }
}
/* Custom style */
.item {
color: #fff;
text-align: center;
line-height: 200px;
font-size: 3rem;
}
.item-1 {
background: #00bcd5;
}
.item-2 {
background:#8bc24a;
}
.item-3 {
background:#fec107;
}
<div class="row">
<div class="item item-2">2</div>
<div class="sub-row">
<div class="item item-1">1</div>
<div class="item item-3">3</div>
</div>
<div class="item hidden item-1">1</div>
<div class="item hidden item-3">3</div>
</div>
How about using absolute position?
In your media query change the .row class to this:
.row {
position: relative;
align-items: flex-end;
}
And your .item-2 to:
.item-2 { order: 1; position: absolute; top: 0; left: 0; }
/* Column */
.item {
width: 100%;
}
/* Wrap */
.row {
display: flex;
flex-flow: column wrap;
}
/* Responsive */
#media screen and (min-width: 700px){
.row {
position: relative;
align-items: flex-end;
}
.item { width: 50%;}
.item-1 { order: 2; }
.item-2 { order: 1; position: absolute; top: 0; left: 0; }
.item-3 { order: 3; }
}
/* Custom style */
.item {
color: #fff;
display: block;
text-align: center;
line-height: 200px;
font-size: 3rem;
}
.item-1 {
background: #00bcd5;
}
.item-2 {
background:#8bc24a;
}
.item-3 {
background:#fec107;
}
<div class="row">
<div class="item item-1">1</div>
<div class="item item-2">2
<br>2</div>
<div class="item item-3">3</div>
</div>
Revised Codepen