How do I wrap using flexbox and media queries? - html

I have a container with four boxes. The container all together should be the width of the window.
Above 720px, there should be one row of four boxes.
Below 720px, there should be two rows of two boxes.
Below 600px, there should be four rows of one box.
I'm confused what I should put in the media queries.
html,
body {
width: 100%;
height: 100%;
}
.container {
border: 1px solid black;
display: flex;
height: 100%;
width: 100%;
}
.column {
border: 1px solid red;
flex: 1;
}
#media (max-width: 720px) {
.container {
?
}
}
#media (max-width: 600px) {
.container {
?
}
}
<div class="container">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>

Set the flex items to wrap at your breakpoints.
Here's a fiddle demo.
.container {
display: flex;
flex-wrap: wrap;
height: 100vh;
}
.column {
flex: 1;
border: 1px solid black;
background-color: lightgray;
}
#media (max-width: 720px) {
.column {
flex-basis: 34%;
background-color: orange;
}
}
#media (max-width: 600px) {
.column {
flex-basis: 51%;
background-color: lightgreen;
}
}
body {
margin: 0;
}
<div class="container">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
Note that with flex-grow: 1 defined in the flex shorthand, there's no need for flex-basis to be exact (25%, 50%, 100%), which can result in unequal wrapping if you were to add margin space.
Since flex-grow will consume free space on the row, flex-basis only needs to be large enough to enforce a wrap. This will ensure plenty of space for margins, but not enough space for an extra item.

You could use grids to achieve this. If you name them like I did in the snippet, it is easy to alter the sequence of the columns.
.container {
display: grid;
grid-auto-rows: 200px;
grid-auto-columns: auto;
grid-template-areas:
"column1 column2 column3 column4";
border: 1px solid black;
width: 100%;
height: 100%;
}
.column {
display: flex;
}
.column1 {
grid-area: column1;
background-color: red;
}
.column2 {
grid-area: column2;
background-color: yellow;
}
.column3 {
grid-area: column3;
background-color: green;
}
.column4 {
grid-area: column4;
background-color: blue;
}
#media (max-width: 720px) {
.container {
grid-template-areas:
"column1 column2"
"column3 column4";
}
}
#media (max-width: 600px) {
.container {
grid-template-areas:
"column1"
"column2"
"column3"
"column4";
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="container">
<div class="column column1"></div>
<div class="column column2"></div>
<div class="column column3"></div>
<div class="column column4"></div>
</div>
</body>
</html>
More info about grids in CSS here

Related

CSS Flexbox MediaQuery - Can't get divs side by side with media query... or at all for that matter

I'm a rookie, so... you know... sorry.
I have 5 sections. I would like them each to stack vertically when screen width is less than 640px. When screen width is more than 640px, I'd like divs 3 and 4 to be on the same row. One tangent problem that tells me I don't understand how this works. When I change div.flex-container {flex-direction: column} to {flex-direction: row}, just as an experiment, nothing changes. I would have guessed all of the divs would appear on the same row. Why does this not happen? and what do I need to do to get my media query to work?
body {
margin: 0px !important;
}
.flex-parent-element {
display: flex;
flex: 1;
}
div.flex-container {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
height: 100px;
align-items: center;
}
#media (max-width: 640px) {
.desktop {
display: flex;
flex-direction: row;
align-items: center;
}
}
div#HEADER {
background-color: #00b7eb;
}
div#HERO {
background-color: #ff0000;
}
div#CONTENT {
background-color: #00ff00;
}
div#SIDEBAR {
background-color: #800080;
}
div#FOOTER {
background-color: #444444;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="src/style.css">
</head>
<body>
<div id="HEADER" class="flex-container" id="HEADER"> HEADER </div>
<div id="HERO" class="flex-container" id="HERO"> HERO </div>
<div id="CONTENT" class="flex-container" class="desktop">CONTENT</div>
<div id="SIDEBAR" class="flex-container" class="desktop">SIDEBAR</div>
<div id="FOOTER" class="flex-container" > FOOTER </div>
</body>
</html>
You have to put a parent div .desktop between the children divs #CONTENT and #SIDEBAR to apply the flex-direction: column and flex-direction: row effects.
Also, don't forget to use the !important property when the screen resolution changes. (to force a CSS update).
Here, the .desktop will change for max resolution > 640px, that's why I'm using #media (min-width: 640px)
body {
margin: 0px !important;
}
.flex-parent-element {
display: flex;
flex: 1;
}
div.flex-container {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
height: 100px;
align-items: center;
}
#media (min-width: 640px) {
.desktop {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
}
div#CONTENT {
width:100%;
}
}
div#HEADER {
background-color: #00b7eb;
}
div#HERO {
background-color: #ff0000;
}
div#CONTENT {
background-color: #00ff00;
}
div#SIDEBAR {
background-color: #800080;
}
div#FOOTER {
background-color: #444444;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="src/style.css">
</head>
<body>
<div id="HEADER" class="flex-container" id="HEADER"> HEADER </div>
<div id="HERO" class="flex-container" id="HERO"> HERO </div>
<div class="desktop">
<div id="CONTENT" class="flex-container">CONTENT</div>
<div id="SIDEBAR" class="flex-container">SIDEBAR</div>
</div>
<div id="FOOTER" class="flex-container" > FOOTER </div>
</body>
</html>

Use of Flexbox and avoid justification

I have a problem with this flexbox. I would like to place 3 div per row. For this reason I've used flexbox.
The first 3 divs are fine and have 33% width, while the divs 4 and 5 get 50%.
Is there any trick to do the job?
Thanks
* {
box-sizing: border-box;
}
.flex-container {
display: flex;
flex-wrap: wrap;
font-size: 30px;
text-align: center;
}
.flex-item-left {
background-color: #f1f1f1;
padding: 10px;
flex: 33%;
}
.flex-item-center {
background-color: dodgerblue;
padding: 10px;
flex: 33%;
}
.flex-item-right {
background-color: red;
padding: 10px;
flex: 33%;
}
/* Responsive layout - makes a one column-layout instead of a two-column layout */
#media (max-width: 800px) {
.flex-item-right, .flex-item-left {
flex: 100%;
}
}
<h1>Responsive Flexbox</h1>
<p>In this example, we change the percentage of flex to create different layouts for different screen sizes.</p>
<p><b>Resize the browser window to see that the direction changes when the
screen size is 800px or smaller.</b></p>
<div class="flex-container">
<div class="flex-item-left">1</div>
<div class="flex-item-center">2</div>
<div class="flex-item-right">3</div>
</div>
<div class="flex-container">
<div class="flex-item-left">4</div>
<div class="flex-item-center">5</div>
</div>
flex: 33% is short for flex: 1 1 33% meaning that the container will grow or shrink if needed with a basis of 33%. Since there is space left, the containers will grow to 50%.
To fix this, replace the flex property with 0 1 33% meaning that it cannot grow and will not be larger than 33%.
You can simplify with display: grid; and it will give you a little more control over your layout.
* {
box-sizing: border-box;
}
.row-1 {
grid-column: 1 / -1;
grid-gap: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
flex-direction: column;
text-align: center;
}
.row-2 {
grid-column: 1 / -1;
grid-gap: 0;
display: grid;
grid-template-columns: repeat(2, 50%);
flex-direction: column;
text-align: center;
}
.flex-container {
display: flex;
flex-wrap: wrap;
font-size: 30px;
text-align: center;
}
.flex-item-left {
background-color: #f1f1f1;
padding: 10px;
}
.flex-item-center {
background-color: dodgerblue;
padding: 10px;
}
.flex-item-right {
background-color: red;
padding: 10px;
}
/* Responsive layout - makes a one column-layout instead of a two-column layout */
#media (max-width: 800px) {
.row-1, .row-2 {
display: flex;
flex-direction: column;
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no" />
</head>
<body>
<h1>Responsive Flexbox</h1>
<p>In this example, we change the percentage of flex to create different layouts for different screen sizes.</p>
<p><b>Resize the browser window to see that the direction changes when the
screen size is 800px or smaller.</b></p>
<div class="row-1">
<div class="flex-item-left">1</div>
<div class="flex-item-center">2</div>
<div class="flex-item-right">3</div>
</div>
<div class="row-2">
<div class="flex-item-left">4</div>
<div class="flex-item-center">5</div>
</div>
</body>
</html>

Any Flexbox Better dynamic Solution : for Responsive layout design

I have to achieve below three layout - in a responsive way.
1st layout - default layout
2nd Layout - with "min-width:600px"
3rd Layout - with "min-width:700px"
Above three layout I have already achieved.
I have mentioned height "200px" for dark-blue and red colored divs, which is actually somewhat fixed. If at a later stage, content in it increases (hypothetically) - the design layout will fail I think.
Is there any better way of doing it dynamically and my design doesn't fail if content increases.
I tried to think of it but couldn't get any.
Just Asked this question for better learning.
I wanted to achieve it by using flexbox. Any other way is also appreciated.
Can someone point in right direction?
I have added my HTML and css code.
/* default color of background */
.red {
background: red;
}
.dark-blue {
background: darkblue;
}
.light-blue {
background: lightblue;
}
.green {
background: green;
}
/* Container properties */
.container {
/* mentioned 100% so that element inside takes full width i.e with id = container2 */
width: 100%;
display: flex;
flex-wrap: wrap;
}
.box {
width: 100%;
height: 100px;
}
/* Responsive design proprties */
#media screen and (min-width: 600px) {
.dark-blue {
width: 50%;
height: 200px;
}
#container2 {
width: 50%;
height: 50%;
}
}
#media screen and (min-width: 700px) {
.dark-blue,
.red {
height: 200px;
}
.dark-blue {
width: 25%;
order: 2;
}
#container2 {
width: 50%;
flex-wrap: wrap;
}
.red {
width: 25%;
order: -1;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Layout shifter</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="container">
<div class="box dark-blue"></div>
<div class="container" id="container2">
<div class="box light-blue"></div>
<div class="box green"></div>
</div>
<div class="box red"></div>
</div>
</body>
</html>
Flexbox has some advanatges and some downsides. one of the downsides is, that it is only good in controlling either height or width. Not both.
If you need to control both, CSS-Grid is the way to go.
Use grid-template-areas to place the divs. Its the equivalent to flex order.
body {
margin: 0;
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
display: grid;
}
.dark-blue {
grid-area: dark-blue;
background-color: darkblue;
}
.light-blue {
grid-area: light-blue;
background-color: lightblue;
}
.green {
grid-area: green;
background-color: green;
}
.red {
grid-area: red;
background-color: red;
}
#media only screen
and (max-width: 600px) {
body {
grid-template-areas:
"dark-blue"
"light-blue"
"green"
"red"
}
}
#media only screen
and (max-width: 600px) {
body {
grid-template-areas:
"dark-blue"
"light-blue"
"green"
"red";
}
}
#media only screen
and (min-width: 601px)
and (max-width: 700px) {
body {
grid-template-areas:
"dark-blue light-blue"
"dark-blue green"
"red red";
}
}
#media only screen
and (min-width: 701px) {
body {
grid-template-areas:
"red light-blue light-blue dark-blue"
"red green green dark-blue"
}
}
<div class="dark-blue"></div>
<div class="light-blue"></div>
<div class="green"></div>
<div class="red"></div>

Make side bars reducing with max-width by degrees

How to make side parts of web page reduce they width with reducing width of whole page by degrees?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.container {
display: grid;
grid-template-columns: 10% 80% 10%;
min-height: 100vh;
}
.side-right {
background: red;
}
.side-left {
background: blue;
}
.main {
background: green;
}
#media screen and (max-width: 1000px) {
.container {
grid-template-columns: 0 100% 0;
}
}
</style>
</head>
<body>
<div class="container">
<div class="side-right">
</div>
<div class="main">
</div>
<div class="side-left">
</div>
</div>
</body>
</html>
In example below after max-width = 1000px side elements are dissapearing instantly, but I want to make them reducing they width reacting by every pixel changed on max-width. How to make it?
If I understand your requirement correctly...change the initial grid-template-columns to
grid-template-columns: 1fr minmax(1000px, 8fr) 1fr;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
::before,
::after {
box-sizing: inherit;
}
.container {
display: grid;
grid-template-columns: 1fr minmax(1000px, 8fr) 1fr;
min-height: 100vh;
}
.side-right {
background: red;
}
.side-left {
background: blue;
}
.main {
background: green;
}
#media screen and (max-width: 1000px) {
.container {
grid-template-columns: 0 1fr 0;
}
}
<div class="container">
<div class="side-right">
</div>
<div class="main">
</div>
<div class="side-left">
</div>
</div>
You can animate all with flex-box and just by changing some of your css.
.container {
display: flex;
min-height: 100vh;
flex-direction: row-reverse;
}
.side-right {
background: red;
width: 100%;
}
.side-left {
background: blue;
width: 100%;
}
.main {
background: green;
min-width: 600px;
}
Thats just a basic example. Consider reading more about flex-box.
Try to add min-with: 50px; to .side-right and .side-left
And then give them both an z-index: 1;
So they wont lay under your main
Hope that helps

Opinions Needed for a Responsive Four-Column Layout Flexbox

I created a responsive four-column layout by using a mobile-first approach. The smallest screen shows 1 column, the larger screen 2 columns, and the largest screen 4 columns.
It seems to work so far, but I'd like you to take a look at my code and tell me if there's anything wrong with my approach. I would be grateful for your opinions.
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FlexBox Test</title>
<style>
:root {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
/* mobile phone */
.flex-container {
display: flex;
flex-wrap: wrap;
max-width: 1400px;
margin: 0 auto;
border: 1px solid red;
padding: 1em;
}
.flex-item-1 {
background: indianred;
}
.flex-item-2 {
background: blue;
}
.flex-item-3 {
background: tomato;
}
.flex-item-4 {
background: coral;
}
.flex-item {
flex: 100%;
height: 100px;
}
/* tablet */
#media screen and (min-width: 640px) {
.flex-item {
flex: calc(50% - 1em);
}
.flex-item:nth-child(2n) {
margin-left: 1em;
}
}
/* desktop */
#media screen and (min-width: 960px) {
.flex-item {
flex: calc(25% - 1em);
}
.flex-container > * + * {
margin-left: 1em;
}
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item flex-item-1">
1
</div>
<div class="flex-item flex-item-2">
2
</div>
<div class="flex-item flex-item-3">
3
</div>
<div class="flex-item flex-item-4">
4
</div>
</div>
</body>
</html>
If you want remove calc from the css you can do something like that.
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FlexBox Test</title>
<style>
:root {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
/* mobile phone */
.flex-container {
display: flex;
flex-wrap: wrap;
max-width: 1400px;
margin: 0 auto;
border: 1px solid red;
padding: 1em;
}
.flex-item-1 {
background: indianred;
}
.flex-item-2 {
background: blue;
}
.flex-item-3 {
background: tomato;
}
.flex-item-4 {
background: coral;
}
.flex-item {
flex: 100%;
height: 100px;
}
/* tablet */
#media screen and (min-width: 675px) and (max-width: 960px) {
.flex-item {
flex: 1 0 19em;
}
.flex-item:nth-child(2n) {
margin-left: 1em;
}
}
/* desktop */
#media screen and (min-width: 960px) {
.flex-item {
flex: 1 0;
}
.flex-container > * + * {
margin-left: 1em;
}
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item flex-item-1">
1
</div>
<div class="flex-item flex-item-2">
2
</div>
<div class="flex-item flex-item-3">
3
</div>
<div class="flex-item flex-item-4">
4
</div>
</div>
</body>
</html>
However to keep the margin as you have on your initial example, I have to change #media screen and (min-width: 675px) and (max-width: 960px) for tablet screen. If not, three block appears on the first line for specific browser width (not the same behaviour as you want).
What do you think about that ?