How do I change Bootstrap 3 column order on mobile layout?

286,404

Solution 1

You cannot change the order of columns in smaller screens but you can do that in large screens.

So change the order of your columns.

<!--Main Content-->
<div class="col-lg-9 col-lg-push-3">
</div>

<!--Sidebar-->
<div class="col-lg-3 col-lg-pull-9">
</div>

By default this displays the main content first.

So in mobile main content is displayed first.

By using col-lg-push and col-lg-pull we can reorder the columns in large screens and display sidebar on the left and main content on the right.

Working fiddle here.

Solution 2

Updated 2018

For the original question based on Bootstrap 3, the solution was to use push-pull.

In Bootstrap 4 it's now possible to change the order, even when the columns are full-width stacked vertically, thanks to Bootstrap 4 flexbox. OFC, the push pull method will still work, but now there are other ways to change column order in Bootstrap 4, making it possible to re-order full-width columns.

Method 1 - Use flex-column-reverse for xs screens:

<div class="row flex-column-reverse flex-md-row">
    <div class="col-md-3">
        sidebar
    </div>
    <div class="col-md-9">
        main
    </div>
</div>

Method 2 - Use order-first for xs screens:

<div class="row">
    <div class="col-md-3">
        sidebar
    </div>
    <div class="col-md-9 order-first order-md-last">
        main
    </div>
</div>

Bootstrap 4(alpha 6): http://www.codeply.com/go/bBMOsvtJhD
Bootstrap 4.1: https://www.codeply.com/go/e0v77yGtcr


Original 3.x Answer

For the original question based on Bootstrap 3, the solution was to use push-pull for the larger widths, and then the columns will show is their natural order on smaller (xs) widths. (A-B reverse to B-A).

<div class="container">
    <div class="row">
        <div class="col-md-9 col-md-push-3">
            main
        </div>
        <div class="col-md-3 col-md-pull-9">
            sidebar
        </div>
    </div>
</div>

Bootstrap 3: http://www.codeply.com/go/wgzJXs3gel

@emre stated, "You cannot change the order of columns in smaller screens but you can do that in large screens". However, this should be clarified to state: "You cannot change the order of full-width "stacked" columns.." in Bootstrap 3.

Solution 3

Bootstrap 3 Answer

The answers here work for just 2 cells, but as soon as those columns have more in them it can lead to a bit more complexity. I think I've found a generalized solution for any number of cells in multiple columns.

Goals

Get a vertical sequence of tags on mobile to arrange themselves in whatever order the design calls for on tablet/desktop. In this concrete example, one tag must enter flow earlier than it normally would, and another later than it normally would.

Mobile

[1 headline]
[2 image]
[3 qty]
[4 caption]
[5 desc]

Tablet+

[2 image  ][1 headline]
[         ][3 qty     ]
[         ][5 desc    ]
[4 caption][          ]
[         ][          ]

So headline needs to shuffle right on tablet+, and technically, so does desc - it sits above the caption tag that precedes it on mobile. You'll see in a moment 4 caption is in trouble too.

Let's assume every cell could vary in height, and needs to be flush top-to-bottom with its next cell (ruling out weak tricks like a table).

As with all Bootstrap Grid problems step 1 is to realize the HTML has to be in mobile-order, 1 2 3 4 5, on the page. Then, determine how to get tablet/desktop to reorder itself in this way - ideally without Javascript.

The solution to get 1 headline and 3 qty to sit to the right not the left is to simply set them both pull-right. This applies CSS float: right, meaning they find the first open space they'll fit to the right. You can think of the browser's CSS processor working in the following order: 1 fits in to the right top corner. 2 is next and is regular (float: left), so it goes to top-left corner. Then 3, which is float: right so it leaps over underneath 1.

But this solution wasn't enough for 4 caption; because the right 2 cells are so short 2 image on the left tends to be longer than the both of them combined. Bootstrap Grid is a glorified float hack, meaning 4 caption is float: left. With 2 image occupying so much room on the left, 4 caption attempts to fit in the next available space - often the right column, not the left where we wanted it.

The solution here (and more generally for any issue like this) was to add a hack tag, hidden on mobile, that exists on tablet+ to push caption out, that then gets covered up by a negative margin - like this:

[2 image  ][1 headline]
[         ][3 qty     ]
[         ][4 hack    ]
[5 caption][6 desc ^^^]
[         ][          ]

http://jsfiddle.net/b9chris/52VtD/16633/

HTML:

<div id=headline class="col-xs-12 col-sm-6 pull-right">Product Headline</div>
<div id=image class="col-xs-12 col-sm-6">Product Image</div>
<div id=qty class="col-xs-12 col-sm-6 pull-right">Qty, Add to cart</div>
<div id=hack class="hidden-xs col-sm-6">Hack</div>
<div id=caption class="col-xs-12 col-sm-6">Product image caption</div>
<div id=desc class="col-xs-12 col-sm-6 pull-right">Product description</div>

CSS:

#hack { height: 50px; }

@media (min-width: @screen-sm) {
    #desc { margin-top: -50px; }
}

So, the generalized solution here is to add hack tags that can disappear on mobile. On tablet+ the hack tags allow displayed tags to appear earlier or later in the flow, then get pulled up or down to cover up those hack tags.

Note: I've used fixed heights for the sake of the simple example in the linked jsfiddle, but the actual site content I was working on varies in height in all 5 tags. It renders properly with relatively large variance in tag heights, especially image and desc.

Note 2: Depending on your layout, you may have a consistent enough column order on tablet+ (or larger resolutions), that you can avoid use of hack tags, using margin-bottom instead, like so:

Note 3: This uses Bootstrap 3. Bootstrap 4 uses a different grid set, and won't work with these examples.

http://jsfiddle.net/b9chris/52VtD/16632/

Solution 4

October 2017

I would like to add another Bootstrap 4 solution. One that worked for me.

The CSS "Order" property, combined with a media query, can be used to re-order columns when they get stacked in smaller screens.

Something like this:

@media only screen and (max-width: 768px) {
    #first {
        order: 2;
    }
    #second {
        order: 4;
    }
    #third {
        order: 1;
    }
    #fourth {
        order: 3;
    }
}

CodePen Link: https://codepen.io/preston206/pen/EwrXqm

Adjust the screen size and you'll see the columns get stacked in a different order.

I'll tie this in with the original poster's question. With CSS, the navbar, sidebar, and content can be targeted and then order properties applied within a media query.

Solution 5

In Bootstrap 4, if you want to do something like this:

    Mobile  |   Desktop
-----------------------------
    A       |       A
    C       |   B       C
    B       |       D
    D       |

You need to reverse the order of B then C then apply order-{breakpoint}-first to B. And apply two different settings, one that will make them share the same cols and other that will make them take the full width of the 12 cols:

  • Smaller screens: 12 cols to B and 12 cols to C

  • Larger screens: 12 cols between the sum of them (B + C = 12)

Like this

<div class='row no-gutters'>
    <div class='col-12'>
        A
    </div>
    <div class='col-12'>
        <div class='row no-gutters'>
            <div class='col-12 col-md-6'>
                C
            </div>
            <div class='col-12 col-md-6 order-md-first'>
                B
            </div>
        </div>
    </div>
    <div class='col-12'>
        D
    </div>
</div>

Demo: https://codepen.io/anon/pen/wXLGKa

Share:
286,404
user3000310
Author by

user3000310

Updated on May 12, 2021

Comments

  • user3000310
    user3000310 about 3 years

    I'm making a responsive layout with a top fixed navbar. Underneath I have two columns, one for a sidebar (3), and one for content (9). Which on desktop looks like this

    navbar
    [3][9]

    When I resize to mobile the navbar is compressed and hidden, then the sidebar is stacked on top of the content, like this:

    navbar
    [3]
    [9]

    I would like the main content at the top, so I need to change the order on mobile to this:

    navbar
    [9]
    [3]

    I found this article which covers the same points, but the accepted answer has been edited to say that the solution no applies to the current version of Bootstrap.

    How can I reorder these columns on mobile? Or alternatively, how can I get the sidbar list-group into my expanding navbar?

    Here is my code:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    
    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
    
    <!-- Latest compiled and minified JavaScript -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    
    <div class="navbar navbar-inverse navbar-static-top">
      <div class="container">
        <a href="#" class="navbar-brand">Brand Title</a>
        <button class="navbar-toggle" data-toggle="collapse" data-target=".navHeaderCollapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <div class="collapse navbar-collapse navHeaderCollapse">
    
        <ul class="nav navbar-nav navbar-right"><!--original navbar-->
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#">FAQ</a></li>
        </ul>
    
        </div>
      </div>
    </div><!--End Navbar Div-->
        <div class="container">
      <div class="row">
    
        <div class="col-lg-3">
      <div class="list-group">
        <a href="#" class="list-group-item">
        <h4 class="list-group-item-heading">Lorem ipsum</h4>
        <p class="list-group-item-text">Lorem Ipsum is simply dummy text.</p></a>
      </div>
    </div><!--end sidebar-->
    
    
    <div class="col-lg-9">
      <div class="panel panel-default">
        <div class="panel-body">
          <div class="page-header">
         Main Content
        </div>
      </div>
    </div><!--end main content area-->
  • user3000310
    user3000310 over 10 years
    That's exactly what I wanted and your answer made perfect sense, thank you!
  • Luchux
    Luchux about 10 years
    @emre, why you specify that just in large? in the official example seems to be working for middle as well. getbootstrap.com/css/#grid
  • cdonner
    cdonner about 10 years
    I have been wondering what the push and pull classes are good for - now I know. Thanks.
  • Zim
    Zim over 9 years
    Shortly after the official release of 3.0 push/pull can be used to change the order of columns at any screen size (xs,sm,md,lg) bootply.com/ft1tOI71cZ
  • kdweber89
    kdweber89 almost 9 years
    Thank you so much for this wonderful explanation. I've working on something similar at work for 3 days now and kept putting down, not knowing where to go. Thank you!
  • Zarko Jovic
    Zarko Jovic over 7 years
    It is really a bad feeling when you see someone using JS to correct the problem with HTML/CSS architecture. You are not correcting the problem, you are just hiding it.
  • mghhgm
    mghhgm over 7 years
    Best... Thank you ❤️
  • Nanoturka
    Nanoturka over 6 years
    @ZarkoJovic so what? Sometimes JS solutions might be much more viable. Bootstrap is not made of pure CSS, it also uses JS.
  • Radmation
    Radmation over 6 years
    Thanks for this. This beats positioning cols absolutely and such!
  • Paul L
    Paul L almost 4 years
    Maybe I'm not understanding, but how can this work if the divs "vary in height" as described in the answer? The listed code and the linked fiddles both explicitly set the height of the hack and the corresponding negative bottom margin to heights that will only be flush because the other divs also have explicitly set heights. If those divs heights are smaller than the hack, we'll have gaps in the next "row", and if they're larger, we'll have content on top of other content.
  • Chris Moschini
    Chris Moschini almost 4 years
    @PaulL Look at the code more carefully, the height of the problem div is randomized so each view you get a different height, to better demo the varies in height scenario.
  • Milo Persic
    Milo Persic over 3 years
    This solution is very elegant and clear, and may be the best answer. Thanks.
  • James_RajKumar
    James_RajKumar over 2 years
    @ChrisMoschini is it possible to bring "Product description" as first element in mobile device using bootstrap 3 ? help would be much appreciated !
  • James_RajKumar
    James_RajKumar over 2 years
    how to do the same for multiple columns? I have 7 columns and their order should change for tablet and phone. For mobile last column(7) should appear first.