I am trying to use Flexbox with the latest browsers (FF 36, Chrome 41, Opera 28, Safari 8) to achieve full-page holy grail layout. I've gotten it working in everything but Firefox.
The page is split vertically into header, main, footer. main is then split horizontally into three panels. Each panel should scroll independently if their content overflows their bounds. Firefox is the only one that will not do this.
Here is my example: http://jsfiddle.net/bpnjx3v9/1/
html, body {
margin: 0;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
background-color: blue;
}
#header, #footer {
flex: 0 0 100px;
background-color: blue;
}
#main {
background-color: yellow;
flex: 1 0 0px; /** Don't set parent of component to auto */
display: flex;
flex-direction: row;
}
.panel {
display: flex;
flex-direction: column;
flex: 1 0 auto;
overflow: auto;
}
What I don't understand even after reading the spec is how to make #main only use the height allocated to them by the parent. Instead FF seems to make their "intrinsic height" the height of all the child elements. What makes this work in all other browsers but not FF? Bonus points for pointing out the correct section of the spec that explains this.
Ok, so setting min-height: 0px on #main fixes Firefox and keeps everyone else happy.
http://jsfiddle.net/hughes_matt/bpnjx3v9/7/
#main {
background-color: yellow;
flex: 1 0 0px; /** Don't set parent of component to auto */
display: flex;
flex-direction: row;
}
Couldn't quite explain it but then found this in the spec:
By default, flex items won’t shrink below their minimum content size (the length of the longest word or fixed-size element). To change this, set the min-width or min-height property. (See Implied Minimum Size of Flex Items.)
main's minimum content height is the height of all its children, the panels. By giving that container explicit permission to be smaller than that, it maxes out at the height of its parent. Chrome/Safari/Opera were happy with a flex-basis: 0px, but Firefox needed min-height in addition to that.
Can anyone tell if this is a violation of the spec? Is FF being too strict or the other browsers being too lenient?
Related
I am adding 3 columns that are 400px wide max and adding space between them using space-between.
.wrap {
display: flex;
flex-wrap: wrap;
align-content: stretch;
justify-content: space-between;
}
.item {
width: 100%;
max-width: 400px;
}
When I make the screen size smaller, the items are not responsive. They just collapse below each other. If I remove flex-wrap I start getting more than 3 columns per row and they are below 400px.
How can I get 3 responsive columns with space between in flex?
Percent for the width can't be used because the space between items has to look the same at any screen size.
You should drop width: 100% if you do not want them to occupy the whole width of the parent. And since you are using flex on the parent, you might as well use flex properties on the children and have these:
.item {
flex-basis: 33%; /* <-- Added in lieu of the width */
max-width: 400px;
margin: 0px 5px; /* <-- Added to give left/right margins */
}
If you only have those 3 children in the parent, then you could also do this:
.item {
flex-grow: 1; /* <-- Lets them grow equally */
flex-shrink: 1; /* <-- Lets them shrink equally. OPTIONAL as 1 is the default */
max-width: 400px;
margin: 0px 5px; /* <-- Added to give left/right margins */
}
The shorthand for the last one is this:
.item {
flex: 1; /* <-- Lets them grow/shrink equally */
max-width: 400px;
margin: 0px 5px; /* <-- Added to give left/right margins */
}
Also, if you only have those 3 children in the parent, you may want to remove flex-wrap: wrap; from .wrapper if you do not want the children elements to wrap. It will not happen in this case, since the children have percentage widths which add up to 100%. But it could be confusing and it contradicts with your intent.
If you want three columns, change the width property to 33% in your .item declaration instead of 100%.
JSFiddle example
Currently, all your "columns" are fighting to be 100% of the parent node. Here's a great explanation of using css flex from css-tricks.com.
I am using Flexbox for a series of content blocks. The idea is to have blocks in a flex container whose height will be determined by the total of the flex items within it. This is working well on Chrome and Safari as it calculates the container height automatically and correctly, but the same does not happen on Firefox + IE. My CSS looks like this:
.container {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
.primary {
position: relative;
background-size: contain;
background-repeat: no-repeat;
width: 100%;
height: 0;
padding-top: 56.25%;
margin-bottom: 10px;
-webkit-box-flex: 1;
-webkit-flex: 1 0 100%;
-ms-flex: 1 0 100%;
flex: 1 0 100%;
}
.secondary {
position: relative;
background-size: contain;
background-repeat: no-repeat;
width: 100%;
height: 0;
padding-top: 28.10026385%;
flex: 2 1 40%;
margin-left: 10px;
}
}
Essentially, the padding-top: 28.1% decoration is for a background image set as an inline style. On chrome + safari, this calculates the height just fine. However, the container's height is not set up on IE + FF. I have tested all my browser prefixes and checked a lot of questions, but I'm a bit lost on why the height is calculated differently. If anyone has any suggestions that would be excellent. Setting a min-height on the blocks is not an option, as we will have varying sizes of blocks, so we don't want to constrain ourselves to a fixed or min height.
Short version: is there a difference in how Firefox + IE calculate height of flex containers and items? If so, what is the best way to get it to behave like Safari + chrome?
Here is a contrived example: http://codepen.io/anon/pen/NGjYGR
I'm noticing a few potential issues with the code you're referencing. Also, without full context of the referenced code—missing HTML—recommendations are based on the assumption that your HTML is structured in the following manner:
.container
.primary
.secondary
No height set on .container
If dimensions aren't set on this element how are the dimensions calculated for the children elements (i.e.: "28.1%" of ?) ?
There are many known issues with certain browser implementations of the flex specification
There are known issues with implementations flex-basis, and height calculations. Here is a comprehensive article on browser nuances on flex: here.
References:
Normalizing Cross-browser Flexbox Bugs:
http://philipwalton.com/articles/normalizing-cross-browser-flexbox-bugs/
I am new to flexbox, and I am trying to make a horizontal scrolling website. The idea is to show the first item as 100% height and width, like covering the screen with the remaining items to the right side, which will only be shown when I scroll.
Here is an image of what I am trying to do:
I tried setting the first item to 100% width, but it's still fitted just like other items.
Here is my CSS code:
body
{
margin: 0;
padding: 0;
background-color: rgb(242, 242, 242);
}
.flex-container
{
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
flex-flow:row;
height:100%;
position:absolute;
width:100%;
/*flex-wrap:wrap;*/
}
.box
{
padding: 20px;
color:white;
font-size:22px;
background-color: crimson;
border:1px solid white;
flex:1;
-webkit-flex:1;
text-align:center;
min-width:200px;
}
.splash
{
background-image: url(1.jpg);
width:100%;
background-size:cover;
background-position:50% 50%;
background-repeat: no-repeat;
transition: all 0.6s ease;
flex:10;
-webkit-flex:10;
}
.flex1:hover
{
flex:4;
-webkit-flex:4;
}
And my HTML code:
<div class="flex-container">
<div class="box splash">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
Flex items have "flex-shrink: 1" by default. If you want the first item to fill the container and force the others to overflow (as it sounds like you do), then you need to set "flex-shrink: 0" on it.
The best way to do this is via the "flex" shorthand, which you're already using to give it "flex: 10".
Just replace that with flex: 10 0 auto -- the '0' there gives it a flex-shrink of 0, which prevents it from shrinking below the width:100% that you've given it.
Perhaps better: just give it flex: none, since I don't think you're really getting any benefit from the "10" there, since there's no free space to distribute anyway, so the "10" is giving you 10 useless shares of nothing.
So that makes your 'splash' rule into this:
.splash {
background-image: url(1.jpg);
width:100%;
background-size:cover;
background-position:50% 50%;
background-repeat: no-repeat;
transition: all 0.6s ease;
flex:none;
}
Here's a fiddle with this change (but otherwise using your provided CSS/HTML). This renders like your mock-up in Firefox Nightly and Chrome:
http://jsfiddle.net/EVAXW/
I think I got a better way - especially when you're creating a horizontal scrolling carousel:
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
overflow-x: auto;
}
.item {
/* how you style this doesn't really matter - depends on your requirements -
but essentially you want the items to span full width, and that's the
default (every flex container item has flex-grow set to 1)
*/
}
Take note here: I changed the direction to column so that flex-wrap now wraps horizontally. Also, you can change overflow-x to hidden if you don't want the scrollbar to show - but don't omit the overflow-x property since that means it will be the outter parent to now overflow (something I wouldn't find desirable)
The JS can then kick in.
Cheers
you just set all flex properties to parent div plus also add "overflow:auto" and in child div of parent set "flex-shrink : 0"----All will be setsee code example in image
You can set the position of the Parent or Container to be Relative and the child inside them to be absolute.
.Parent{
display: flex;
// and use any flexbox property
width: 100%;
height: 100%
position: relative; // important point
overflow: auto;
}
.Child{
position: absolute; // important point
}
I have a problem combining div boxes and the overflow: auto property for adding scrollbars if needed.
The problem is that I don't want the whole page to be scrollable, but just the content div, thus I added overflow: hidden to the body and overflow: auto to the content.
body
{
padding: 0;
margin: 0;
background-color: navy;
overflow: hidden; /** no scrollbar on whole page **/
height: 100%;
}
#content
{
background-color: green;
overflow: auto;
height: 100%;
}
Nevertheless, I'm not able to see the end of the page, as the div increases its size beyond the viewable part of the website.
Please suggest how to solve this problem and only keep the content div scrollable.
I uploaded an example of my problem here: jsfiddle.net/3n7ay/
I can only get this to work with a fixed header height, is there no solution for dynamic header size? It's hard for me to believe...
Thanks & Regards
I think you looking for overflow-y: scroll; instead?
See fiddle: http://jsfiddle.net/3n7ay/5/
If you set height: 100% to the content element and you have also an header in your viewport this will make the former not entirely visible inside the viewport itself.
So the height must be defined as 100% - <header height>, either via javascript (if you need to support older browser) or via CSS3 calc() function, e.g.
#content {
height: -webkit-calc(100% - <height of header>px);
height: -moz-calc(100% - <height of header>px);
height: calc(100% - <height of header>px);
}
Try flex box, if you don't concern about Ie8 and Ie9. You can see the compatibility situation in caniuse.com: flexbox
Make container a flex box:
#container {
background-color: yellow;
height: 100%;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
}
Flex the content:
#content {
background-color: green;
overflow: auto;
height: 100%;
-ms-flex: 1;
-webkit-flex: 1;
flex: 1;
}
See fiddle: http://jsfiddle.net/r4JUk/4/
Im wanting to float 3 divs evenly(or more generally speaking) .
Im building a responsive theme (kinda) and i want specific items to adjust accordingly based on widths available.
now Yes i can start with taking random screen measurements and make calculations for "breaking points" (what i normally do) but with so many devices, im trying to see if i can make something truly flex in a smarter way which for me, would be something more automatic.
Like when one does even alignment with say margin 0px auto; etc...
so for example. if i have parent div at 1000px wide, and div1, div2, div3, div4 that i want floated at say, 240px wide, and "even" spacing, id maybe do it like this.
div1{ float:left; max-width:XXX; min-width:XXX; margin-right:10px; }
div2{ float:left; max-width:XXX; min-width:XXX; margin-right:10px; }
div3{ float:left; max-width:XXX; min-width:XXX; margin-right:10px; }
div4{ float:right; max-width:XXX; min-width:XXX; }
which will give me more or less my even spacing. If i wanted to adjust to different screens, id maybe do a media queries and blah blah blah
then id have to start with math to make good breaking points that look even.
is there a way to make it so that the spacing between divs floated remains even reguardless of the screen width without having to get into specific numbers?? as an example again, like when one does margin 0px auto; for example???
It may have been asked before, i apologize if it has.
Thanks in advanced.
If your markup looks similar to this...
<div class="parent">
<div>a</div>
<div>b</div>
<div>c</div>
<div>c</div>
</div>
Flexbox can do this very easily, and you won't need to use media queries for narrower devices. It just redistributes the free space for you.
http://jsfiddle.net/END8C/ (all prefixes included)
.parent {
display: -webkit-flexbox;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-flex-pack: justify;
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
margin: -5px; /* optional */
overflow: hidden; /* optional */
}
.parent div {
-webkit-flex: 0 0 240px;
-ms-flex: 0 0 240px;
flex: 0 0 240px;
margin: 5px;
}
You're still free to use floats on the child elements as a fall back for browsers that don't support flexbox (see: http://caniuse.com/#search=flexbox). Only thing to be aware of is that Firefox doesn't support wrapping so you'll have to use a #supports block for the unprefixed version (see: http://www.sitepoint.com/supports-native-css-feature-detection/).
You can get a similar effect by using justification:
http://jsfiddle.net/END8C/1/
.parent {
text-align: justify;
margin: -5px; /* optional */
}
.parent:after {
content: " ";
display: inline-block;
width: 100%;
}
.parent div {
display: inline-block;
margin: 5px;
width: 240px;
}
You'll need to comment out or remove any whitespace after the last child element or they won't line up right when the children wrap.
Try this, it will work for dynamic width,
#parent
{
width:99%;
text-align:center;
border-style:solid;
}
.kids
{
width:23%;
border-style:solid;
height:100px;
display:inline-block;
}