Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reorder rows in bootstrap

I have the following layout when viewing my page on a phone


-A-

-B-

When the viewport is larger (i.e. md) I want to invert the two. such as:


-B-

-A-

I thought I could do this by thinking 'mobile first' via

<div class="row"> 
<div class="col-xs-12 col-md-4">first guy</div>
<div class="col-xs-12 col-md-8"> second guy
    <div class="col-xs-12 col-md-push-12">A</div>
    <div class="col-xs-12 col-md-pull-12">B</div>
</div>

Rather, it appears that this offsets the columns to the left and right outside of the container such as

 -*-     A          

B -*-

Hard to illustrate here, but rather than switching row positions (since they are each size 12) they offset to the outside of their containing element (which should be col-md-8)

like image 928
75inchpianist Avatar asked Dec 05 '14 07:12

75inchpianist


1 Answers

If you open up the unminified CSS for Bootstrap, which is second best way to learn how to use a framework, the first being LESS and/or SCSS, you'll see that push and pull work within 12 columns and not on full width items. These classes only change the relative position left or right, respectively.

  .col-sm-push-8 {
    left: 66.66666667%;
  }

  .col-sm-pull-4 {
    right: 33.33333333%;
  }

When you open up the LESS mixins for the grid, you'll see that they didn't remove col-12-X from the push and pull or the offsets, but they are not used.

Bootstrap is not CSS, it's a framework that uses CSS. It doesn't provide a solution for every layout scenario or a class for every situation. GetBootstrap.com itself, all of the showcase sites, and nearly every theme or Bootstrap supported site on the planet uses custom CSS. You actually have to learn CSS to get the most out of a framework.

  1. Another way, supported on current and legacy browsers is to use display:table on the parent and display:table-caption on the child you want to change the order of. See answer here by dfsq

    https://stackoverflow.com/a/27432782/1004312

    Make sure your images have width:100% on them (see the css example) if you intend to use responsive images with display:table as max-width:100% doesn't work on images inside tables.

  2. The current, modern way using CSS alone is to use flexbox to put elements in the order that you want at a given breakpoint using media queries. Flexbox is supported on modern browsers.

    http://caniuse.com/#feat=flexbox -- see the current support

  3. Another way is to use jQuery insertBefore or insertAfter (whatever is required) on resize/load.

All of of these above methods are client side.

Another way, and it's my preferred way when the content is complicated, is to use server side code (such as php-mobile-detect) and serve up totally different html when the need arises, especially if the content is inappropriate (like freaking large images) for a small device.

Demo of the first three methods: https://jsbin.com/guyenu

Table Caption Example

HTML:

   <h2>Table Caption</h2>
   <div class="table-wrap">
      <section class="content-Y">
         <h2>A</h2>
         <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
      </section>
      <section class="content-X">
         <h2>B</h2>
         <form action="#" method="post" role="form">
            <div class="form-group">
               <label for="name">Text Input:</label>
               <input type="text" name="name" class="form-control" id="name" value="" tabindex="1" />
            </div>
            <div class="form-group">
               <input type="submit" class="btn btn-default" value="Submit" />
            </div>
         </form>
      </section>
   </div>

CSS

/* table caption */
/* https://stackoverflow.com/questions/27432398/vertical-order-grid-in-bootstrap */

.content-X,
.content-Y {
    border: 1px solid red;
    margin: 0 0 10px 0;
}

@media (min-width: 768px) {
    .table-wrap {
        display: table;
    }

    .table-wrap img {width:100%;height:auto;}

    .content-X {
        display: table-caption;
    }
}

Flexbox Example

HTML

   <h2>Flexbox</h2>
   <div class="flex-wrap">
      <section class="content-2">
         <h2>A</h2>
         <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
      </section>
      <section class="content-1">
         <h2>B</h2>
         <form action="#" method="post" role="form">
            <div class="form-group">
               <label for="name">Text Input:</label>
               <input type="text" name="name" class="form-control" id="name" value="" tabindex="1" />
            </div>
            <div class="form-group">
               <input type="submit" class="btn btn-default" value="Submit" />
            </div>
         </form>
      </section>
   </div>

CSS

.content-1,
.content-2 {
    border: 1px solid red;
    margin: 0 0 10px 0;
}
@media (min-width:768px) { 
    .flex-wrap {
        display: -moz-box;
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
        -moz-box-orient: vertical;
        -webkit-box-orient: vertical;
        -webkit-flex-flow: column;
        -ms-flex-direction: column;
        flex-flow: column;
    }
    .content-1 {
        -moz-box-ordinal-group: 1;
        -webkit-box-ordinal-group: 1;
        -webkit-order: 1;
        -ms-flex-order: 1;
        order: 1;
    }
    .content-2 {
        -moz-box-ordinal-group: 2;
        -webkit-box-ordinal-group: 2;
        -webkit-order: 2;
        -ms-flex-order: 2;
        order: 2;
    }
}

jQuery Example

HTML

   <h2>jQuery InsertBefore</h2>
   <div class="content-A">
      <h2>A</h2>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
   </div>
   <div class="content-B">
      <h2>B</h2>
      <form action="#" method="post" role="form">
         <div class="form-group">
            <label for="name">Text Input:</label>
            <input type="text" name="name2" class="form-control" id="name" value="" tabindex="1" />
         </div>
         <div class="form-group">
            <input type="submit" class="btn btn-default" value="Submit" />
         </div>
      </form>
   </div>

CSS

.content-A,
.content-B {
    border: 1px solid red;
    margin-bottom: 10px;
}

jQuery:

$(window).on("resize", function() {

    if($(window).width() >= 768) {

        $(".content-B").insertBefore($(".content-A"));


    } else {

        $(".content-A").insertBefore($(".content-B"));

    }

}).resize();

*Note: .col-xs-12 is not required when using the grid system. Anything under the last min-width will be 100% width.

Full width items do not require the grid system, save yourself some extra wrappers.*

like image 98
Christina Avatar answered Oct 07 '22 18:10

Christina