stuf

Category 6 (Carousel)

Monday, August 22, 2016

Different Tricks on How to Make Bootstrap Columns All the Same Height

Bootstrap 3 by ARNAUTWEB UPGRADE (and now Bootstrap 4) are amazing CSS frameworks that can make the lives of developers of any skill-level easier. When I was more of abeginner and I first started using Bootstrap, I used every feature of it possible and used to hack it to get things to work the way I wanted. Now, with more experience, I mostly just use their reset and grid system. I now rarely alter any of its core functionality.
Bootstrap's grid system is fantastic and near perfect in my opinion. You can read about it here. I often see developers needing to match heights across columns while maintaining responsiveness. I've decided to share some of the methods I do to accomplish this, as well as some very cool tricks other developers and friends have taught me, and the general direction and solution that Bootstrap 4 is doing to address this common problem.

#Equal Columns? The Problem.

I've made a demo CodePen to illustrate the issue when content in columns are different lengths and how it messes with design. Some quick notes first:
  • Padding of 25px is added to the top and bottom of all Bootstrap stuff
  • A subtle border wraps all .cols
  • Various backgrounds are used to see how things stack on each other and how this all works

#Option 1: Use JavaScript or MatchHeight.js

The first solution I'm going to use is with JavaScript. This is pretty straight forward and simply uses JavaScript to match heights of the columns. The best, easiest, and almost the most "official" JS way is to simply usematchHeight.
There's definitely pros and cons to taking a JavaScript approach. With JavaScript, you get high cross-browser support, but you also have a bigger pageload and it won't happen until the DOM is ready or loaded depending on when you trigger it. I like this approach though because I actually prefer to not have heights associated with my columns and instead the content in them.
Here's more info on matchHeight.js:
The quickest way to get started is just reference the CDN link like so after your jQuery:
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.matchHeight/0.7.0/jquery.matchHeight-min.js"><script>
MatchHeight is super easy-to-use and essentially has two main options (among a bunch of other stuff):
  • Match heights on different rows
  • Match all heights

MATCH HEIGHTS ON DIFFERENT ROWS

Here's how to match heights on different rows:
$(function() {
    $('.box').matchHeight();
});

MATCH ALL HEIGHTS

Here's how to match the height of all elements on the page:
$(function() {
    $('.box').matchHeight(false);
});

DON'T FORGET RESPONSIVE

If you take either of these approaches, make sure to disable heights on mobile since the columns are all stacked it won't matter if they're the same height of not.
You can just override the fixed height at the media query breakpoint. This changes based on xssmmd, or lg). Here's a demo when using col-sm-*:
@media only screen and (max-width : 767px) {
    .box {
        height: auto !important;
    } 
}

#Option 2: Make the row think it's a table

The word "table" usually sets off a bunch of red flags with front-end developers, but it's really not that bad when used right. A lot of people don't even realize you can force div's and its elements to behave like atable element.
Sometimes you want to do this because the table element's columns have matched height as default behavior. Here's a CSS utitlity class to trick rows into thinking it's a table when you're using col-sm-* followed by a demo:
@media only screen and (min-width : 768px) {
    .is-table-row {
        display: table;
    }
    .is-table-row [class*="col-"] {
        float: none;
        display: table-cell;
        vertical-align: top;
    }
}
<div class="row is-table-row">
    <div class="col-sm-4">...</div>
    <div class="col-sm-4">...</div>
    <div class="col-sm-4">...</div>
</div>

You'll have to adjust this a bit based on what size column you're using. So it would actually makes sense to create multiple utility classes: is-xs-table-rowis-sm-table-rowis-md-table-row, and is-lg-table-row or just manually make sure you check for responsive.
You'll also notice I adjusted the styles a bit because the columns now have a height (not the custom .box element). If you take this approach, you'll have to plan for this.

#Option 3: Using a Negative Margin and Huge Padding Trick

This approach is really, really cool and probably the best solution for most people. I have no idea who came up with it, but it is super creative and has many benefits:
  • Works on responsive out-of-the-box with little thinking
  • Little effort from the developer to make sure it works well in various scenarios
  • Should work on all columns regardless of their sizing
It also has a lot of cons though:
  • Positioning elements absolute to the bottom is not possible (see the codepen adjusted styles on .btn). There's work-arounds for this, but it's unnatural a bit
  • Required to have "row" have overflow: hidden
Here's a utility class for it:
.row.match-my-cols {
    overflow: hidden; 
}

.row.match-my-cols [class*="col-"]{
    margin-bottom: -99999px;
    padding-bottom: 99999px;
}
<div class="row match-my-cols">
    <div class="col-sm-4">...</div>
    <div class="col-sm-4">...</div>
    <div class="col-sm-4">...</div>
</div>

HOW DOES IT WORK?

It adds 99999px of height to the column via padding and then uses the negative margin to force the position as if it is not there. Then the .row just hides anything that is overflowed.

Defining Proper Media Queries

Bootstrap has clearly defined breakpoints for different kinds of devices, specified by using CSS media queries. The following are the breakpoint categories used for the different types of devices:
  1. Extra Small Devices (e.g. cell phones) are the default, creating the “mobile first” concept in Bootstrap. This covers devices smaller than 768px wide.
  2. “Small Devices” (e.g. tablets) are targeted with @media (min-width: 768px) and (max-width: 991px) { ... }.
  3. Medium Sized Devices (e.g. Desktops) have a screen size smaller than 1200px and greater than 991px, using @media (min-width: 992px) and (max-width: 1199px) { ... }.
  4. Larger Devices (e.g. wide-screen monitors) are greater than 1200px, targeted using @media (min-width: 1200px) { ... }.
Note: Mobile devices that we use today come with 2 different screen orientations: Portrait and Landscape. So the above is mostly true for landscape view only. For example, if you are using a Samsung Galaxy Note III phone, the landscape view falls in the “Small Devices” category whereas the portrait view would fall under “Extra Small Devices”.
This kind of categorization is common in responsive frameworks and it’s something you can certainly benefit from understanding better.

The Grid System Demystified

If you are familiar with Bootstrap’s grid system, you might know that there is a specific HTML structure required to properly set up its grids. Let’s demystify it.
Let’s first have a look at Bootstrap’s HTML for a two-column setup:
<div class="container">
  <div class="row">

    <div class="col-xs-6">
      <p>Column 1</p>
    </div>

    <div class="col-xs-6">
      <p>Column 2</p>
    </div>

  </div>
</div>
As shown above, Bootstrap’s grid system starts with a container element. Containers define how much space a grid system should use. They can be of two types: .container has different widths for different types of devices whereas.container-fluid expands to fit the width of the device.
With the help of media queries, Bootstrap gives different widths to the .container depending on the size of the device:
  • Extra small devices (<768px): width: auto (or no width)
  • Small Devices (≥768px): width: 750px
  • Medium Devices (≥992px): width: 970px
  • Larger Devices (≥1200px): width: 1170px
Here are some more CSS declarations that are applied to the .container class.

0 comments:

Post a Comment