I am working on a responsive site and came across an interesting problem. I have some divs side by side. There could be anywhere from 2 to 6 or so of them. When the screen isn't wide enough to show all the content properly, the divs stack vertically. Simple enough to do with CSS.
The problem is, I need them to be in a different order depending on the layout. This is easy to do with 2 or 3 divs (Changing divs order based on width), but significantly more challenging when you add a fourth.
I could use position: absolute; and manually set the position, however this causes the parent to shrink and not contain them properly.
To make this even more complicated, I can't use JavaScript.
Working with two columns:
(untested)
HTML:
<div id="container">
<div class="column-half column-half-2">
First div on mobile, right div on desktop
</div>
<div class="column-half column-half-1">
Second div on mobile, left div on desktop
</div>
</div>
CSS:
.container {
width: 80%;
max-width: 1200px;
margin: 0 auto;
padding-bottom: 20px;
position: relative;
}
.column-half {
display: table-cell;
padding: 25px;
vertical-align: top;
width: 40%;
}
.column-half-1 {
float: left;
}
.column-half-2 {
float: right;
}
HTML, with 4 columns:
<div id="container">
<div class="column-quarter column-quarter-3">
First div on mobile, third div on desktop
</div>
<div class="column-quarter column-quarter-2">
Second div on mobile, second div on desktop
</div>
<div class="column-quarter column-quarter-1">
Third div on mobile, first div on desktop
</div>
<div class="column-quarter column-quarter-4">
Fourth div on mobile, fourth div on desktop
</div>
</div>
This is doable in CSS thanks to the wonderful flexbox spec. Using the order and flex-flow properties, we can achieve what you want. Unprefixed, IE11 and all evergreen browsers will support this. IE10 prefixes -ms-order and doesn't support flex-flow.
The solution takes into consideration all the constraints you listed:
Have a list of elements in a given order displayed as a row.
When the window is too small, change them to display in a column.
Change the order of the elements when they are displayed in a column.
Because of the limitations of Stack Snippets, you'll need to view the demo in Full page mode, and resize your browser to see the effect.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column; }
.five { order: 1; }
.four { order: 2; }
.three { order: 3; }
.two { order: 4; }
.one { order: 5 }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
Alternatively, here is a JSFiddle demo.
You can also simply use flex-flow: column-reverse without the order property assigned to each div, if you are so inclined against verbose CSS. The same demo restrictions apply; view this demo in full screen and resize the browser window accordingly.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column-reverse; }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
It's worth pointing out that flex-flow is a shorthand property encompassing both flex-direction and flex-wrap properties.
Related
As you can see in the snippet, I have 2 columns, however, I want to make it so that the red column goes under the blue one ( and they both take 100% of the parent width ) when the browser becomes less than 1200px.
Now if I were using 2 inline-block elements I would just create a media query that would make both elements block, however, now that I'm trying to use flexbox, I'm not sure how to do this.
.specific-image-container {
display: flex;
position: relative;
width: 100%;
}
.specific-image-column {
flex: 4;
background-color: blue;
}
.more-images-column {
flex: 1;
background-color: red;
}
.content {
height: 300px;
}
<div class="specific-image-container">
<div class="specific-image-column">
<div class='content'>s</div>
</div>
<div class="more-images-column">
<div class='content'>s</div>
</div>
</div>
Set flex-direction to column within a media query
#media all and (max-width: 1200px) {
.specific-image-container {
flex-direction: column;
}
}
I'm trying to create this structure using only flexbox.
This is how my html looks like.
<div class="container">
<div class="first_container"></div>
<div class="second_container"></div>
<div class="third_container"></div>
</div>
I know it's really basic problem if i could just change divs order or add additional wrapper for the first line. The problem is it have to stay as it is.
Basic dimensions:
1. first_container - should takes 100% minus third_container width
2. second_container - shoudl takes 100%
I am asking for some tips, because my hands are slowly falling.
You can use flexbox order property
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
}
.container div {
padding: 10px;
border: 5px solid #fff;
background: gray;
text-align: center;
}
.first_container {
width: 70%;
order: 1;
}
.second_container {
width: 100%;
order: 3;
}
.third_container {
width: 30%;
order: 2;
}
<div class="container">
<div class="first_container">1</div>
<div class="second_container">2</div>
<div class="third_container">3</div>
</div>
I'm trying to achieve a certain fluid layout where the content of each DIVs are centered vertically and horizontally. But, my middle row (A, B, C) keeps on having vertical and/or horizontal alignment issues.
The goal is to have it work like this:
Note: If there's a way I can have the option to set the Mobile layout's "C" area fluid as well (without having to change the HTML, just the CSS, so that I can test which option works best), that'd be a bonus!
Here's a snippet of the HTML:
<div class="page">
<div class="col col-top">top</div>
<div class="col col-mid">
<div class="col col-left">
<div class="centerBox"><div class='debugBox'></div></div>
</div>
<div class="col col-center">
<div class="centerBox"><div class='debugBox'></div></div>
</div>
<div class="col col-right">
<div class="centerBox"><div class='debugBox'></div></div>
</div>
</div>
<div class="col col-bottom">bottom</div>
</div>
I'm not sure if the "wrapper" DIVs with the "centerBox" class is really necessary (they're set as display: table-cell while each col class are set to display: table to behave like tables, but this causes issues to place those areas with position: absolute and % values for their left / right / top / bottom properties.
For instance, if the "C" area is set to display: table, this happens:
And if I change the "C" area to display: block;, then it fills that full center area, but...
... the horizontal and vertical alignment breaks inside of it.
Would using "Ghost" DIV elements (as discussed in this css-tricks article, "Centering in the Unknown" by Chris Coyier ) be any better to get the correct alignment?
Ok, this solution works without a framework, pure CSS using flexbox. As long as the layout is horizontal, C has a fixed width. When it is mobile, C takes up the whole width and has a variable height.
header,
footer {
padding: 10px;
background-color: lightblue;
}
main {
display: flex;
flex-direction: row;
}
main > div {
padding: 10px;
background-color: tomato;
flex-grow: 1;
min-height: 40px;
display: flex;
align-items: center;
}
main > div:nth-child(2) {
background-color: olive;
}
.fixed {
width: 400px;
}
#media (max-width: 768px) {
main {
flex-direction: column;
}
.fixed {
width: auto;
}
}
<header>Top</header>
<main>
<div>A</div>
<div class="fixed">C</div>
<div>B</div>
</main>
<footer>Bottom</footer>
Here is a pen (drag the border to see the mobile layout):
Codepen
Here are the styles for the code you have provided. The one thing to keep in mind is your middle column, being a fixed width, is what helps with the calc() function. 50% of HALF the width of the middle container. This will not work in IE 8 or less, so you'll have to write a JS solution if you care about those browsers.
.page {
width: 100%;
position: relative;
}
.col-top {
background: #0f0;
width: 100%;
height: 50px;
}
.page .col-mid {
width: 100%;
display: table;
}
.page .col-mid .col {
width: calc(50% - 250px);;
height: 100px;
background: #f00;
display: table-cell;
vertical-align: middle;
text-align: center;
}
.page .col-mid .col-center {
width: 500px;
background: #00f;
}
.debugBox {
display: inline-block;
width: 20px;
height: 20px;
background: #000;
vertical-align: middle;
}
.col-bottom {
clear: both;
height: 50px;
background: #0f0;
}
and a working example here:
https://jsfiddle.net/g45pwedd/
And you don't need some of the container elements, as you stated.
UPDATE
Sorry, forgot to add for responsive. I wasn't sure if you still needed vertical align for responsive or not. This solution removes vertical align, as I doubt it's needed on a mobile display anyways:
#media (max-width: 768px) {
.page .col-mid .col {
display: block;
width: 100%;
}
}
https://jsfiddle.net/g45pwedd/2/
In bootstrap 4
to center the childs horizontally, use bootstrap-4 class
justify-content-center
to center the childs vertically, use bootstrap-4 class
align-items-center
but remember don't forget to use d-flex class with these
it's a bootstrap-4 utility class, like so
<div class="d-flex justify-content-center align-items-center" style="height:100px;">
<span class="bg-primary">MIDDLE</span>
</div>
Note: make sure to add bootstrap-4 utilities if this code does not work
I am working on a responsive site and came across an interesting problem. I have some divs side by side. There could be anywhere from 2 to 6 or so of them. When the screen isn't wide enough to show all the content properly, the divs stack vertically. Simple enough to do with CSS.
The problem is, I need them to be in a different order depending on the layout. This is easy to do with 2 or 3 divs (Changing divs order based on width), but significantly more challenging when you add a fourth.
I could use position: absolute; and manually set the position, however this causes the parent to shrink and not contain them properly.
To make this even more complicated, I can't use JavaScript.
Working with two columns:
(untested)
HTML:
<div id="container">
<div class="column-half column-half-2">
First div on mobile, right div on desktop
</div>
<div class="column-half column-half-1">
Second div on mobile, left div on desktop
</div>
</div>
CSS:
.container {
width: 80%;
max-width: 1200px;
margin: 0 auto;
padding-bottom: 20px;
position: relative;
}
.column-half {
display: table-cell;
padding: 25px;
vertical-align: top;
width: 40%;
}
.column-half-1 {
float: left;
}
.column-half-2 {
float: right;
}
HTML, with 4 columns:
<div id="container">
<div class="column-quarter column-quarter-3">
First div on mobile, third div on desktop
</div>
<div class="column-quarter column-quarter-2">
Second div on mobile, second div on desktop
</div>
<div class="column-quarter column-quarter-1">
Third div on mobile, first div on desktop
</div>
<div class="column-quarter column-quarter-4">
Fourth div on mobile, fourth div on desktop
</div>
</div>
This is doable in CSS thanks to the wonderful flexbox spec. Using the order and flex-flow properties, we can achieve what you want. Unprefixed, IE11 and all evergreen browsers will support this. IE10 prefixes -ms-order and doesn't support flex-flow.
The solution takes into consideration all the constraints you listed:
Have a list of elements in a given order displayed as a row.
When the window is too small, change them to display in a column.
Change the order of the elements when they are displayed in a column.
Because of the limitations of Stack Snippets, you'll need to view the demo in Full page mode, and resize your browser to see the effect.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column; }
.five { order: 1; }
.four { order: 2; }
.three { order: 3; }
.two { order: 4; }
.one { order: 5 }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
Alternatively, here is a JSFiddle demo.
You can also simply use flex-flow: column-reverse without the order property assigned to each div, if you are so inclined against verbose CSS. The same demo restrictions apply; view this demo in full screen and resize the browser window accordingly.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column-reverse; }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
It's worth pointing out that flex-flow is a shorthand property encompassing both flex-direction and flex-wrap properties.
I need to convert a 3-column fixed width layout to a responsive one and have been frying my brain trying to understand all the various ways people are going about this. The column widths are roughly 22% - 56% - 22% of the container div width. When displaying in a smartphone context, I want columns 1 and 3 to appear together side by side taking up 50% of the screen width each, then column 2 (the main content) to appear below at 100% of width.
Can anyone advise the best way to go about achieving this? Do I need to swap columns 2 and 3 around to get them to flow the way I want them to? Or is there another way that works as well without having to go through and change the markup of the entire site? I would like to use CSS only solutions if possible. Thanks.
You can do this with media queries and floats. Using float: left and float: right you just need to set up your HTML properly. The trick is to float column 1 to the left and two and three to the right with three coming before two in your html:
FIDDLE
HTML
<div class="wrapper">
<div class="one"></div>
<div class="three"></div>
<div class="two"></div>
</div>
CSS
.one{
float: left;
background: red;
width: 22%;
height:100px;
}
.two{
float: right;
background: blue;
width: 56%;
height:100px;
}
.three{
float: right;
background: green;
width: 22%;
height:100px;
}
#media only screen and (max-width: 300px){
.one{
width: 50%
}
.two{
width: 100%
}
.three{
width: 50%
}
}
UPDATE
As Crispy-George posted you could use flexbox but it does have limited browser support and basically doesn't work with IE 9 and below:
FLEXBOX EXAMPLE
If you have to maintain a strict order on your columns, like:
<div class='box box-1'>Small box</div>
<div class='box box-2'>Yeah, I'm the big box</div>
<div class='box box-3'>Even Smaller box</div>
you can use flexbox to change the order of these boxes on your desired screen resolutions, however I believe it has no support for lower than IE9, but if you dont have to support older browsers, check out the demo here.
The markup:
<div class='container'>
<div class='box box-1'>Small box</div>
<div class='box box-2'>Yeah, I'm the big box</div>
<div class='box box-3'>Even Smaller box</div>
</div>
And the css stuff:
.container{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.box{
min-height: 200px;
font-size: 18px;
}
.box-1{
width: 25%;
background: red;
}
.box-2{
width: 60%;
background: teal;
}
.box-3{
width: 15%;
background: cyan;
}
#media all and (max-width: 768px){
.box-1{
-webkit-order: 1;
-ms-order: 1;
order: 1;
width: 50%;
}
.box-3{
-webkit-order: 2;
-ms-order: 2;
order: 2;
width: 50%;
}
.box-2{
-webkit-order: 3;
-ms-order: 3;
order: 3;
width: 100%;
}
}