1

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.

sdvnksv
  • 9,350
  • 18
  • 56
  • 108
  • 1
    Go look up flexbox' `order` property. – CBroe Oct 27 '16 at 20:57
  • @CBroe I need to cover IE too, also Bootstrap v4 is still an alpha. – sdvnksv Oct 27 '16 at 20:58
  • I wasn't talking about BS4. And IE has decent enough support for this in all versions that any responsible developer would still support. – CBroe Oct 27 '16 at 21:13
  • @CBroe, you was absolutely right to advice flexbox. The answer below provided a solution that worked as expected. Worked in IE 11 which is all I need. – sdvnksv Oct 28 '16 at 12:41

2 Answers2

1

I'm doing some tests here, to tell you the truth I didn't knew it about this feature in bootstrap V3, but after a few minutes searching I've realised that the major point to achieve what you want is paying attention in the HTML MARKUP.

col-vp-push-x = push the column to the right by x number of columns, starting from where the column would normally render -> position: relative, on a vp or larger view-port. col-vp-pull-x = pull the column to the left by x number of columns, starting from where the column would normally render -> position: relative, on a vp or larger view-port.

vp = xs, sm, md, or lg

x = 1 thru 12

In the example below, B comes before A like I said bellow, and that it only does the pushing or pulling on view-ports that are greater than or equal to what was specified. i.e. col-sm-push-5 will only push 5 columns on sm view-ports or greater. This is because Bootstrap is a "mobile first" framework, so your HTML should reflect the mobile version of your site. The Pushing and Pulling are then done on the larger screens.

<div class="row">
    <div class="col-sm-4  col-xs-12">
        Content B
    </div>
    <div class="col-sm-4 col-sm-push-4 col-xs-12">
        Content A
    </div>
    <div class="col-sm-4 col-sm-pull-4 col-xs-12">
        Content C
    </div>
</div>

See the demo here: https://jsfiddle.net/kL649qp0/1/

Also, I tried to follow your number of columns but the layout got messed due to the number exceed 12 columns.

I hope it helps!

Obs.:
1. (Desktop) Larger view-ports get pushed and pulled.
2. (Mobile) Smaller view-ports render in normal order.
Source: http://www.schmalz.io/2014/10/08/Column-Ordering-in-Bootstrap/

Yuri Pereira
  • 1,945
  • 17
  • 24
  • 1
    That was the problem that the 3d column should span full width on all screen sizes, i.e. the total number of cols will always be more than 12. – sdvnksv Oct 27 '16 at 22:11
1

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>
Community
  • 1
  • 1
Ricky Ruiz
  • 25,455
  • 6
  • 44
  • 53