Flexbox wraps last column of the first row in Safari

Twitter BootstrapCssTwitter Bootstrap-3Flexbox

Twitter Bootstrap Problem Overview


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>

Twitter Bootstrap Solutions


Solution 1 - Twitter Bootstrap

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`
}

Solution 2 - Twitter Bootstrap

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;
}

Solution 3 - Twitter Bootstrap

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;
}

Solution 4 - Twitter Bootstrap

I didn't want to add more classes to fix this kind of bug, so alternatively you can fix the .row class itself.

.row {
    &:before {
	    content: none;
    }

    &:after {
	    content: '';
    }
} 

Solution 5 - Twitter Bootstrap

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;
}

Solution 6 - Twitter Bootstrap

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.

Solution 7 - Twitter Bootstrap

Bootstrap 4 have issues with display: block; property when set either from css or from javascript on the .row class. I figured a solution for this Just create a class as:

.display-block {
	display: -webkit-box !important;
	display: -ms-flexbox !important;
	display: flex !important;
	-ms-flex-wrap: wrap !important;
	flex-wrap: wrap !important;
}

And then apply this class when you want to display the row.

Solution 8 - Twitter Bootstrap

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 [tag: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.

Solution 9 - Twitter Bootstrap

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/PZbNMX Additionally, 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.

Solution 10 - Twitter Bootstrap

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.

Solution 11 - Twitter Bootstrap

.row:before, .row:after {
content:'';
display:block;
width:100%;
height:0;
}
.row:after {
clear:both;
}

Solution 12 - Twitter Bootstrap

In case you are using display flex with flex-wrap i solved it applying a hight order to the before and after pseudo-elements of the row, so they position as the last elements.

.row.flex_class {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
.row.flex_class::before, .row.flex_class::after {
    order: 10;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDominikN.View Question on Stackoverflow
Solution 1 - Twitter BootstrapTaylanView Answer on Stackoverflow
Solution 2 - Twitter BootstrapDominikN.View Answer on Stackoverflow
Solution 3 - Twitter BootstrapGauravView Answer on Stackoverflow
Solution 4 - Twitter BootstrapJoeri WautersView Answer on Stackoverflow
Solution 5 - Twitter Bootstrapuser5373314View Answer on Stackoverflow
Solution 6 - Twitter BootstrapashamunView Answer on Stackoverflow
Solution 7 - Twitter BootstrapFarhanView Answer on Stackoverflow
Solution 8 - Twitter BootstrapMcVencoView Answer on Stackoverflow
Solution 9 - Twitter BootstrapBasil MohabirView Answer on Stackoverflow
Solution 10 - Twitter BootstrapCam TullosView Answer on Stackoverflow
Solution 11 - Twitter BootstrapEnotView Answer on Stackoverflow
Solution 12 - Twitter BootstrapJose SView Answer on Stackoverflow