change block order with flex - html

How to do this kind of markup? So when the resolution is lower than 640px the container number 2 goes to the bottom.
I know that I should use #media (max-width:600px) {}
but I don't really understand how to get the block #2 to bottom from "column right"
Thanks
My example fiddle is https://jsfiddle.net/benderlio/tewzvLxf/3/
#container {
display: flex;
}
.column.left {
width: 60%;
flex: 0 0 1;
background-color: red;
}
.column.right {
padding-top: 30px;
text-align: center;
width: 40%;
flex: 0 0 1;
}
.box {
border: 1px solid red;
margin: 20px;
padding: 20px;
}
<div id="container">
<div class="column left">
</div>
<div class="column right">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
</div>

I would use grid with a media query and removing the column divs:
* {
box-sizing: border-box;
}
#container {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas:
"a b"
"a c"
"a d";
}
.box {
border: 1px solid red;
margin: 20px;
padding: 20px;
}
.box1 {
grid-area: a;
}
.box2 {
grid-area: b;
}
.box3 {
grid-area: c;
}
.box4 {
grid-area: d;
}
#media (max-width:640px) {
/* adding the commented out areas will allow box1 to keep it's height like in your images so there is a space below box 4 */
#container {
/* grid-template-rows: 1fr 1fr 1fr; */
grid-template-areas:
"a b"
"a d"
/* "a ." */
"c c";
}
}
<div id="container">
<div class="box box1">
1
</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
<div class="box box4">4</div>
</div>

You can do it without changing your structure, like this
#media only screen and (max-width: 640px) {
#container {
flex-direction: column-reverse;
}
}
You can set the flex-direction to have a reverse outcome on columned box.
EDIT
So after the confusion was set out, this is the least I can think of to closely produce what you want. You need to set the container's position to be relative and set the 2nd box's position to be absolute, but this rather a dirty way to do it.
body {}
#container {
display: flex;
}
.column.left {
width: 60%;
flex: 0 0 1;
background-color: red;
}
.column.right {
padding-top: 30px;
text-align: center;
width: 40%;
flex: 0 0 1;
}
.box {
border: 1px solid red;
margin: 20px;
padding: 20px;
}
#media only screen and (max-width: 640px) {
#container {
position: relative;
}
.box:nth-child(2) {
width: 90%;
position: absolute;
bottom: -100px;
left: -20px;
}
}
<div id="container">
<div class="column left">
1
</div>
<div class="column right">
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>

Related

Move central div to bottom on mobile

On desktop side columns will take a max-width of 175px leaving the center dynamic but on mobile I want to have a 2x1 grid. Also top columns will be 50% width but the height will depend on their content.
How could I move this center element to the bottom taking 100% of the width and leave the side columns next to each other taking each 50% of the width? I don't want to have hidden and duplicated elements.
#container {
display: flex;
}
.column.left,
.column.right {
max-width: 175px;
}
.column.center {
flex: 1;
text-align: center;
background-color: red;
}
.column.left,
.column.right {
text-align: center;
}
<body>
<div id="container">
<div class="column left">this is a long long long long label</div>
<div class="column center">center</div>
<div class="column right">short label</div>
</div>
</body>
You can use flex-wrap and the order property:
#container {
display: flex;
}
.column.left,
.column.right {
max-width: 175px;
}
.column.center {
flex: 1;
text-align: center;
background-color: red;
}
.column.left,
.column.right {
text-align: center;
}
#media all and (max-width: 600px) {
#container {
flex-wrap: wrap;
}
.column.left, .column.right {
max-width: none;
width: 50%;
}
.column.left {
order: 1;
}
.column.right {
order: 2;
}
.column.center {
order: 3;
width: 100%;
}
}
<body>
<div id="container">
<div class="column left">this is a long long long long label</div>
<div class="column center">center</div>
<div class="column right">short label</div>
</div>
</body>
You can do this easily enough with CSS grid and a media query. See the snippet below
#container {
display: grid;
grid-gap: 1rem;
grid-template-columns: var(--gridColTemplate, 1fr 1fr);
}
.column { text-align: center }
.column.left, .column.right { max-width: var(--sideMaxWidth, none) }
.column.center {
grid-column: var(--centerCol, 1/-1);
grid-row: var(--centerRow, 2);
background-color: red;
}
#media only screen and (min-width: 600px) {
:root {
--gridColTemplate: auto 1fr auto;
--centerCol: 2/3;
--centerRow: 1;
--sideMaxWidth: 175px;
}
}
<div id="container">
<div class="column left">this is a long long long long label</div>
<div class="column center">center</div>
<div class="column right">short label</div>
</div>

Why even the width fit? it still drop below

Try to make this:
Article and Aside are the same width
I don't know if the floating is wrong, or other. even I make the margin to 0, the Article box will drop below to Aside. And I don't why after I float the box, some of the borderlines will overlap but the footer won't. And there are some requirements.
The border is 3px.
The height of each box is 200px. Article and Aside are the same width
header,main,aside,article,footer{
background-color: lightblue;
border: 3px solid red;
height: 200px;
margin: 0;
}
header {
}
main {
width: 60%;
float: left;
}
aside{
width: 20%;
float: left;
}
article {
width: 20%;
float: right;
}
footer{
clear: both;
}
<header>
<h2>Header</h2>
</header >
<main>
<h2>Main</h2>
</main>
<aside>
<h2>Aside</h2>
</aside>
<article>
<h2>Article</h2>
</article>
<footer>
<h2>Footer</h2>
</footer>
A way is using grid:
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(3, 100px);
grid-gap: 20px;
}
.container div {
background-color: green;
border: solid red 1px;
}
.header {
grid-column: 1 / 6;
}
.main {
grid-column: 1 / 4;
}
.asid {
grid-column: 4 / 5;
}
.article {
grid-column: 5 / 6;
}
.footer {
grid-column: 1 / 6;
}
<div class="container">
<div class="header">header</div>
<div class="main">main</div>
<div class="asid">asid</div>
<div class="article">article</div>
<div class="footer">footer</div>
</div>
I would wrap the .main, .aside, .article blocks with a flex container.
.content {
display: flex;
gap: 10px;
}
.content {
display: flex;
gap: 10px;
}
.header,.main,.aside,.article,.footer{
background-color: lightblue;
border: 3px solid red;
height: 200px;
margin: 1em;
}
.main {
width: 60%;
}
.aside {
width: 20%;
}
.article {
width: 20%;
}
<div class="container">
<div class="header">HEADER</div>
<div class="content">
<div class="main">MAIN</div>
<div class="aside">ASIDE</div>
<div class="article">ARTICLE</div>
</div>
<div class="footer">FOOTER</div>
</div>
Try using flex
section{
display: flex;
}
main, aside, article{
height: 60px;
}
main{
flex-grow: 3;
background: red;
}
aside{
flex-grow: 1;
background: green;
}
article{
flex-grow: 1;
background: blue;
}
<section>
<main>main</main>
<aside>aside</aside>
<article>article</article>
</section>

reallocate items inside a div with responsive pages

I edited literally a few lines from the code taken from this question link
#wrap {
margin: 20px auto;
width: 80%;
}
.separator {
margin-top: 30px;
}
.row {
height: 30px; margin-bottom: 10px; background-color: green;
}
.left,
.right {
width: 33%; height: 30px; line-height: 30px;
display: inline-block;
text-align: center;
background-color: grey;
}
.left { margin-right: 10px; }
.right { margin-left: 10px; }
.center {
min-height: 30px; line-height: 30px;
text-align: center;
background-color: blue;
display: inline-block;
width: 30%;
}
<div id="wrap">
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
<div class="separator"></div>
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
</div>
when the sizes of the windows becomes too small, for example on mobile, it will become a mess. When this happens, how can I reallocate items vertically, one items for line, where the left will be the first, the center the second, and so.
I'm actually using this in React, just to know.
With display grid
You can use grid-template-areas on the grid parent selectors and grid-areas on the grid children selectors to place the elements in the order you want them to be displayed in the document despite their order in the HTML. You just change the grid properties in your media query.
#cont {
display: grid;
grid-auto-columns: 1fr;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"left-1 center-1 right-1"
"left-2 center-2 right-2";
gap: .5rem;
}
.box {
height: 100px;
background: blue;
margin: 0.5rem;
}
.left-1 {
grid-area: left-1;
}
.left-2 {
grid-area: left-2;
}
.center-1 {
grid-area: center-1;
}
.center-2 {
grid-area: center-2;
}
.right-1 {
grid-area: right-1;
}
.right-2 {
grid-area: right-2;
}
/* mobile */
#media screen and (max-width: 700px) {
#cont {
display: grid;
grid-auto-columns: auto;
grid-template-columns: auto;
grid-template-rows: auto;
grid-template-areas:
"left-1"
"left-2"
"center-1"
"center-2"
"right-1"
"right-2";
gap: .5rem;
}
}
<div id="cont">
<div class="left-1 box">left</div>
<div class="center-1 box">center</div>
<div class="right-1 box">right</div>
<div class="left-2 box">left</div>
<div class="center-2 box">center</div>
<div class="right-2 box">right</div>
</div>
You could do the following without using display grid and just adding a media query:
You however do not have control of re-ordering the elements like you do with grid or flex display, you could use box-ordinal-group to change the order of the elements, however it has been taken out of the standard with the introduction of flex - order and grid.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#cont {
width: calc(100% - 5px);
height: auto;
margin: 5px;
}
.box {
min-width: calc(33.3% - 5px);
height: 100px;
background: blue;
display: inline-block;
}
.box~.box {
margin-top: 5px;
}
#media screen and (max-width: 700px) {
#cont {
width: calc(100% - 5px);
margin: 5px;
}
.box {
min-width: calc(100% - 5px);
height: 100px;
}
}
<div id="cont">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
Using flex box with order
~ Change the visual order of your content when using Flexbox.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#cont {
display: flex;
flex-wrap: wrap;
}
.box {
min-width: calc(33.3% - 10px);
height: 100px;
background: blue;
display: inline-block;
margin: 5px;
}
#media screen and (max-width: 700px) {
#cont {
width: calc(100% - 10px);
margin: 5px;
}
.box {
min-width: calc(100% - 10px);
height: 100px;
}
.box:nth-of-type(1) {
order: 1;
}
.box:nth-of-type(2) {
order: 3;
}
.box:nth-of-type(3) {
order: 5;
}
.box:nth-of-type(4) {
order: 2;
}
.box:nth-of-type(5) {
order: 4;
}
.box:nth-of-type(6) {
order: 6;
}
}
<div id="cont">
<div class="box">left row 1</div>
<div class="box">center row 1</div>
<div class="box">right row 1</div>
<div class="box">left row 2</div>
<div class="box">center row 2</div>
<div class="box">right row 2</div>
</div>
You can use CSS Flexbox to position the items side-by-side on large screens, and use a media query to detect mobile devices and align the items vertically.
#wrap {
margin: 20px auto;
width: 80%;
}
.row {
display: flex;
}
/* mobile */
#media screen and (max-width: 700px) {
.row {
flex-direction: column;
}
}
.box {
width: 100%;
height: 100px;
background: blue;
margin: 0.5em;
}
<div id="wrap">
<div class="row">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
<div class="row">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
</div>

Need to make row-column-row using css flexbox

I want to make a row-column-row layout using css flexbox, here's the code:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
gap: 0.2%;
}
.box {
color: white;
background: royalblue;
min-height: 100px;
min-width: 100px;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid;
}
.b1 {
flex: 1 0 80%;
}
.b2 {
flex: 1 1 auto;
}
.b3 {
flex: 1 0 100%;
}
<div class="container">
<div class="box b1">1</div>
<div class="box b2">2</div>
<div class="box b3">3</div>
</div>
This is what I want:
And on mobile I want something like this:
But as you can see in the code, the column is not growing vertically and I cannot even use margins or gaps in between the divs.
Any suggestions will be appreciated. CSS-Grid solutions are also welcome.
A grid-based approach using a media query:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container {
display: grid;
grid-template-columns: 4fr 1fr;
grid-auto-rows: minmax(100px, auto);
grid-template-areas:
"b1 b2"
"b3 b2";
gap: 0.2%;
}
#media screen and (max-width: 480px) {
.container {
grid-template-columns: 1fr;
grid-template-areas:
"b1"
"b2"
"b3";
}
}
.box {
color: white;
background: royalblue;
min-height: 100px;
min-width: 100px;
border: 1px solid;
}
.b1 {
grid-area: b1;
}
.b2 {
grid-area: b2;
}
.b3 {
grid-area: b3;
}
<div class="container">
<div class="box b1">1</div>
<div class="box b2">2</div>
<div class="box b3">3</div>
</div>

CSS - Flex positioning with two separate parent divs [duplicate]

I'm trying to learn CSS Flexbox and found an impediment.
I have content that displays right and left on desktop screen sizes and for mobile, I have flex-direction: column
See the visual bellow:
Desktop:
Mobile:
This is the code to accomplish such:
<div class="container">
<div class="box box1">
<div class="a">a</div>
<div class="b">b</div>
</div>
<div class="box box2">
<div class="c">c</div>
<div class="d">d</div>
</div>
</div>
These are the flexbox styles:
.box {
color: white;
font-size: 100px;
text-align: center;
text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
padding: 10px;
width: 100vw;
}
.container {
display: flex;
height: 100vh;
}
.a, .b, .c, .d {
height: 50%;
}
#media all and (max-width: 500px) {
.container {
flex-direction: column;
}
.box {
height: 50vh;
}
}
When in mobile, how can I order the following divs to be displayed in columns (as is) however on the following order:
a
c
d
b
I can't seem to find a solution for that unfortunately.
I have a CodePen here the CSS lines that matter are from line 162 onward.
You can consider display:contents (https://caniuse.com/#feat=css-display-contents) on the .box element then you will be able to use order on the inner elements:
.box {
color: white;
font-size: 80px;
text-align: center;
text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
padding: 10px;
width: 100vw;
}
body {
margin:0;
}
.container {
display: flex;
height: 100vh;
background:blue;
}
.a,.b,.c,.d {
height: 50%;
border:2px solid;
}
#media all and (max-width: 500px) {
.container {
flex-direction: column;
}
.box {
display:contents;
}
.b {
order:2;
}
}
<div class="container">
<div class="box box1">
<div class="a">a</div>
<div class="b">b</div>
</div>
<div class="box box2">
<div class="c">c</div>
<div class="d">d</div>
</div>
</div>
display: contents causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself. This can be useful when a wrapper element should be ignored when using CSS grid or similar layout techniques.
If you are open to change the html you can do it like below:
.container > * {
color: white;
font-size: 80px;
text-align: center;
text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
padding: 10px;
border:2px solid;
box-sizing:border-box;
}
body {
margin:0;
}
.container {
display: flex;
flex-direction:column;
flex-wrap:wrap;
height: 100vh;
background:blue;
padding:10px;
box-sizing:border-box;
}
.a,.b,.c,.d {
height: 50%;
width:50%;
}
#media all and (max-width: 500px) {
.a,.b,.c,.d {
width:100%;
height:25%;
}
.b {
order:2;
}
}
<div class="container">
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
</div>
And with CSS grid:
.container > * {
color: white;
font-size: 80px;
text-align: center;
text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
padding: 10px;
box-sizing:border-box;
border:2px solid;
}
body {
margin:0;
}
.container {
display: grid;
grid-template-areas:
'a b'
'c d';
grid-template-columns:1fr 1fr;
grid-template-rows:1fr 1fr;
grid-gap:10px;
min-height: 100vh;
background:blue;
padding:10px;
box-sizing:border-box;
}
.a {
grid-area:a;
}
.b {
grid-area:b;
}
.c {
grid-area:c;
}
.d {
grid-area:d;
}
#media all and (max-width: 500px) {
.container {
grid-template-areas:
'a'
'c'
'd'
'b';
grid-template-columns:1fr;
grid-template-rows:1fr 1fr 1fr 1fr;
}
}
<div class="container">
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
</div>
If you order your divs as .a & .c in .box1 and .c & .d in .box 2, you can use column in .container for desktop, and column in .box in mobile + order within .box2:
.box {
color: white;
font-size: 100px;
text-align: center;
text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
padding: 10px;
width: 100vw;
display: flex; /* <-- */
}
.container {
display: flex;
height: 100vh;
flex-direction: column; /* <-- */
}
.a, .b, .c, .d {
height: 50%;
}
#media all and (max-width: 500px) {
.box {
height: 50vh;
flex-direction: column; /* <-- */
}
.box2 .d {
order: 0; /* <-- */
}
}
<div class="container">
<div class="box box1">
<div class="a">a</div>
<div class="c">c</div>
</div>
<div class="box box2">
<div class="b">b</div>
<div class="d">d</div>
</div>
</div>
Nuri Katsuki's comment is right. If the "abcd" divs are on the same level, you can use CSS order property to achieve the order you want on mobile.
Also, the flex-wrap: wrap makes the children flow into columns on desktop query
I've edited your sample to illustrate it:
.container {
color: white;
font-size: 100px;
text-align: center;
text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
width: 100vw;
display: flex;
height: 100vh;
flex-direction: column;
flex-wrap: wrap;
}
.a { background:#e67e22;}
.b { background:#e74c3c;}
.c { background:#9b59b6;}
.d { background:#34495e;}
.a, .b, .c, .d {
height: 50%;
width: 50%;
}
#media all and (max-width: 500px) {
.container {
height: auto;
}
.a, .b, .c, .d { width: 100%; }
.b {
order: 3;
}
}
<div class="container">
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
</div>
/* Some default styles to make each box visible */
html,body {
padding: 0;
margin: 0;
}
.container {
color: white;
font-size: 100px;
text-align: center;
text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
width: 100vw;
display: flex;
height: 100vh;
align-items: stretch;
flex-direction: column;
flex-wrap: wrap;
}
.a { background:#e67e22;}
.b { background:#e74c3c;}
.c { background:#9b59b6;}
.d { background:#34495e;}
.a, .b, .c, .d {
height: 50%;
width: 50%;
}
#media all and (max-width: 500px) {
.container {
height: auto;
}
.a, .b, .c, .d { width: 100%; }
.b {
order: 3;
}
}
<div class="container">
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
</div>