Freebie: Responsive Equal Height Columns in Bootstrap

Create seamless responsive equal height columns in Bootstrap with the jquery.matchHeight plugin.

Yes, it’s Javascript!

Before we begin I should point out that you can achieve equal height columns with just CSS but for the purpose of this tutorial we wanted to create some more robot and generic which could be reused from multiple Bootstrap components without any additional code per component.

Meet jquery.matchHeight.js

For the heavy lifting in this tutorial we’ll be using a third-party plugin called jquery.matchHeight.js created & maintained by Liam Brummitt. jquery.matchHeight.js will handle the actual height comparisons and setting of the equal heights.

jquery.matchHeight.js offers a nice data-api so like Bootstrap itself it’s quick & simple to fire the plugin without needing to write any javascript. The data-api works by “grouping” elements which should have their height compared and set this makes nested height matching very easy.

Only limitations the plugin has are as follows and we’ll fix them in this tutorial:

  • The data-api doesn’t allow you to pass plugin settings/options- we’ll fix this by adding a new data-bootstrap-eh-settings data attribute which can contain global and per group settings
  • Adding a data attribute to all elements in a large group of elements can be cumbersome – we’ll fix this by allowing a wrapper element to declare a class for selecting elements within the wrapper to compare the height of.

We love using third-party (especially Open Source ones) plugins to save us time in initial development and in maintenance.

Demos

Let’s dive in with some demos. The matchHeight plugin uses the data attributes data-match-height="GROUP" or data-mh="GROUP" so save confusion and to give us more control we’ll create our own data-bootstrap-eh="GROUP" which we’ll apply to all elements that should have their height compared and set.

Demo 1: Simple Grouping

We’ll take a simple 3 column grid layout and add our own data-bootstrap-eh="column" attributes to create a “group” of elements to compare and set the height of. All elements with data-bootstrap-eh="column" will be considered the “group” called “column” and have their heights compared and set. NOTE: Group names can be anything you like but should be all lowercase and not contain any punctuation.

<div class="container-fluid">
  <div class="row">
    <!-- Col 1 -->
    <div class="col-md-4 bg-info" data-bootstrap-eh="column">
      <h3>Column 1 Content</h3>
      <ul>
        <li>Lorem ipsum dolor sit amet consectetuer.</li>
        <li>Aenean commodo ligula eget dolor.</li>
        <li>Aenean massa cum sociis natoque penatibus.</li>
      </ul>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.</p>
      <p>Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>                  
    </div>
    
    <!-- Col 2 -->
    <div class="col-md-4 bg-warning" data-bootstrap-eh="column">
      <h3>Column 2 Content</h3>
      <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>                
    </div>
    
    <!-- Col 3 -->
    <div class="col-md-4 bg-danger" data-bootstrap-eh="column">
      <h3>Column 3 Content</h3>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec qu</p>                  
    </div>
  </div>
</div>

 

Demo 2: Simple Nested Grouping

“Groups” can be created anywhere on the page and as each group is evaluated and compared separately you can even “nest” groups within groups. The following example adds as new “group” called “nested-column” within the first column.

<div class="container-fluid">
  <div class="row">
    <!-- Col 1 -->
    <div class="col-md-4 bg-info" data-bootstrap-eh="column">
      <h3>Column 1 Content</h3>
      <ul>
        <li>Lorem ipsum dolor sit amet consectetuer.</li>
        <li>Aenean commodo ligula eget dolor.</li>
        <li>Aenean massa cum sociis natoque penatibus.</li>
      </ul>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.</p>
      <p>Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>
      
      <!-- Nested Group -->
      <div class="row">
        <div class="col-md-6 bg-warning" data-bootstrap-eh="nested-column">
          <h4>Nested</h4>
          <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.</p>
          <p>Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
        </div>
        <div class="col-md-6 bg-danger" data-bootstrap-eh="nested-column">
          <h4>Nested</h4>
          <p>Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
        </div>                    
      </div>                  
    </div>
    
    <!-- Col 2 -->
    <div class="col-md-4 bg-warning"  data-bootstrap-eh="column">
      <h3>Column 2 Content</h3>
      <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>                
    </div>
    
    <!-- Col 3 -->
    <div class="col-md-4 bg-danger"  data-bootstrap-eh="column">
      <h3>Column 3 Content</h3>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec qu</p>                  
    </div>
  </div>
</div>

Demo 3: Wrapper Grouping

Say you have a grid with multiple rows of elements, it would be cumbersome to have to add data-bootstrap-eh="column" to every single element you want to group so you can also use the data-bootstrap-eh attribute on a parent wrapper element and pass it an HTML class to match child elements with.

In the following example we add data-bootstrap-eh=".col-md-4" to the wrapper element which will create a “group” of all elements within the wrapper which have the class .col-md-4.

<div class="container-fluid">
  <div class="row" data-bootstrap-eh=".col-md-4">
    <!-- Col 1 -->
    <div class="col-md-4 bg-info">
      <h3>Column 1 Content</h3>
      <ul>
        <li>Lorem ipsum dolor sit amet consectetuer.</li>
        <li>Aenean commodo ligula eget dolor.</li>
        <li>Aenean massa cum sociis natoque penatibus.</li>
      </ul>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.</p>
      <p>Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>  
    </div>
    
    <!-- Col 2 -->
    <div class="col-md-4 bg-warning">
      <h3>Column 2 Content</h3>
      <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>  
    </div>
    
    <!-- Col 3 -->
    <div class="col-md-4 bg-danger">
      <h3>Column 3 Content</h3>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec qu</p>                  
    </div>
    
    <!-- Col 4 -->
    <div class="col-md-4 bg-danger">
      <h3>Column 3 Content</h3>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec qu</p>                  
    </div>
    
    <!-- Col 5 -->
    <div class="col-md-4 bg-info">
      <h3>Column 1 Content</h3>
      <ul>
        <li>Lorem ipsum dolor sit amet consectetuer.</li>
        <li>Aenean commodo ligula eget dolor.</li>
        <li>Aenean massa cum sociis natoque penatibus.</li>
      </ul>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.</p>
      <p>Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>  
    </div>
    
    <!-- Col 6 -->
    <div class="col-md-4 bg-warning">
      <h3>Column 2 Content</h3>
      <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia</p>  
    </div>
  </div>
</div>

 

Demo 4: Plugin Options/Settings

As we mentioned at the start the matchHeight plugin doesn’t by default allow you to pass options/settings via it’s data-api so we’ve added this in using another data attribute.

The matchHeight plugin offers the following options:

  • byRow is true or false to enable row detection – set to false to make all elements in group the same height regardless of the row they are on
  • property is the CSS property name to set (e.g. 'height' or 'min-height')
  • target is an optional element to use instead of the element with maximum height
  • remove is true or false to remove previous bindings instead of applying new ones

Simple Group Settings: data-bootstrap-eh-settings-GROUPNAME

If you’re using simple grouping then you can pass plugin options/settings by adding a data-bootstrap-eh-settings-GROUPNAME attribute to any element on the page.

<div data-bootstrap-eh-settings-GROUPNAME='{"byRow":false, "property":'height', "target":null, "remove":false}'></div>

 

Wrapper Group Settings: data-bootstrap-eh-settings

If you’re using wrapper grouping then you can pass plugin options/settings by adding a data-bootstrap-eh-settings attribute to the wrapper element.

<div data-bootstrap-eh=".col-md-4" data-bootstrap-eh-settings='{"byRow":false, "property":'height', "target":null, "remove":false}'></div>

 

Extended Demos

To expand on the basic usage demos we’ve also put together some extended demos using default Bootstrap components.

Within the extended demos you’ll notice we’ve used the matchHeight plugin hooks we’ve also added some HTML classes to group elements depending on their state which you can use in your own CSS:

  • .bootstrap-eh: height has been compared
  • .bootstrap-eh-active height has been set (is active)

We’ve also added the following CSS helper classes:

  • .bootstrap-eh-pull-center: (Experimental) which can be used to pull elements to the center of their container once the height of the container has been set. See demo 6
  • .bootstrap-eh-pull-bottom: which can be used to pull elements to the bottom of their container once the height of the container has been set. See demo 3

Summary

Let us know what you think via our contact form.

Credits

jQuery MatchHeight plugin by Liam Brummitt

License

  • jquery.matchHeight.js is licensed under The MIT License (MIT). Copyright (c) 2014 Liam Brummitt
  • All other tutorial files can be used and abused at your will but a link back to this article would be greatly appreciated.

No Coments

    Leave a Reply

    Your email address will not be published. Required fields are marked *