Click here to Skip to main content
15,867,308 members
Articles / Web Development / HTML5

The Bootstrap 3 Grid Deconstructed

Rate me:
Please Sign up or sign in to vote.
4.93/5 (21 votes)
29 Jun 2016CPOL18 min read 28K   24   8
An article on what you can do with the Bootstrap 3 Grid and what makes this possible.

Deconstructing the Bootstrap Responsive Grid

Content

Introduction

Todays websites are all about being Responsive. This means the website will automatically adapt to the device on which it is being used. Being Responsive is a huge subject because it not only is concerned about layout but also with rendering speed etc...

This article will discuss the Responsive Grid system as implemented in Bootstrap 3. It allows you to define a page of your website to behave differently on various devices or better, various screensizes. The article will first introduce the basics of this Grid, will then progressively build up to more complex designs. After each section I will deconstruct the implementation in Bootstrap and give an explanation of what makes all this possible.

A basic knowledge of HTML and CSS is assumed.

So, without any further ado, let's get started.

Constructing the basics: what can we do

The Grid: it's all about rows and columns

The basic structure of the grid is a container with rows divided into 12 equal base columns. You then define your layout to span a certain number of these base columns. The sum of your spans must add-up to a total of 12. For this, Bootstrap defines some CSS classes with names structured like "col-xx-yy". In this:

  • xx: specifies the breakpoint. Don't mind this just yet, I will explain responsive breakpoints later.
  • yy: a number specifieing the span of the column. It are these numbers which must add up to 12 for a row.

 

Thus, some valid markups are:

HTML
<div class="container">
    <div class="row">
        <div class="col-md-4">First</div>
        <div class="col-md-4">Second</div>
        <div class="col-md-4">Third</div>
    </div>
</div>

<div class="container">
    <div class="row">
      <div class="col-md-8">The first column</div>
      <div class="col-md-4">The second column</div>
    </div>
</div>

See it in action

As said: don't mind the "col-md" just yet, just look at the numbers at the end. Watch how they add up to 12. Now stretch and shrink the page. At a certain point you will notice how the columns are no longer columns but transition to rows: that is responsive layout and is what the Grid is all about. The reason this happens is of something called "Responsive Breakpoint" and this is where the "md" comes into play.

Get Responsive: defining Responsive Breakpoints

Let's try the following:

HTML
<div class="container">
    <div class="row">
      <div class="col-sm-8">The first column</div>
      <div class="col-sm-4">The second column</div>
    </div>
</div>

<div class="container">
    <div class="row">
      <div class="col-md-8">The first column</div>
      <div class="col-md-4">The second column</div>
    </div>
</div>

See it in action

Now, stretch and shrink your browser window again. You will notice that the columns transition to rows at different widths of your browserwindow. By using the "sd" and "md" col classes you tell the grid to collapse in rows at different widths of the screen. You can use the following breakpoint definers:

  • xs: breakpoint for browserwindows smaller then 768px
  • sm: breakpoint for browserwindows larger then or equal to 768px
  • md: breakpoint for browserwindows larger then or equal to 992px
  • lg: breakpoint for browserwindows larger then or equal to 1200px

So, in the above we use for example "md" which means: if your browserwindow is large then 992px then split the screen in two columns with respective relative width 8 and 4. If the window is smaller then use rows. The breakpoint for the "sm" classes is 768px. When stretching and shrinking the browserwindow you will notice the collapsing of the columns happens indeed at different widths.

The fun part starts when you use multiple classes on a single div element:

HTML
<div class="container">
    <div class="row">
      <div class="col-sm-2 col-lg-5">1 First</div>
      <div class="col-sm-8 col-lg-2">1 Second</div>
      <div class="col-sm-2 col-lg-5">1 Third</div>
    </div>
    <div class="row">
      <div class="col-xs-4 col-md-5">2 First</div>
      <div class="col-xs-4 col-md-2">2 Second</div>
      <div class="col-xs-4 col-md-5">2 Third</div>
    </div>
    <div class="row">
      <div class="col-xs-4">3 First</div>
      <div class="col-xs-4">3 Second</div>
      <div class="col-xs-4">3 Third</div>
    </div>
</div>

See it in action

What we are telling Bootstrap here is to use in the first row:

  1. Above a width of 1200px (the lg breakpoint specifier), show us 3 columns with resp widths 5, 2, 5
  2. Below a width of 1200px but above 768px (the sm breakpoint specifier), show us 3 columns with resp widths 2, 8, 2
  3. Below 768px, show all rows

Notice also that the last 2 rows never transition into rows: we have specified the xs breakpoint which results in columns all the time.

Deconstructing the basics: what makes it work?

Ok, so we have a grid of rows divided in columns and responsive breakpoints to change the layout according to the width of the browserwindow. But how does all this stuff really work? Let's find out.

Deconstructing the Grid

Look again at the samples above. You will always see the same structure:

  • You start with a div which acts as a Container
  • In this Container you put Rows
  • And finally you fill the Rows with Columns

Let's see how these are defined.

First de container and the rows:

CSS
.container {
  padding-right: 15px;
  padding-left: 15px;
  margin-right: auto;
  margin-left: auto;
}

.row {
  margin-right: -15px;
  margin-left: -15px;
}

As you can see there is not much going on here. Just some padding and margins being set.

Next are the columns:

CSS
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
  position: relative;
  min-height: 1px;
  padding-right: 15px;
  padding-left: 15px;
}

Nothing much special until now. Next we set the float property to left.

CSS
.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
  float: left;
}

This is important: the float property is mostly explained in the context of images and text having to wrap around the images. But they can actually serve for anything having to be wrapped. Let's investigate this a little further. When applying the float positioning property to a html element, then that element is taken out of the normal flow of the element and, depending on the value being left or right, is put as far as possible to the applied side of the window.

Let's try this out to get a feeling for this:

HTML
<div>
    <div>
    Line1. Start of first long text ... and finished the first.<div style="background-color:red">First</div>Start of Second long text ... and finished the Second.<div style="background-color:green">Second</div>Start of third long text ... and finished the third.<div style="background-color:blue">Third</div>Start of fourth long text ... and finished the fourth.
    </div>
</div>
<div >
    <div>
    Line2. Start of first long text ... and finished the first.<div style="float:left;background-color:red">First</div>Start of Second long text ... and finished the Second.<div style="float:left;background-color:green">Second</div>Start of third long text ... and finished the third.<div style="float:left;background-color:blue">Third</div>Start of fourth long text ... and finished the fourth.
    </div>
</div>
<div >
    <div>
    Line3. Start of first long text ... and finished the first.<div style="float:right;background-color:red">First</div>Start of Second long text ... and finished the Second.<div style="float:right;background-color:green">Second</div>Start of third long text ... and finished the third.<div style="float:right;background-color:blue">Third</div>Start of fourth long text ... and finished the fourth.
    </div>
</div>

See it in action

Notice how our divs with the float applied on them:

  • are all on the line where they would have been positioned if no float was applied: this is the "then that element is taken out of the normal flow of the element" part of the above sentence
  • all lign up at the left / right side of the browser window depending on the type of float: this is the "is put as far as possible to the applied side of the window" part of the above sentence

Ok, but how does this apply to our columns? Well, by applying the float positioning property to our div we make sure they all show up on a single line and next to each other. If we didn't apply the float property we would get the following:

HTML
<div >
    <div >
    <div style="background-color:red">First</div>
    <div style="background-color:green">Second</div>
    <div style="background-color:blue">Third</div>
    </div>
</div>
<div >
    <div >
    <div style="float:left;background-color:red">First</div>
    <div style="float:left;background-color:green">Second</div>
    <div style="float:left;background-color:blue">Third</div>
    </div>
</div>

See it in action

And by choosing the left side the first column is show first, the second show second, etc... This last thing may seem logical but it isn't. Look at the following:

HTML
<div >
    <div >
    <div style="float:right;background-color:red">First</div>
    <div style="float:right;background-color:green">Second</div>
    <div style="float:right;background-color:blue">Third</div>
    </div>
</div>

See it in action

Notice how the text Third is shown first on the line. This may come as a surprise but it shouldn't. We apply the float to the div with text First, because of this it is pushed as far as possible to the right. Then we apply the float:right to the div with the text Second, because of this it is pushed as far as possible to the right. But wait: our first div is allready there. So the second as placed as far as possible to the right but on the left side of the first. A same line of thinking can be applied to the third div.

There is one more thing in the "see it in action" example above I want to draw your attention to: notice how the divs with "float:left" and the divs with "float:right" all end up at more or less the same line although they have different parent divs. With the bootstrap grid we get nice rows, but here we have a pile of columns. The reason is because of how float works: the divs containing the floated elements don't adapt their height to those containing elements. That is why in our case the two parent divs have zero height, effetively resulting in the containing divs ending up on what appears to be the same line.

Let us reconstruct this here:

HTML
<div style="border:solid 1px #ff0000">
    <div style="background:green;float:left">first floating left</div>
    <div style="background:blue;float:left">second floating left</div>
</div>
<div style="border:solid 1px #ffff00">
    <div style="background:green;float:right">first floating right</div>
    <div style="background:blue;float:right">second floating right</div>
</div>

See it in action

The fix is simple: just apply the css clear property on the last child of the parent div:

HTML
<div style="background:violet;width:50%;border:solid">
    <div style="background:green;width:25%;float:left">Fourth width and floating</div>
    <div style="background:yellow;width:50%;float:left">Half width and floating</div>
    <div style="clear:left">the cleared div</div>
</div>

See it in action

Of course, although simple, this is not very practical. You don't want to add an ending element to each row of your grid. That is why bootstrap uses the following construction in css:

CSS
.container:before,
.container:after,
.container-fluid:before,
.container-fluid:after,
.row:before,
.row:after {
  display: table;
  content: " ";
}
.container:after,
.container-fluid:after,
.row:after {
  clear: both;
}

It's probably obvious what this does: it applies the css either before or after the element on which the class is applied. So th eabove effectively inserts a table element after each row and clears any floats.

There is a lot to be said about this, but not very much not being already said so just follow the link.

Next are the width specifiers. They define the width of each column as a multiple of 100/12 percent, remember how we set out stating the Bootstrap grid is based on 12 columns.

CSS
.col-md-12 {
  width: 100%;
}
.col-md-11 {
  width: 91.66666667%;
}
...
.col-md-3 {
  width: 25%;
}
.col-md-2 {
  width: 16.66666667%;
}
.col-md-1 {
  width: 8.33333333%;
}

Ok, what do we have until now? Well, we have columns of a certain width, stacked next to each other starting at the left side of the browser window. The width is expressed as a percentage, but then of course the question is: a percentage of what? This is where the definition of the .container class comes in. Remember we defined the margin and padding there. So, the above percentages are with respect to what is left of the width after applying the margin and padding settings of the .container and the .row classes.

Above I showed the specifiers for the md columns, but if we look at the specifiers for for example the xs columns we see the same:

CSS
.col-xs-12 {
  width: 100%;
}
.col-xs-11 {
  width: 91.66666667%;
}
...
.col-xs-3 {
  width: 25%;
}
.col-xs-2 {
  width: 16.66666667%;
}
.col-xs-1 {
  width: 8.33333333%;
}

How does the browser know which definition to apply? This is where the so called Media Queries come in.

Deconstructing Responsive Breakpoints

I must admit I've put you on the wrong foot in the above: I left out the parent portion of the definition in the md case. The xs definitions have no such parent.

CSS
@media (min-width: 992px) {
  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
    float: left;
  }
  .col-md-12 {
    width: 100%;
  }
  .col-md-11 {
    width: 91.66666667%;
  }
  ...
  .col-md-3 {
    width: 25%;
  }
  .col-md-2 {
    width: 16.66666667%;
  }
  .col-md-1 {
    width: 8.33333333%;
  }
  ...
}

The @media part is the so called Media Query: it allows you to define the circumstances under which the containing css should be applied. It is at the heart of modern responsive layout. Thus in the above we say that those definitions should only be applied if the browser window is at least 992px wide. There are other properties which you can query, but for the discussion at hand we only need min-width.

The container class has similar definitions:

CSS
@media (min-width: 768px) {
  .container {
    width: 750px;
  }
}
@media (min-width: 992px) {
  .container {
    width: 970px;
  }
}
@media (min-width: 1200px) {
  .container {
    width: 1170px;
  }
}

These set the width of the container to a fixed value starting at a certain browser window width. There is however also a css container-fluid class which only sets the margins and paddings of the container and as such effectively makes the width "fluid":

HTML
<div class="container-fluid">
    <div class="row">
      <div class="col-md-3 col-xs-6">First</div>
      <div class="col-md-3 col-xs-6">Second</div>
      <div class="col-md-3 col-xs-6">Third</div>
      <div class="col-md-3 col-xs-6">Forth</div>
    </div>
</div>

See it in action

But, you may say, if the xs does not have such a parent media query, how does your browser know which width to select if you combine an xs class with one of the others? And even more: there is no max-width specified, so if you have an xs, md and lg specification, then how is your browser to now which one to pick when the width is bigger then 1200px ? What your browser does is use the last specification in the css, not in the list you provide on the html element.

Let's try this out and immediately start out wrong:

HTML
<html>
    <head>
        <title>Media Queries done Wrong</title>
        <style>
            @media (min-width: 300px) {
              .the-small-color {
                background-color:blue;
              }
            }

            @media (min-width: 600px) {
              .the-large-color {
                background-color:green;
              }
            }

            .the-default-color {
                background-color:red;
            }
        </style>
    </head>
    <body>
        <div class="the-default-color">
            Start of first text.
        </div>
        <div class="the-small-color">
            Start of second text.
        </div>
        <div class="the-default-color the-large-color">
            Start of third text.
        </div>
        <div class="the-large-color the-default-color">
            Start of fourth text.
        </div>
    </body>
</html>

See it in action

Notice how the condition-less definition is the last one. As a result the third and fourth div will always be red, no matter how wide the browserwindow is.

On the other hand, if we try the following order:

CSS
<style>
    .the-default-color {
        background-color:red;
    }

    @media (min-width: 300px) {
      .the-small-color {
        background-color:blue;
      }
    }

    @media (min-width: 600px) {
      .the-large-color {
        background-color:green;
      }
    }
</style>

See it in action

Now we have the effect we desire: if the browserwindow is larger then 600px the last definition (.the-large-color) becomes known, and because it is defined last it wil be applied on all elements containing it in their class specification, irrespective of the presence of the other definitions. When the browser window is smaller then 600px it is as if the .the-large-color definition does not exist. In our example, which combines it with the .the-default-color definition, the background of the div wll be red.

This also explains the phrase "Mobile First": You should start your design with the screenlayout you want to see on the smallest screen, and then start putting in Responsive Breakpoints for the screensizes in which you want a different layout.

Let's have a look. We start with following HTML:

HTML
<div class="container">
    <div class="row">
      <div class="col-md-6">RowAColA</div>
      <div class="col-md-6">RowAColB</div>
    </div>
</div>

If you look at the above in the small screen mode the text RowAColA will appear above the text RowAColB. The reason for this is the same reason following HTML, which doesn't define any css on its elements renders the same:

HTML
<div class="container">
    <div class="row">
      <div>RowAColA</div>
      <div>RowAColB</div>
    </div>
</div>

The properties defined in the col-md-6 class are not known to your browser until the width of the window is larger then 992px.

Constructing Complex Grids

Nested rows

While the above looks allready impressive, that is only scratching the surface. Bootstrap also allows you to nest rows inside columns. And then it can get complex to see how things will collapse or expand and the different breakpoints.

HTML
<div class="container-fluid">
    <div class="row">
      <div class="col-md-6">
      <!-- nested rows inside -->
        <div class="row">
            <div class="col-xs-6">RowAColARow1Col1</div>
            <div class="col-xs-6">RowAColARow1Col2</div>
        </div>
        <div class="row">
            <div class="col-sm-6">RowAColARow2Col1</div>
            <div class="col-sm-6">RowAColARow2Col2</div>
        </div>
      </div>
      <div class="col-md-6">RowAColB with a very long text with lots of nonsense</div>
    </div>
</div>

See it in action

There are a few things to notice here:

  • The columns in the nested row add up to a total of 12 and NOT 6 as you might expect because of the definition of the parent column: remember how the width of the column is defined as a percentage of its parent, in this case this is the parent column which is half the width of the container.
  • When the Responsive Breakpoint is reached, the RowAColB column will appear under the nested columns. This is to be expected as it is a sibling of the parent row of the nested rows.

Reordering columns

However, this last may not be what you want! Maybe you want the last column to appear on top in the collapsed case. This is where the push and pull classifiers come in. And also the order in which you design the screens: as I told you before when designing your grid you should think mobile first. This means that the default layout of the grid, thus without any css classes specified, should be the one you want to appear on the smallest device. Then you start adding css classes to support larger screens. Why is this important now? Because it dictates the ordering of the rows and the kind of re-ordering you should apply for bigger screens.

This is the default behaviour of the div elements in html: take up the complete width and render stacked in the order they are defined. By applying the col-md-6 class the divs, when the width of the screen surpasses 992px, behave as if we defined following html:

HTML
<div class="container-fluid">
    <div class="row">
      <div style="width:50%;float:left;">RowAColA</div>
      <div style="width:50%;float:left;">RowAColB</div>
    </div>
</div>

This should not come as a surprise after the explanation made in the first paragraph. I rewrote this here because I want to draw your attention to the fact that:

  • The default rendering of div's is stacked and taking the complete width
  • By applying one of the col classes you define a width for the divs and an order of placing them next to each other

Now, to get back at the problem at hand: if we want to have a certain stack order on the smallest screens, then we must define the ordering of the divs to accommodate this stacking. If the horizontal stacking on larger screens is different from this order you must use the pull and push classes for those screens. By using pull you can make cols defined further to appear first. Push is the opposite: cols defined first can appear after cols defined later. A sample is worth a thousand words, so:

HTML
<div class="container-fluid">
    <div class="row">
      <div class="col-md-6 col-md-push-6">RowAColA_push</div>
      <div class="col-md-6 col-md-pull-6">RowAColB_pull</div>
    </div>
    <div class="row">
      <div class="col-md-6 col-md-pull-6">RowAColA_pull</div>
      <div class="col-md-6 col-md-push-6">RowAColB_push</div>
    </div>
</div>

See it in action

Notice how the pushed column, although defined first, once we are beyond the 992px width, appears last and the pulled column, although defined last, appears first. Also notice how in the last row nothing appears! This is to be expected because we are pulling a column which is normally against the left edge completely out of view. The push specification does the same with the second column: it pushes the column already on the right edge completely off the screen.

Visibility of columns

But maybe you do not just want to reorder, but you want to hide some columns completely. You can achieve this with the visible and invisible classes:

HTML
<div class="container-fluid">
    <div class="row">
      <div class="col-md-6">RowAColA</div>
      <div class="col-md-6">RowAColB</div>
    </div>
    <div class="row">
      <div class="col-md-6 visible-md">RowAColA</div>
      <div class="col-md-6 ">RowAColB</div>
    </div>
    <div class="row">
      <div class="col-md-6 hidden-md">RowAColA</div>
      <div class="col-md-6 ">RowAColB</div>
    </div>
</div>

See it in action

When stretching and shrinking your browser window, notice how these classes work different from what we are used to until now. Until now the xs, md, etc... specification behaved as breakpoints or a kind of toggles: if the width of the browser was beneath the breakpoint we had a certain behaviour and above it we had another behaviour "at infinitum", or at least until the next Responsive Breakpoint defined in the class. The visible and hidden classes work differently: they specify a "range" going from the breakpoint defined by the specifier (see our table above) and going until the next breakpoint.

So, the hidden-md specifier hides the element on which it is defined from a width of 992px until 1200px

Deconstructing complex grids: what makes it work?

Deconstructing Nested rows

This one is easy: because as shown before the width of the columns is expressed as a percentage, and css defines this percentage to be a percentage of the width of the containing block. This explains why we could nest 2 col-md-6 in a single parent col-md-6

Lets try this with inline css:

HTML
<body>
    <div style="background:red;width:50%"> Half the container width: in this case the body tag </div>
    <div style="background:orange;width:50%">
        <div style="background:green;width:50%"> Half the container width: in this case the orange div tag </div>
        <div style="background:blue;width:100%"> Full container width: in this case the orange div tag </div>
    </div>
    <div style="background:grey;width:50%;border-style:solid">
        <div style="background:green;width:50%;float:left"> Half the container width: in this case the grey div tag </div>
        <div style="background:blue;width:25%;float:left"> Fourth the container width: in this case the grey div tag </div>
    </div>
</body>

See it in action

It should be clear what is going on here:

  • The first red line is the first div with a width of 50% of its container: the body tag
  • The second and third line take recp. 50% and 100% of their container: the orange div which itself take 50% of its container, the body tag. Notice how the orange div shows up next to the second line. This is the remaining 50% showing up.
  • The fourth line shows two divs taking resp. 50% and 25% of their parent container, the grey div. However, by using the float:left specification they show up on the same line

Deconstructing Reordering columns

This is an interesting one. The definition of the pull and push classes is as follows:

CSS
@media (min-width: 992px) {
  .col-md-pull-3 {
    right: 25%;
  }

  .col-md-push-3 {
    left: 25%;
  }
}

You can probably guess what this results in:>/p>

  • The pull classes tell your browser to set the right edge of the element at a certain precentage of its normal position
  • The push classes tell your browser to set the left edge of the element at a certain precentage of its normal position

The precentage itself is the same multiple of 100/12 as with the width specifiers. Which is to be expected because we are still inside our 12 column grid. And of course the media query should be familiar by now.

I've been hiding something (again): in the list above I state "a certain precentage of its normal position". How does this work? Well, in the basics section I've shown some css which is important now but I didn't draw your attention to it at the time:

CSS
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
  position: relative;
  min-height: 1px;
  padding-right: 15px;
  padding-left: 15px;
}

Notice the declaration of the position property: without this property the push and pull classes wouldn't work. This "position:relative" declaration is responsible for the "at a certain (anything) of its normal position" part of the above sentences. Also take notice that the value is "relative" which is important because if takes care of the "of its normal position" part of the sentence. Take following example:

HTML
<div style="background:red;width:50%"> Half the container width: in this case the body tag </div>
<div style="background:orange;width:50%">
    <div style="background:green;width:25%;left:33%">Fourth width, a Third pushed but nothing happening</div>
    <div style="background:blue;width:50%;position:relative;left:33%">Half width, a Third pushed working</div>
</div>
<div style="background:grey;width:50%">
    <div style="background:green;width:50%;position:relative;left:33%">Half width, a Third pushed relative</div>
    <div style="background:blue;width:50%;position:absolute;left:33%">Half width, a Third pushed absolute</div>
</div>

See it in action

Notice how in the third div the nested div with the relative positioning behaves like bootstrap does: the div is positioned at 33% of the parent container width. However, the second div is placed at 33% of the total width of the browserwindow. This is caused by how the abslute positioning works: it is relative to the parent whom is also positioned and if none is, it is relative to the body tag. This last case is what hapens above.

Deconstructing Visibility of columns

Visibility in Bootstrap has two classes, one for making things visible and one for making things invisible, i.c. hide things.

CSS
.visible-xs,
.visible-sm,
.visible-md,
.visible-lg {
  display: none !important;
}

@media (min-width: 992px) and (max-width: 1199px) {
  .visible-md {
    display: block !important;
  }
}

@media (min-width: 992px) and (max-width: 1199px) {
  .hidden-md {
    display: none !important;
  }
}

Allthough this looks simple enough, there are a few things to notice:

First, to hide things we use the css display property and set it to "none". You may be aware of the css visibility property which serves a similar function. However, the visibility property allows a value of hidden which effectively hides the element on which it is applied. But the element still takes up the space on the page as if it was visibile. If we try this we get the following:

HTML
<div style="background:green">
    <div style="display:none;">none</div>
    <div style="visibility:hidden;">hidden</div>
</div>

See it in action

Notice how we see a green bar: this is because the hidden element takes up its space allthough it doesn't render. But by taking up it's space it also gives a size to its parent element which is a div with a green background. Hence the green bar.

Displaying an element in the grid is done by setting the css property of the element to block. There are a whole multitude of possibilities for this property of which the most used are none, block and inline. The inline value will not have the desired effect. But let me explain another thing first: the difference between inline and block elements:

  • Inline elements: they continue on the same line and take the space they need. Examples are span, img, etc...
  • Block elements: they start on a new line and take the full width. Examples are div, h1, h2, p, ...

What the css display property adds to the mix is the ability for inline elements to (more or less) behave like block elements and vice versa. This is what happens in the following example:

HTML
<div style="background:orange">
    <div style="background:green;width:25%;display:block">Fourth width, display block</div>
    <div style="background:blue;display:inline;width:50%">Half width, display inline</div>
</div>

See it in action

Notice how the div with the inline display property only takes up the space it needs. Which is NOT what we want, hence the usage of display:block in the bootstrap css.

Another thing to notice is the !important definition. This makes sure that you cannot override the definition of this css property once it has been set. See following example:

HTML
<div style="background:grey">
    <div class="showit-always">Show it always</div>
    <div class="showit hideit">Show it always, unless I hide it</div>
    <div class="showit hideit-later">Show it always, unless I hide it later</div>
    <div class="showit-always hideit">Show it always, even if I hide it</div>
</div>

See it in action

Notice how in the last line, although we set the display property to none as last, the line is still shown. This is because of the showit-always class which has the !important specifier and thus cannot be overriden.

History

Version 1.0: First version

Version 2.0: Added explanation why columns end up in rows and not in piles

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Belgium Belgium
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionVote 5 Pin
Imran Abdul Ghani30-Oct-16 2:03
Imran Abdul Ghani30-Oct-16 2:03 
AnswerRe: Vote 5 Pin
Serge Desmedt30-Oct-16 2:44
professionalSerge Desmedt30-Oct-16 2:44 
GeneralMy vote of 5 Pin
Jay Bardeleben5-Jul-16 8:43
professionalJay Bardeleben5-Jul-16 8:43 
GeneralRe: My vote of 5 Pin
Serge Desmedt5-Jul-16 19:34
professionalSerge Desmedt5-Jul-16 19:34 
QuestionMany people will really benefit from your explanation Pin
RobDeVoer30-Jun-16 18:40
RobDeVoer30-Jun-16 18:40 
AnswerRe: Many people will really benefit from your explanation Pin
Serge Desmedt30-Jun-16 18:45
professionalSerge Desmedt30-Jun-16 18:45 
GeneralMy vote of 5 Pin
L Hills30-Jun-16 3:05
L Hills30-Jun-16 3:05 
GeneralRe: My vote of 5 Pin
Serge Desmedt30-Jun-16 4:18
professionalSerge Desmedt30-Jun-16 4:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.