Flexbox wraps last column of the first row in Safari

+46 votes
asked Dec 13, 2015 by dn

The last column of the first row is wrapped to the next line when viewing in Safari, and some other iOS based browsers.

Safari:

enter image description here

Chrome / Others:

enter image description here

Code:

.flexthis { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap;
}
.flexthis .col-md-4 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex;
}
<div class="row flexthis"> <div class="col-md-4 col-sm-6 text-center"> <div class="product"> <img src="img.jpg" alt="" class="img-responsive"> <h3>Name</h3> <p>Description</p> </div> </div>
</div>

9 Answers

+99 votes
answered Jul 11, 2016 by taylan

Explanation

This happens because Safari treats :before and :after pseudo-elements as if they were real elements. E.g. think about a container with 7 items. If container has :before and :after Safari will position the items like this:

[:before ] [1st-item] [2nd-item]
[3rd-item] [4th-item] [5th-item]
[6th-item] [7th-item] [:after ]

Solution

As an alternative to the accepted answer I remove :before & :after from flex containers instead of altering the HTML. In your case:

.flexthis.container:before,
.flexthis.container:after,
.flexthis.row:before,
.flexthis.row:after { content: normal; // IE doesn't support `initial`
}
+8 votes
answered Aug 25, 2016 by gaurav

Just to update on my question

This is the solution I go with, this is obviously fixed for Bootstrap4, which is flexbox compatible. So this is only for bootstrap3.

.row.flexthis:after, .row.flexthis:before{ display: none;
}
+2 votes
answered Feb 8, 2017 by basil-mohabir

Found this issue trying to do a simple grid using Bootstrap for the TwentyThree CMS, and got the same bug in Safari. Anyway, this solved it for me:

.flex-container:before { display: inline;
}
+5 votes
answered Apr 10, 2017 by joeri-wauters

I know the issue is quite old, but I ran into this issue today, and wasted over 12 hours in fixing it. Though about 10 hours out of that were spent in realizing that safari is failing with 12-column bootstrap grid, and it is no other issue.

Fix that I made is rather simple. Here is the version for Visual Composer. Class names may vary for other frameworks.

.vc_row-flex:before, .vc_row-flex:after{ width: 0;
}
0 votes
answered Aug 18, 2017 by cam-tullos

This seems to be a bug in Safari's rendering causing the columns to overflow (and therefore wrap) the Bootstrap container (some kind of Webkit rounding error maybe?). Since you are using Bootstrap, you should be able to achieve the desired result without using flex:

<div class="row"> <div class="col-md-4 col-sm-6 text-center"> <div class="product"> <img src="img.jpg" alt="" class="img-responsive"> <h3>Name</h3> <p>Description</p> </div> </div>
</div>
<style> .product { /* this is to automatically center and prevent overflow on very narrow viewports */ display: inline-block; max-width: 100%; }
</style>

But! Now the problem looking at your example is that you need to keep your product blocks the exact same size or the grid won't keep it's shape. One possible solution is to give .product a fixed height and adjust using media queries.

Here is an example I made that works in Safari and other browsers: http://codepen.io/anon/pen/PZbNMXAdditionally, you can use style rules to keep images or description text within a certain size to make things easier to maintain.

Another possible solution is to use a script or jQuery plugin to allow for more dynamic uniform sizing, but I'm not as savvy with that stuff.

I ran into the same issue when trying to combine flex and Bootstrap using Safari, so I hope this helps.

0 votes
answered Oct 27, 2017 by enot

I had the same problem and the answer was that Flex box on safari doesn't seem to like the floats being cleared on the same div that is display: flex.

0 votes
answered Dec 14, 2017 by ashamun
.row:before, .row:after {
content:'';
display:block;
width:100%;
height:0;
}
.row:after {
clear:both;
}
0 votes
answered Mar 13 by mcvenco

I was able to fix it by adding

.row:before, .row:after {
display: flex !important;
}

Obviously this isn't the most elegant solution but it may work for some in the meantime until they fix it.

0 votes
answered Nov 8 by farhan

I've spent a few hours on this issue as well. In my case I inserted flexbox in an existing project to make all elements in a row have the same height. All browsers except Safari rendered it correctly, but none of the above answers seemed to fix my problem.

Until I discovered that there still was a Bootstrap clearfix hack being used: (code is from a laravel project, but generic Bootstrap otherwise)

@foreach ($articles as $key => $article) @if ($key % 3 === 0) <div class="clearfix hidden-xs hidden-sm"></div> @endif @if ($key % 2 === 0) <div class="clearfix hidden-lg hidden-md"></div> @endif etc...
@endforeach

Apparently, other browsers than Safari ignore the .clearfix in some way when flexbox is being used.

So, when using flexbox on your columns, there is no need to use Bootstrap's clearfix anymore.

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
...