How to wrap items in flexbox for smaller screens? - html

I'm trying to create a layout for different resize. I need to reach the result in these images here:
I have this code:
.container {
position: relative;
display: flex;
align-items: stretch;
}
.item {
background-color: black;
box-sizing: border-box;
padding: 20px;
flex: 2;
color: #fff;
}
.item:nth-child(2) {
background-color: grey;
flex: 1
}
.item:nth-child(3) {
background-color: green;
flex: 0.5;
}
#media screen and (max-width: 990px) {
.container {
height: auto;
display: table;
}
.item:nth-child(2) {
float: left;
}
.item:nth-child(3) {
float: right;
}
}
<section class="container">
<div class="item">
<h2>title1</h2>
<hr>You'll notice that even though this column has far more content in it, instead of the other columns ending early, they size themselves to meet the end of this column vertically.</div>
<div class="item">
<h2>title2</h2>
<hr>Normally, the only way to achieve this would be either a hack, or to set all boxes to min-height.
</div>
<div class="item">
<h2>title3</h2>
<hr>This is a column with not much content.
</div>
</section>
Here there's a codepen https://codepen.io/darudev/pen/pyBrzL
Problem is in 990px resize view, I don't find solution to create the same view as "mockup".
Is there someone that can help me or give me some suggestions?
Thank you.

You don't need the table and float properties in your code.
#media screen and (max-width: 990px) {
.container {
height: auto;
display: table;
}
.item:nth-child(2) {
float: left;
}
.item:nth-child(3) {
float: right;
}
}
The entire layout can be made with flexbox.
Here's the solution: When the screen resizes smaller than 990px, allow flex items to wrap and give the first item a 100% width, which forces the following items to the next line.
.container {
display: flex;
}
.item {
background-color: black;
box-sizing: border-box;
padding: 20px;
flex: 2;
color: #fff;
}
.item:nth-child(2) {
background-color: grey;
flex: 1;
}
.item:nth-child(3) {
background-color: green;
flex: 0.5;
}
#media screen and (max-width:990px) {
.container { flex-wrap: wrap; }
.item:first-child { flex-basis: 100%; }
}
<section class="container">
<div class="item">
<h2>title1</h2>
<hr>You'll notice that even though this column has far more content in it,
instead of the other columns ending early, they size themselves to meet the end
of this column vertically.</div>
<div class="item">
<h2>title2</h2>
<hr>Normally, the only way to achieve this would be either a hack, or to set
all boxes to min-height.</div>
<div class="item">
<h2>title3</h2>
<hr>This is a column with not much content.
</div>
</section>
revised codepen

Related

Responsive NavBar like StackOverflow

I am trying to create a responsive navigation bar, similar to the one on Stack Overflow. I have attached an image of the layout I'm trying to achieve.
For simplicity, I added some values to make it easier to follow. There is the outer div that encapsulates the whole page, outer-wrapper and the main div that encapsulates the main content (navigation bar, main content, and footer), main-wrapper.
Now suppose that outer-wrapper is 1000px wide and main-wrapper is 800px wide, then there is 100px of buffer on the left and right side. When the window shrinks, I want the buffer to be used up before any of the main content changes.
CSS
.outer-wrapper {
width: 100%;
}
.main-wrapper {
width: 800px;
display: flex;
flex-direction: column;
margin-left: auto;
margin-right: auto;
position: relative;
}
.nav-home {
position: fixed;
top: -30px;
left: -30px;
height: 60px;
width: 100%;
padding: 20px 20px 0px 20px;
display: flex;
justify-content: space-around;
}
}
HTML
<div class='outer-wrapper'>
<div class='main-wrapper'>
<div class='nav-bar'>...</div>
<div class='main-content'>...</div>
<div class='footer'>...</div>
</div>
</div>
The problem is when the window shrinks to match the width of main-wrapper at 800px, there is still a left and right margin in the navigation bar. How would I ensure the width of the navigation bar matches the width of the main content and footer when the left and right margin is shrunk to 0?
Thanks.
I stripped out some of your styles from the .nav-bar class and it seems to be performing as you require - am I missing something?
I've added colours to help visualise the resizing.
.outer-wrapper {
background-color: yellow;
width: 100%;
}
.main-wrapper {
background-color: blue;
width: 800px;
display: flex;
flex-direction: column;
margin-left: auto;
margin-right: auto;
position: relative;
}
.nav-bar {
background-color: red;
justify-content: space-around;
}
.main-content {
background-color: green;
}
.footer {
background-color: purple;
}
<div class='outer-wrapper'>
<div class='main-wrapper'>
<div class='nav-bar'>Nav Bar</div>
<div class='main-content'>Main Content</div>
<div class='footer'>Footer</div>
</div>
</div>
.outer-wrapper {
width: 100%;
}
.main-wrapper {
width: 800px;
display: flex;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
margin: 0 auto;
}
.main-wrapper > * {
padding: 10px;
flex: 1 100%;
}
.nav-bar {
background: tomato;
}
.footer {
background: lightgreen;
}
.main-content {
background: deepskyblue;
}
.aside-1 {
background: gold;
}
.aside-2 {
background: hotpink;
}
#media all and (min-width: 600px) {
.aside {
flex: 1 0 0;
}
}
#media all and (min-width: 800px) {
.main-content {
flex: 3 0px;
}
.aside-1 {
order: 1;
}
.main-content {
order: 2;
}
.aside-2 {
order: 3;
}
.footer {
order: 4;
}
}
body {
padding: 2em;
}
<div class="outer-wrapper">
<div class="main-wrapper">
<nav class="nav-bar">Navbar</nav>
<main class="main-content">content</main>
<aside class="aside aside-1">aside 1</aside>
<aside class="aside aside-2">aside 2</aside>
<footer class="footer">footer</footer>
</div>
</div>
this is the code that I made, hopefully it will help you and what you expect

Responsive CSS: shift middle div rows to a separate column after reaching media query break point

I am using CSS media queries to create a responsive layout.
In my current HTML layout I use flexbox to align rows of divs:
<div id="page">
<div id="div-1">DIV 1</div>
<div id="div-2">DIV 2</div>
<div id="div-3">DIV 3</div>
<div id="div-4">DIV 4</div>
</div>
and CSS:
#page {
display: flex;
flex-direction: column;
align-items: center;
}
[id^="div-"] {
border: 1px solid #ccc;
margin-bottom: 10px;
width: 50vw;
}
#div-1 {
height: 50px;
}
#div-2 {
height: 70px;
}
#div-3 {
height: 150px;
}
#div-4 {
height: 100px;
}
Here is Jsfiddle for you to tinker with.
It is what I am after for a smaller viewports, but would like to switch things around on the next media query break point to have 2 middle divs to shift to a separate column on the right like this:
How do I achieve that? It is pretty obvious for me how to shift last few div rows to another column, but not sure how to tackle the middle rows...
Is there a way to do it by using flexbox or grid?
Another possible solution is to use the order-property in combination with Flexbox (drawback: you'll need a tiny bit of extra html and set the height of the #page container; advantages: flexible div heights and gap sizes):
#page {
display: flex;
flex-direction: column;
align-items: center;
}
[id^="div-"] {
border: 1px solid #ccc;
margin-bottom: 10px;
width: 50vw;
}
#div-1 {
height: 50px;
background: lightgreen;
}
#div-2 {
height: 70px;
background: lightyellow;
}
#div-3 {
height: 150px;
background: lightcoral;
}
#div-4 {
height: 100px;
background: lightblue;
}
#media (max-width: 1000px) {
#page {
flex-wrap: wrap;
height: 300px;
}
#small-screen-spacer {
order: 3;
align-self: stretch;
flex: 1 0 100%;
margin-right: 10px;
}
#div-1 {
order: 1;
}
#div-2 {
order: 4;
}
#div-3 {
order: 5;
}
#div-4 {
order: 2;
}
}
<div id="page">
<div id="div-1">DIV 1</div>
<div id="div-2">DIV 2</div>
<div id="div-3">DIV 3</div>
<div id="div-4">DIV 4</div>
<div id="small-screen-spacer"> </div>
</div>
The #small-screen-spacer will fill the entire available vertical space, so that all elements that come after the spacer (defined by the order property) are moved to the second column. Additionally you can set the desired gap between the two columns by setting margin-right on the spacer to your desired value.
Fiddle

Flex-wrapping without nested divs

I'm trying to make a horizontal card using flexbox without having nested divs.
For example, what I have right now is this:
.card {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.card-img {
width: 37%;
}
.card-content {
width: 63%;
}
<div class='card'>
<div class='card-img'>
<img src='example' />
</div>
<div class='card-content'>
<div class='card-number'>
</div>
<div class='card-type'>
</div>
</div>
</div>
This layout works for now, but when the viewport resizes, I want the horizontal card to change into a vertical one (which it already does). However, I want to re-order the card-img, card-number, and card-type using flex order.
How could I get this same horizontal layout while using this type of div layout?
Edit:
Sorry for the confusing wording, what I was aiming to do was to create a horizontal layout that works like the image except with 3 separate divs, not 2 divs with 1 being a nested div. Sorry!
.card {
display: flex;
}
.card-img {
flex: 0 0 37%;
border: 1px dashed red;
}
.card-number {
flex: 0 0 30%;
border: 1px dashed red;
}
.card-type {
flex: 1 0 30%;
border: 1px dashed red;
}
img {
width: 100%;
}
.card > div {
display: flex;
align-items: center;
justify-content: center;
}
#media (max-width: 500px) {
.card { flex-direction: column; }
.card-img { order: 3; }
.card-number { order: 2; }
.card-type { order: 1; }
}
<div class='card'>
<div class='card-img'>
<img src="http://i.imgur.com/60PVLis.png">
</div>
<div class='card-number'>555</div>
<div class='card-type'>Orange</div>
</div>
https://jsfiddle.net/7y8sarwn/

Re-sizing and re-ordering elements between desktop and mobile layouts

I'd like to achieve the following with CSS only (left is mobile layout, right is desktop after breakpoint):
The challenge here obviously is that from a float point of view the element order changes: on mobile the green item is the second, but on desktop it's the first.
Is this possible to achieve with pure CSS? Possibility would be flex-box but I don't have enough experience to recreate this layout.
#container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 400px; /* 1 */
}
.box {
width: 50%;
}
.box1 {
background-color: lightgreen;
height: 400px;
}
.box2 {
background-color: orangered;
height: 200px;
}
.box3 {
background-color: aqua;
height: 200px;
}
#media (max-width: 600px) {
#container { height: auto; } /* 2 */
.box { width: 100%; }
.box2 { order: -1; } /* 3 */
}
/* purely decorative styles */
.box {
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.5em;
}
* { box-sizing: border-box; }
<div id="container">
<div class="box box1"><span>1</span></div>
<div class="box box2"><span>2</span></div>
<div class="box box3"><span>3</span></div>
</div>
jsFiddle
Notes:
Without a fixed height in a column wrap container, flex items don't know where to wrap. So, for your larger screen, define a height which forces the second item to a new column.
Now you're in a mobile layout and wrapping is no longer necessary. The container needs to be twice the height of the desktop layout. Release the height.
Tell the red box to re-position itself first on the list. (The initial order value for flex items is 0.)
Yes you can do this if you can set fixed height on flex-container. You just need to use flex-direction: column and flex-wrap: wrap and then change order with media-queries.
.content {
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.a {
height: 200px;
background: #00FF02;
}
.b {
height: 100px;
background: red;
}
.c {
height: 100px;
background: blue;
}
#media(min-width:768px) {
.content {
height: 200px;
}
.content > div {
width: 50%;
}
}
#media(max-width:768px) {
.b {
order: -1;
}
}
<div class="content">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
</div>
There is also no-flex solution, fiddle (just replace media-query min-width with whatever breakpoint you consider phone width ends):
HTML:
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
CSS:
div {
width: 50%;
}
.div1 {
background-color: red;
float: right;
height: 200px;
}
.div2 {
background-color: green;
float: left;
height: 400px;
}
.div3 {
background-color: blue;
float: right;
height: 200px;
}
#media (max-width: 500px) {
.div1, .div2, .div3 { width: 100%;}
}

DIV with float right over DIV with float left

Hi I have a navigation div, which has a div on the bottom of it. This div has two other divs "DIV 1" and "DIV 2" (see on picture). Now I the navigation is closed on a tablet device, so I would show the second div which contains float: right over the first div which contains float: left, like in the picture. How can I do this? Now the first div is over the second. Thanks.
You can do this with Flexbox and media queries just change order of second element to order: -1 , here is Fiddle
.nav {
height: 200px;
display: flex;
align-items: flex-end;
border: 1px solid black;
}
.one {
background: #5B9BD5;
}
.two {
background: #FF0000;
}
.div {
flex: 1;
padding: 10px 0;
border: 1px solid black;
margin: 5px;
box-sizing: border-box;
}
#media(max-width: 480px) {
.nav {
flex-direction: column;
align-items: normal;
justify-content: flex-end;
}
.div {
flex: 0 0 50px;
}
.two {
order: -1;
}
}
<div class="nav">
<div class="div one">1</div>
<div class="div two">2</div>
</div>
You can use media queries for that purpose.
You can just manipulate your divs at some point to change their style.
#media (max-width: 600px) {
#someElement {
float: left;
}
}
You can try the following, along with media queries to remove the float at 800px:
JSFiddle: https://jsfiddle.net/7ws3m9Lx/
CSS:
.div1,.div2 { width: 50%; }
.div1 { float: left; }
.div2 { float: right; }
#media screen and (min-width: 0) and (max-width: 800px){
.div1,.div2 { float: none; width: 100%; }
}
HTML:
<div class="parent">
<div class="div2">DIV2</div>
<div class="div1">DIV1</div>
</div>