I noticed an interesting difference between Firefox and Chrome in the following flexbox layout:
html,
body {
height: 100%;
min-height: 100%;
margin: 0px;
display: flex;
flex-direction: column;
}
header {
border: 1px solid #D3D3D3;
flex: 0 1 auto;
}
.row {
display: flex;
flex-direction: column;
flex: 1 0 auto;
flex-wrap: wrap;
}
.tab1 {
flex: 1 0 48%;
position: relative;
margin: 0.5em;
background-color: orange;
}
.tab2 {
flex: 1 0 48%;
position: relative;
margin: 0.5em;
background-color: blue;
}
.tab3 {
flex: 1 0 48%;
position: relative;
margin: 0.5em;
border: 1px solid lightgray;
background-color: green;
}
.tab4 {
flex: 1 0 48%;
position: relative;
margin: 0.5em;
border: 1px solid lightgray;
background-color: yellow;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<header>
</header>
<div class="row">
<div class="tab1"></div>
<div class="tab2"></div>
<div class="tab3"></div>
<div class="tab4"></div>
</div>
</body>
</html>
When I run this in Chrome 43, I get horizontal rectangles. However, in Firefox 39 this results in vertical rectangles. The important part is the use of flex-direction: column; and flex-wrap: wrap; in the element with class .row.
In order to get a similar layout, adding height: 100%; gives vertical rectangles in Chrome. However, this creates a scrollbar in both browsers due to the (empty) header element. Does anyone know what is the reason of this difference in the layout and what is the best way to fix it?
UPDATE:
By the way, I'm interested in understanding why there is a difference in Chrome and Firefox, not so much in obtaining a layout with vertical rectangles. Maybe there is something buggy in the use of flex-direction: column or maybe I'm doing something wrong. In any case, it would be helpful to know that.
There is a bug in Flex that causes strange behavior when you don't define width's and height's also min-height is known to cause a lot of problem's.
Here is a repository of some known issues and how to workaround them.
Side note I believe Safari requires -webkit- vendor prefix for flex rules
Here is a possible workaround give's vertical box's in both FF and Chrome
html,
body {
height:100%;
width:100%;
margin: 0px;
display: flex;
flex-direction: row;
}
header {
border: 1px solid #D3D3D3;
flex: 0 1 auto;
}
.row {
display: flex;
flex-direction: row;
flex: 1 0 auto;
flex-wrap: wrap;
}
.tab1 {
flex: 1 0 20%;
position: relative;
margin: 0.5em;
background-color: orange;
}
.tab2 {
flex: 1 0 20%;
position: relative;
margin: 0.5em;
background-color: blue;
}
.tab3 {
flex: 1 0 20%;
position: relative;
margin: 0.5em;
border: 1px solid lightgray;
background-color: green;
}
.tab4 {
flex: 1 0 20%;
position: relative;
margin: 0.5em;
border: 1px solid lightgray;
background-color: yellow;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<header>
</header>
<div class="row">
<div class="tab1"></div>
<div class="tab2"></div>
<div class="tab3"></div>
<div class="tab4"></div>
</div>
</body>
</html>
Related
This question already has answers here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 4 months ago.
I have a horizontally centered column of Flex items ordered from 1 to 5 that are aligned from the top of the container like this:
body, html {
height: 100%;
position: relative;
margin: 0;
padding: 0;
}
.container {
display: inline-flex;
flex-wrap: wrap;
flex-direction: column;
align-items: flex-end;
align-content: center;
width: 100%;
height: 100%;
background: pink;
}
.item {
margin: 1px;
width: 30px;
height: 30px;
background: green;
}
<div class=container><div class=item>1</div><div class=item>2</div><div class=item>3</div><div class=item>4</div><div class=item>5</div></div>
I would like to let it aligned by the bottom of the container instead. I manage to do it with flex-direction: column-reverse; like in the next Snippet:
body, html {
height: 100%;
position: relative;
margin: 0;
padding: 0;
}
.container {
display: inline-flex;
flex-wrap: wrap;
flex-direction: column-reverse;
align-items: flex-end;
align-content: center;
width: 100%;
height: 100%;
background: pink;
}
.item {
margin: 1px;
width: 30px;
height: 30px;
background: green;
}
<div class=container><div class=item>1</div><div class=item>2</div><div class=item>3</div><div class=item>4</div><div class=item>5</div></div>
However, as you see, the items get out of order! Is there a way to let a flex column on the bottom without reversing the items order using CSS? I tried every Flex property that I know so far without success.
You can use justify-content: end;
.container {
width: 150px;
height: 150px;
border: 1px solid black;
display: flex;
flex-direction: column;
align-items: center;
justify-content: end;
}
.content {
width: 25px;
height: 25px;
border: 1px solid black;
}
<div class="container">
<div class="content">1</div>
<div class="content">2</div>
<div class="content">3</div>
<div class="content">4</div>
<div class="content">5</div>
</div>
You need to use the justify-content property to align content along the main axis (in your case vertically). You are using align-items which defines how the items should be aligned along the cross axis.
body, html {
height: 100%;
position: relative;
margin: 0;
padding: 0;
}
.container {
display: inline-flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: flex-end;
align-content: center;
width: 100%;
height: 100%;
background: pink;
}
.item {
margin: 1px;
width: 30px;
height: 30px;
background: green;
}
<div class=container>
<div class=item>1</div>
<div class=item>2</div>
<div class=item>3</div>
<div class=item>4</div>
<div class=item>5</div>
</div>
I'm wondering how I can make the blue div 'stick' to the top and bottom of the page (so you can't scroll beyond it) without breaking the document flow (I don't want it to overlap the content div). A crude version is here in the code snippet. If I set 'absolute' on it, it breaks flow and the content goes under the menu. If I leave it relative, you can scroll beyond it (I want it to stay at top: 0, bottom: 0 for a full 100vh with its own scrolling).
Is there something that I'm missing?
* {
box-sizing: border-box;
}
.main {
display: flex;
flex-direction: row;
}
.sideNav {
width: 100px;
height: 100vh;
border: 5px solid red;
}
.sidePanel {
width: 50px;
height: 100vh;
border: 5px solid blue;
}
.content {
display: flex;
flex-direction: column;
flex-grow: 1;
height: 200vh;
margin: auto;
width: auto;
border: 5px solid green;
}
<div class="main">
<div class="sideNav">Side Nav</div>
<div class="content">This is the content area</div>
<div class="sidePanel">Side Panel</div>
</div>
You really can't do it without removing it from the document flow.
But if you know the width of the side panel, you can apply it as a right margin to the content div.
.main {
display: flex;
flex-direction: row;
}
.sideNav {
width: 100px;
height: 100vh;
border: 5px solid red;
}
.sidePanel {
width: 50px;
height: 100vh;
border: 5px solid blue;
position: fixed; /* new */
right: 0; /* new */
}
.content {
display: flex;
flex-direction: column;
flex-grow: 1;
height: 200vh;
margin: auto;
width: auto;
border: 5px solid green;
margin-right: 50px; /* new */
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
<div class="main">
<div class="sideNav">Side Nav</div>
<div class="content">This is the content area</div>
<div class="sidePanel">Side Panel</div>
</div>
I am trying to make a fluid flex field where if there is no enough space then it should drop to next line. As you can see in this example if you decrease the size of the field it doesnt drop to next line because I am using flex.
.container {
width: 80%;
border: 2px solid #ddd;
padding: 20px;
display: flex;
overflow: hidden;
}
.container .panel {
flex: none;
}
.container .panel-info {
display: flex;
align-items: center;
}
.container .panel-info .dot {
background-color: #ccc;
width: 4px;
height: 4px;
border-radius: 50%;
margin: 0 8px;
}
<div class="container">
<div class="panel">Some Long Info</div>
<div class="panel-info">
<div class="dot"></div>
<div class="info">Information</div>
</div>
</div>
Use flex-wrap: wrap.
More information on MDN about the flex-wrap property
I have a requirement that there are 4 boxes in one row.
the boxes have fixed width and height
but the width of the row will change by screen size.
the first box should be aligned to the left border of the row
last box aligned to right border.
Also the space between any two boxes should be equal.
Is there a pure CSS way to make that happen? Here is the jsfiddle code.
HTML:
<div class="row">
<div class ="col">
<div class="box"></div>
</div>
<div class ="col">
<div class="box"></div>
</div>
<div class ="col">
<div class="box"></div>
</div>
<div class ="col">
<div class="box"></div>
</div>
</div>
CSS:
.row {
display: table;
border: 1px solid green;
width: 400px; /* it changes by screen size actually */
padding: 5px;
}
.row:before, .row:after {
content: "";
}
.row:after {
clear: both;
}
.col {
float: left;
width: 25%;
}
.box {
border: 1px solid #DDD;
width: 80px;
height: 80px;
margin: 0 auto;
}
.col:first-child .box {
margin-left: 0;
}
.col:last-child .box {
margin-right: 0;
}
Use text-align:justify on the container, this way it will work no matter how many elements you have in your div (you don't have to work out % widths for each list item
Updated CSS
.row {
text-align: justify;
min-width: 412px;
border: 1px solid green;
width: 80%; /* it changes by screen size actually */
height: 90px;
padding: 5px;
}
.row:after {
content: '';
display: inline-block;
width: 100%;
}
.col {
display: inline-block;
}
.box {
border: 1px solid #DDD;
width: 80px;
height: 80px;
margin: 0 auto;
}
FIDDLE
You can make use of css3 flex boxes which is supported in modern browsers.
.row {
display: flex;
justify-content: space-between;
border: 1px solid green;
}
.box {
border: 1px solid #DDD;
width: 80px;
height: 80px;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
jsfiddle demo
more about flex boxes # css tricks
Why not use flexbox ?
Demo
css
.flex-container {
padding: 5px;
margin: 0;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: space-between; /* this make the end divs at sides and equal space between other divs */
}
.flex-item {
background: tomato;
padding: 5px;
width: 200px;
height: 150px;
margin-top: 10px;
line-height: 150px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
}
html
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
</div>
Read here for more detail on flexbox
you simply have to remove the padding attribute from the following
.row {
display: table;
border: 1px solid green;
width: 400px; /* it changes by screen size actually */
/*padding: 5px;*/
}
here is the demo.
Let me know if this was helpful or if you have anymore queries.
Given the following HTML:
<div class="outer">
<div>
<div class="inner">A</div>
</div>
</div>
<div class="outer">
<div class="inner">B</div>
</div>
and the following CSS (prefix free):
.outer {
display: box;
box-orient: vertical;
height: 100px;
width: 100px;
background: red;
margin: 10px;
}
.inner {
height: 50px;
margin-top: 10px;
background: green;
}
Here is a CodePen.
A is wrapped in a <div> so it's margin gets ignored.
Q: How can I achieve B's behavior for A (margin) with the flex box model?
Note: The div wrappers can go multiple levels deep
Targeting: latest Chrome/Safari/iOS
Thank you very much for your help!
Edit: Thanks to #JoséCabo I came up with this:
.outer {
display: flex;
flex-direction: column;
height: 100px;
width: 100px;
background: red;
margin: 10px;
}
.inner {
height: 50px;
margin-top: 10px;
background: green;
}
CodePen
Chrome:
Safari:
Unfortunately it doesn't work in Safari as mentioned by #cimmanon, so I still need some help.
What you're looking at actually has nothing to do with Flexbox, but what's called margin collapse
.outer div {
border: 1px solid;
}
The addition of the border has prevented the margin from collapsing. Rather than relying on margins, I would recommend placing a padding on the parent container:
.outer {
padding-top: 10px;
}
Example:
.wrapper {
background: #eef;
border: 1px solid darkgray;
}
.container {
display: flex;
flex-wrap: wrap;
margin: -1em;
}
.item {
flex-grow: 1;
margin: 1em;
border: 1px solid black;
padding: 1em;
min-width: 6em;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class="wrapper">
<div class='container'>
<div class='item'>item</div>
<div class='item'>item</div>
<div class='item'>item</div>
<div class='item'>item</div>
<div class='item'>item</div>
<div class='item'>item</div>
</div>
</div>
</body>
</html>
Now, to cover all of your prefixes, you need something like this:
.outer {
display: -moz-box;
display: -webkit-flexbox;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-moz-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
height: 100px;
width: 100px;
background: red;
margin: 10px;
}
Finally I came up with the right solution (for my specific problem).
.outer {
display: flex;
flex-direction: column;
height: 100px;
width: 100px;
background: red;
margin: 10px;
}
.inner {
height: 50px;
margin-top: 10px;
background: green;
display: inline-block;
width: 100%;
}
CodePen
I'm using display: inline-block on .inner to disable margin collapsing and then compensate for the lost width with width: 100%.
All the credit goes to cimmanon for pointing me in the right "margin collapse" direction