Flexbox, clear fix and pseudo elements in Safari and Chrome

If you are progressively enhancing a layout with flexbox, remember that when you apply display: flex to an element, the flex layout applies to all its children including any pseudo elements.

This can occasionally cause issues in some browsers if you already have a clear fix in place to ensure the height of the element respects any floated children. One of the most common ways of doing this is to set the pseudo elements ::before and ::after to force the parent element to wrap:

.clear-fix:before,
.clear-fix:after {
    content: "";
    display: table;
}

.clear-fix:after {
    clear: both;
}

But applying flexbox can cause these elements to obtain small width of 1px in some browsers which looks ugly and probably isn’t what you want. Here’s a pen to test it out for yourself.

The fix

To hide the pseudo element, we need to tell the flexbox algorithm that they should definitely have zero width by using the flex-basis property which sets the initial size of the flexitem.

However, for some reason (I think to do with the fact the pseudo-elements are display: table) that isn’t enough. The ::after element shrinks away to nothing, but the ::before remains. The only way I have found to fix this is by explicitly setting the order property to something other than the default 0. The seems to give flexbox the kick it needs to force apply the flex-basis to both pseudo-elements:

.clear-fix:before,
.clear-fix:after {
  flex-basis: 0;
  order: 1;
}

Because these properties are only available in browsers which support flexbox, they shouldn’t interfere with the styles in older browsers, so you don’t need to test with Modernizr before using it.

The culprits

I haven’t tested extensively but this is what I’ve found so far:

Browser Chrome Safari Firefox
Version 33 6.1.1 27.0.1
Display Incorrect Incorrect Correct

The flexbox spec is still settling down so this kind of anomaly is to be expected. Still it’s good to know there is a fix for it.

Note to self: Old Safari, Android 2.3 and max-width: none

It seems some older browsers don’t correctly interpret element widths when both width: 100% and max-width: none are set.

I created a quick pen on CodePen to test this out. The test has two examples.

The first example should show the placeholder image at it’s natural width (300px). All browsers seems to get this right.

The second example with width: 100%; max-width: none; should show the image stretched to the full width of the red container. The value none is the default for max-width so the image should obey the 100% width declaration.

max width test: correct

However in some browsers (notably Safari before version 5.1) the image will revert to its natural size. This is a screenshot from Safari 4.0.5 for example:

max width test: incorrect

This seems to affect at least: IE6, Safari <5.1, and Android 2.3.

The solution seems to be to set: max-width: 100% on the child element to force it to occupy the full width on all browsers.

Old version of Safari make up a very small percentage of global usage but Android 2.3 is still pretty common so it’s worth watching out for.

Related: