Making flexbox inherit proper width in IE11 - css

We have a series of div components that are supposed to flex in IE11 as per the same behavior in Chrome. Within the following fiddle, you will find checkbox elements that make up a 'column' structure, as well as checkbox elements that are expected to fill the width of the entire parent.
On the second row where the full-width checkbox elements begin, that element is expected to wrap to the next line, because the .grid__item-flex element within it exceeds that width available to it in .grid__row a couple of levels up. However, on IE11, that width ceases to be respected, and thus .grid__item-flex continues to overflow off the width of the parent element.
Potential solutions that failed include enforcing a width on .grid__item-flex; where we give it 100% width, but the nested checkbox elements above will lose its column structure. Also, max-width: 100% as a property seems to be ignored when we apply it to .grid__item-flex.
Is there a CSS solution where we can force .grid__item-flex to respect its container width without breaking the nested columns above it, and ensure that the last checkbox element (below it) stays on the same line?
The JSFiddle that replicates my problem can be found here. The example works as expected on Chrome. Update Nov. 2018, JSFiddle no longer supports IE so this example is invalid unless we sandbox it elsewhere.
To summarize, there's two cases where flexboxes has to work simultaneously:
1) n number of div in a row that wraps to the next line if row width exceeds parent's width
We can achieve this using flex-wrap: wrap, but only when element has correct width
2) div that wraps to the next line if it's own content exceeds parent's width
Things I've tried:
Expanding out the shorthand flex: 1 into its full properties flex-grow flex-shrink flex-basis as "IE10 and IE11 default values for flex are 0 0 auto rather than 0 1 auto, as per the draft spec, as of September 2013"
Using a JS Polyfill for IE Flexbox, however the project is no longer being maintained (and did not work as a fix)
Using a PostCSS plugin for Webpack that attempts a global fix using flex: 1 1 0%
Applying width: 100% on the div that overflows its parent causes the nested columns above to turn into one long column, thus although it partially fixes the overflow issue, it defeats the purpose of having flexbox in the first place (since we want as many divs as possible to flex into a row).

If you need a solution which doesn't involve declaring width, I was able to get this working with a couple of flex specifications:
See example: https://jsfiddle.net/0ykq19um/
.grid__item-flex {
flex: 0 1 auto;
}
To be explicit with IE,
.grid__item-flex:only-child {
flex: 1 1 auto;
}
To allow full-width, and
.grid__row-overflow {
flex: 1 1;
}
For a new class on the .grid__row.grid__row-md.parent which surrounds the (potentially) overflowing row.

Related

CSS3 display:table, overflow-y:scroll doesn't work

I have a data table that needs to scroll vertically. It seems that if your display value is table, you cannot set a height or max-height, and so overflow-y:scroll does nothing.
(Codepen with table)
.fake-table {
display: table;
max-height: 300px;
overflow-y: scroll;
}
Also, if you remove the display:table from the parent but keep the display:table-row and table-cell, the width of the rows will not be 100%;
I tried instead doing this with flexbox (Codepen with flexbox). But of course, then I don't have nice columns that are left-justified.
.fake-table > * {
display: flex;
justify-content: space-around;
}
Browser support is all modern browsers (IE10 +) including mobile safari and android browser.
It seems that if your display value is table, you cannot set a height or max-height
Effectively, the spec says (max-height):
In CSS 2.1, the effect of 'min-height' and 'max-height' on tables,
inline tables, table cells, table rows, and row groups is undefined.
And you can use the height property, but it will be treated as a minimum height, and thus won't produce overflow (Table height algorithms):
The height of a table is given by the 'height' property for the
'table' or 'inline-table' element. A value of 'auto' means that the
height is the sum of the row heights plus any cell spacing or borders.
Any other value is treated as a minimum height.
Also, if you remove the display:table from the parent but keep the display:table-row and table-cell, the width of the rows will not be 100%
In this case, since there is no tabular container, an anonymous one is generated (Anonymous table objects):
Document languages other than HTML may not contain all the elements in
the CSS 2.1 table model. In these cases, the "missing" elements must
be assumed in order for the table model to work. Any table element
will automatically generate necessary anonymous table objects around
itself
But that anonymous table won't necessarily be as wide as .fake-table.
I tried instead doing this with flexbox
Flexbox is a bad choice because it has no grid notion.
Maybe CSS Grid would be better, but it's currently experimental and only IE10 supports it (an older version of the spec, tough).
Basically, you have two options:
Fixed column width approach
If you predefine the width of the columns, the result will be a grid, even if you don't use tabular/grid displays.
Non-tabular to wrapper
You can wrap your table inside a dummy (non-tabular) element, and set overflow and max-height to that element.
Wrap your .fake-table in a div?
CodePen
Also, it is 100% acceptable to use actual <table>'s for displaying tabular data... actually it's preferred. Its using tables for layout when things get hairy.
This addition worked for me:
table {
width: 100%;
}
.example-container {
height: 400px;
max-width: 100%;
overflow: auto;
}
Just set a container for your table, make it scrollable and fix its size, and limit its width, to prevent horizontal scroll.
I would like to give credit to Hardik Savani, who wrote the solution & explanation here.

How to make IE 11 wrap flexbox items when the flex container is inside a floating element?

I'm trying to add a flexbox element to the content area of a two column layout. The layout has a fixed width sidebar and fluid content. It uses float: left and negative margins to achieve this.
The goal is for the flex container to be 100% width of the parent. Flex items should be displayed in rows, with excess items wrapping to the next row.
The straight-forward approach works fine in Firefox and Chrome:
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: stretch;
}
.flex-item {
flex: 1 0 100px;
padding: 10px;
border: 1px solid gray;
}
...
<div class="flex-container">
<div class="flex-item">Item</div>
<!-- more items here -->
<div class="flex-item">Item</div>
</div>
Full example (works in FF and Chrome, but not IE 11):
http://jsfiddle.net/btc9chw0/3/
The problem
In Internet Explorer 11, all items are displayed on a single row. They never wrap to the next row, even when there are lots of items. This causes the page to become much wider than the browser window.
After lots of experimentation, it appears that this is somehow related to the fact that the flex container is inside a float: left element. Removing the float allows items to wrap correctly, but breaks other parts of the layout. The content area can have other content in addition to the flexbox, and some of that content needs to use float: left and clear: both. Without a floating parent element, a clear: both would push everything below the sidebar. Giving .flex-container a fixed width also fixes the problem, but in this case we want it be 100% width.
Firefox screenshot:
IE 11 screenshot:
The question
Is there are way to make flex items wrap to the next row in IE 11 when the parent of the flexbox container has "float: left"?
Disclaimer: Please disregard, for the moment, the fact that this layout uses both floats and flexbox instead of just one or the other. In this case, flexbox is a nice-to-have enhancement for one part of the page, while the general layout must be more robust.
The underlying issue here actually has to do with the auto measurement of a container in a shrink-to-fit context. By making .content have a min-width of 100% you've left the max-width to auto so the browser needs to measure the content to know its max-width to shrink down around it.
In IE, complete layout will be done to get the exact result with no limitations if none were set (as is the case here, we actually have infinite space since we can scroll and you have limited the width anywhere within its ancestor tree). Webkit and Gecko had made some changes in the past to avoid having to actually do layout and do an approximation, even though the actual measurement results were incorrect since they didn't know how big other (shrink-to-fit containers were) they decided the perf benefits were worth the tradeoff. With Gecko, Webkit and Blink (due to forking from webkit) all using this same behavior we changed our implementation to match this in Microsoft Edge and so we render the same as Firefox, Chrome, Safari. To get the same result in IE11 you'll need to provide a maximum width constraint when in a shrink-to-fit context (floats, abspos, table cell, etc).
Ultimately I prefer the IE behavior because it actually makes sense and is consistent. If there is enough space to lay out the content, the layout shouldn't change (as is the case here). Here is a simpler example showing why this approximation can cause issues, there is still enough room in the viewport to render the same result in each case but because they can't determine the actual dimensions of the floated blocks you get different results in Chrome/Firefox/Safari/Edge; while in IE they produce the same consistent result.
Sorry for the long reply, but I wanted to provide the context for why IE seems incorrect here.
Let me know if you need any further clarification.

How can I allow flex-items to grow while keeping the same size?

Flexbox is one of the coolest tools a web designer could wish for. Unfortunately, sometimes it's not immediately obvious what I'm supposed to do. Take, for example, this plunk. I'd like for the items to expand to fill the row, without expanding all the way across in the last row.
My CSS contains this important stuff:
.recipe-picker recipe {
-webkit-flex: 0 1 8em;
flex: 0 1 8em;
height: 12em;
}
If I change the 0 to any positive number (which corresponds to the flex-grow property), the last item row will stretch in a super ugly way. The rest of the items behave rather nicely, but the last row should keep the same size as the rest of the items.
What can I do to fix this behavior?
This is something that cannot be expressed via CSS Flexbox right now. Someone asked basically this exact question on the CSS Working Group Mailing List a few days ago, and the response was: "At the moment, no, this is not possible. This is a high-priority item for Flexbox 2, though.
You may be able to hack up something like you want using max-width, though -- that'll prevent flex items (particularly those on the last line) from growing indefinitely. Here's a forked version of your plunk with a nonzero flex-grow, and with max-width: 10em.
(I chose 10em arbitrarily; you could also use e.g. max-width: calc(100%/5), if you want to make sure each flex item takes up no more than 1/5 of the line, for example.)
I achieved what you were looking for by adjusting flex-shrink.
.recipe-picker recipe {
flex: 0 0 8em;
}
I try to think of flex-grow and flex-shrink as "permission to expand". When either has a value, that means the element has permission to grow. When all elements have flex-grow, they will expand to the same size. But, the same rule holds true if they all have a flex-shrink value, too.
http://plnkr.co/edit/sxHUzIRPlbstpOzoGcR6?p=preview
I had the exact same problem, and managed to find a fully working workaround to deal with this flexbox shortcoming.
Given that this is a duplicate of this other question, and it would be wrong to copy my answer here again, I'm going to link to it, for those Googlers who find themselves here and not there:
How to keep wrapped flex-items the same width as the elements on the previous row?

Divide the page in two (vertically) among two children, if one not available, other should cover complete page

I hope the pictures describes what I want. Currently both the child div have height:50%
However, when one of them is absent, I want the other to cover the entire page.
I am looking for a css only solution as I presume I'm missing something very fundamental! :P
Without using the flex model or JavaScript, good luck :)
If you're okay with only modern browsers, then use the flex layout. Make a container with flex-direction: column and give each div inside a flex value of flex: 1 1 auto;.
See this fiddle.

float:left for an element with width:100%

What is the reason of using float:left for an element with width:100% in the 1140px Grid V2 by Andy Taylor https://github.com/andytlr/cssgrid
.row .twelvecol {
width: 100%;
float: left;
}
If for no other reason, probably consistency. Since all the other column numbers have to be floated (to get them as column groups across the row), it may be simply so that the full width column .twelvecol would have the same float applied, therefore being less likely to cause issues of it behaving differently with its wrappers or content compared to other column groupings.
Look at this fiddle even in a modern browser (Firefox 18) and note how the second full width row (the third row of the example) is not showing its yellow background color because the float was removed from it but it holds a floated element in it. This would be the type of issue avoided by putting a float on it.

Resources