I just got into the flex world and am struggling a little with a setup like this one:
https://jsfiddle.net/5b0pLgkj/
In Chrome and Safari it works perfectly, children elements can be re-sized and they take the full empty space of the container. In Firefox, however, flex:1 does not seem to do anything and children can't be resized (although the height seems to be changing in the DOM).
Is it really necessary to use flex:auto?. When I do that it seems to work but children no longer take all the empty space. Any thoughts?
Thank you!
flex:1; it is equivalent to flex: 1 1 0n;
In Chrome for example flex:1 and flex:1 1 0; produce different results because flex-basis is ignored and only flex-grow and flex-shrink are applied.
So, your flex-basis is set to zero and FF read it as 0, which do not work for your the desired effect.
Set it to flex: 1 1 auto; or simply flex: auto;
Flex is the shorthand for flex-grow, flex-shrink and flex-basis.
See: https://css-tricks.com/almanac/properties/f/flex/
Related
Please see the code below:
ul {
display: flex;
list-style-type: none;
flex-wrap: wrap;
}
li {
flex-grow: 1;
border: 1px solid;
width: 1000px;
}
<header>
<ul class="child">
<li>Monday</li>
<li>Tuesday</li>
<li>Wednesday</li>
<li>Thursday</li>
<li>Friday</li>
</ul>
</header>
Notice the width of 1000px. When I load the page there are five rows as I would expect. If I remove the width property, then the boxes appear on one row as expected.
Now if I add a width of 1px, then the only change is that all boxes are the same size i.e. 372.28 pixels (not 1px). It appears to me that the behaviour is as follows:
If any width is added to the flex items that means they can all fit on one row then make sure all boxes are the same size.
If a width is added to the flex items meaning they cannot all fit on one row then honour the width.
If a width is not added then the boxes can be any size i.e. the Wednesday box is biggest in this case because Wednesday is the longest word.
Have I understood this correctly and why does the width effect the flex items like this?
I have done my own research and found questions like this: What are the differences between flex-grow and width?. However, I have not found an answer to my question. I have also read about the flex grow property here: https://www.w3.org/TR/2018/CR-css-flexbox-1-20181119/#flex-grow-property
It's important to note that width, height and flex-basis in a flex container represent the initial size of the item.
Once that size are determined, then flex-grow and flex-shrink enter into the picture and do their work, if possible. That can change the initial size.
Now, let's break down your question into the main points:
Notice the width of 1000px. When I load the page there are five rows as I would expect. If I remove the width property, then the boxes appear on one row as expected.
OK
Now if I add a width of 1px, then the only change is that all boxes are the same size i.e. 372.28 pixels (not 1px).
Do you mean "e.g., 372.28 pixels (not 1px)", not "i.e.", because the size of the item will vary depending on the size of the viewport. In other words, the size of each item will scale as you resize the window. But this is not an essential point.
All boxes are indeed equal length. This happens because the width is set to 1px.
If you were to remove the width rule, then the boxes would vary in length based on their content length. This is because the default width / flex-basis is auto.
If any width is added to the flex items that means they can all fit on one row then make sure all boxes are the same size.
Not necessarily.
The width property doesn't always relate to items all fitting on one row. That behavior is controlled by the flex-wrap and flex-direction properties.
Also, the width property doesn't always relate to items all having equal length. Other factors, such as flex-grow, can have an impact.
If a width is added to the flex items meaning they cannot all fit on one row then honour the width.
Not necessarily.
flex-grow, flex-shrink and flex-wrap can all have an impact.
If you want the width / flex-basis of an item to remain fixed, set both flex-shrink and flex-grow to 0 (which disables those functions).
If a width is not added then the boxes can be any size i.e. the Wednesday box is biggest in this case because Wednesday is the longest word.
Not necessarily.
flex-grow, flex-shrink and flex-wrap can all have an impact.
More details:
Make flex-grow expand items based on their original size
Flex items are shrinking below flex-basis
I have some table that set width for elements so some columns will have at least some percent of a width of the container.
I want to use flexbox to center this table and set the minimum-width for it.
The goal is to have centered table with some minimum width for which some columns will have the same width (same ratio).
If some cells have longer texts then I don't care if ratio will broke (width of this column will be bigger then other). I just care that it has nice and same width of columns for common case (small amount of text data in cells)
I was able to came up with solution that works on Firefox and Chrome (link).
But for Edge and IE11 the table stretch as if it was not in flex container (try to comment display: flex; on Firefox or Chrome and the result is stretched table like on Edge.
Also it looks that sometime setting columns work (link2). But I don't see the pattern of when it break in Edge/IE11.
Here is more production example that I want to achieve (works in Chrome/Firefox, stretch in Edge/IE11): "production" table example.
Any ideas how to achieve what I want on Edge/IE11? (I put in bold what I want to achieve).
It would be good if I could keep using flexbox container (it might require more changes in my codebase) but I think I will be fine with deleting style=width:p% from <col> if that's necessary.
The min-width rule is apparently being ignored in Edge / IE11.
There's an equivalent command that seems to work.
Instead of:
.inner {
min-width: 800px
}
Use:
.inner {
flex-basis: 800px; /* 1 */
flex-shrink: 0; /* 2 */
}
revised codepen
notes:
flex-basis is a substitute for width, in this case (see: flex-basis vs width)
flex-shrink: 0 ensures flex-basis / width cannot decrease below 800px (hence, both rules together emulate min-width)
I'm trying to have two elements fill their container and wrap when they reach a certain minimum size. The code I have works perfectly on all browsers other than safari & I can't figure out an alternative. It appears to be an issue with flex-basis: 0
Here's the issue:
http://www.cssdesk.com/RKeNY
Both display differently in safari and chrome. When the container width is changed on safari the flex-wrap has no effect.
Try setting
-webkit-flex:1 1 auto;
instead of
-webkit-flex:1;
on the flex elements.
This is discussed here: https://github.com/Modernizr/Modernizr/issues/1414
Specifically:
hexalys commented 28 days ago
To enable wrapping you'll need to need to specifically set flex: auto
(equivalent to flex: 1 1 auto;) or set both property flex-shrink:
1;and flex-basis: auto. The flex: 1; you have in your code does flex:
1 1 0px; technically allowing shrink, but apparently there is a bug
with the webkit prefixed version in Safari which does not allow a flex
wrap in that condition, while it correctly does on the unprefixed
version of Chrome and Firefox.
I'm curious is it possible to use the Grid Layout CSS to create such thing:
************************
* row #1 *
************************
* *
* *
* row #2 *
* *
* *
************************
* row #3 *
************************
So the grid must fill the full body height. And there's also some restrictions for other elements:
The row #1 is aligned to the top of the grid and can change it's
height (but has a max-height value)
The row #3 is aligned to the
bottom and can change it's height (also has a max-height value)
So the row #2 must fill all remaining space in grid.
The grid container should not overflow the html body.
There's an example what I achieved: 3 row grid layout.
I also can make everything with absolute position like this but there's no use because I can automatically calculate the row #2 margins without any imperative js code.
I see that the original question is marked as answered, but as the original included an attempt to use the CSS Grid Layout module to solve the problem, I thought I'd complement the answers with some solutions using newer standards.
Using flexbox
First of all, this kind of layout is pretty easy using flexbox. The flex-grow property allows you to define elements that fill the remaining space in this very way. JSBin example using flexbox here
Note: Not using all prefixes (e.g. to target IE10 etc) in the quick demo, but if you use something like autoprefixer it's kind of trivial. Also, beware of bugs relating to things like vh units in iOS and min-height flexbox columns in IE.
Using grid layout
Note: This demo will only work in Chrome Canary at the time the answer was written!
Grid layout is picking up pace and the spec has stabilized a bit. Chrome Canary has an implementation that is pretty far along, as does the WebKit nightly builds.
Grid layout has the same type of flexible sizing as flexbox, and moves the layout mechanism to the container element instead. JSBin demo – remember, Chrome Canary only at the time of writing. (It would work in WebKit nightlies as well with the right prefixes.)
Basically, the whole thing boils down to these lines:
body {
margin: 0;
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 100%;
height: 100vh;
}
The above means "Use the body element as a grid container, place items in it in source order, in a single column that is 100% wide, and size the first and third row according to content, and the middle one takes up all the space that is left". We don't need to specifically place the items inside the grid: they will auto-place themselves – we could change order etc if we wanted though. Grid Layout can do many more advanced things!
Most browser vendors are working on finishing their first grid implementations, so it's fun & worthwhile to start playing with it. :-)
Until then, the flexbox version gets you pretty good browser support.
You can do this with display:table property See Spec and Compatibility
Working Demo
CSS
#container {
display:table;
}
#head, #content, #foot {
display:table-row;
}
Edit:
Updated Fiddle
Added div inside table-row to prevent overflow
what about setting percentages heights like this:
.head{
height:10%;
max-height: /*max height allowed*/;
}
.content{
height:80%;
max-height: /*max height allowed*/;
}
.foot{
height:10%;
max-height: /*max height allowed*/;
}
I have a DIV that need a minimum width. I can't use the CSS min-width as its not cross-browser. I've created a inner div with a set width. When the browser is smaller than this inner div I get a scroll bar as expected.
The issue is that the outter div keeps shrinking smaller than the inner div.
See here for an example.
I would expect the blue to be the same width as the yellow.
Whats wrong with my CSS?
min-width is supported by all browsers except IE6. If you don't need IE6 support, you can use min-width like normal.
If you do need IE6 support, IE6 happens to treat width (and height) the same way that other browsers treat min-width (and min-height). You can use a hack to fake it:
#outer {
width: auto !important;
width: 1000px;
min-width: 1000px;
}
IE6 will apply the second width property (which it will treat as min-width) because it incorrectly ignores the !important on the first one. Other browsers will set the width to auto and the min-width to 1000px.
Hopefully I've understood your question correctly. Here's a modification of your original code with this update: http://jsfiddle.net/6e6yX/6/. Does this do what you're looking for?
If you add:
float: left;
To both of them, they'll behave as you're expecting.
http://jsfiddle.net/eVWKu/