Deka87 Deka87 - 1 month ago 9
CSS Question

Change the order of full width columns in Bootstrap

I have the following grid:

<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6">col-sm-6</div>
<div class="col-xs-12 col-sm-6">col-sm-6</div>
<div class="col-xs-12 col-sm-12">col-sm-12</div>
</div>
</div>


http://codepen.io/Deka87/pen/amApvk

It has the
.col-sm-12
block displayed under the first two items. What I want is to display the same column under the first column on extra smal screens.

<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6">col-sm-6</div>
<div class="col-xs-12 col-sm-12">col-sm-12</div>
<div class="col-xs-12 col-sm-6">col-sm-6</div>
</div>
</div>


Seems like I can't use push / pull classes with full width columns, so is it only JS left?

PS: The first item should go first on extra small screens too, so I can't change the order of the first two columns on extra small screens.

Answer

If you want to achieve this with flexbox you can do the following:

Create a class modifier for Bootstrap's row class.

.row--flex {
  display: flex; /* Creates a flex container. */
  flex-wrap: wrap; /* Wrap columns, now flex-items. */
}

Since Bootstrap's col-* classes already set a different width percentage for each viewport using media queries and our flex-container has flex-direction: row; by default, you will not need to define a flex-basis on flex-items, here's why.


Then you remove the floats, because they are not needed anymore:

.row--flex [class^="col-"],
.row--flex [class*="col-"] {
  float: none;
}

Finally you use a selector in the element with the col-* class you want to move.

We will use the class col-order-* as a selector.

Move the second column down changing its order property value to 1 and you're done.

The CSS order property specifies the order used to lay out flex items in their flex container.

The default order value in flex-items is 0, that's why using any value higher than that will work.

CSS:

.col-order-1 {
  order: 1;
}

HTML:

<div class="container">
  <div class="row row--flex">
    <div class="col-xs-12 col-sm-6">col-sm-6</div>
    <div class="col-xs-12 col-sm-12 col-order-1">col-sm-12</div>
    <div class="col-xs-12 col-sm-6">col-sm-6</div>
  </div>

Code Snippet:

.row--flex {
  display: flex;
  flex-wrap: wrap;
}
.row--flex [class^="col-"],
.row--flex [class*="col-"] {
  float: none;
}
.col-order-1 {
  order: 1;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row row--flex">
    <div class="col-xs-12 col-sm-6">col-sm-6</div>
    <div class="col-xs-12 col-sm-12 col-order-1">col-sm-12</div>
    <div class="col-xs-12 col-sm-6">col-sm-6</div>
  </div>
</div>


Edit:

If you want this only applied to extra small screens, declare the col-order-* class inside a media query.

Example:

@media (max-width: 480px) {
  .col-xs-order-1 {
    order: 1;
  }
}

Code Snippet:

.row--flex {
  display: flex;
  flex-wrap: wrap;
}
.row--flex [class^="col-"],
.row--flex [class*="col-"] {
  float: none;
}
@media (max-width: 480px) {
  .col-xs-order-1 {
    order: 1;
  }
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row row--flex">
    <div class="col-xs-12 col-sm-6">col-sm-6</div>
    <div class="col-xs-12 col-sm-12 col-xs-order-1">col-sm-12</div>
    <div class="col-xs-12 col-sm-6">col-sm-6</div>
  </div>
</div>