HTML & CSS
Article

Bourbon Refills Provide Drop-In Design and Functionality

By M. David Green

All the advantages of design templates and web component frameworks without surrendering control of your source code.

The Bourbon Refills Philosophy

If you’re tired of sacrificing your standards to templates designed by people who may not share your concern for clean and consistent source code, or frameworks that want to take over your entire site, you may be ready to try Bourbon Refills.

The Refills library consists of a useful selection of independent and customizable web page ingredients such as accordions, tabbed navigation, footers, font stacks, and other conveniences. Bourbon Refills are available as sets of coordinated HTML, SCSS, and jQuery code ready to use in your site to provide layout, functionality, and design in quick snippets.

Unlike all-or-nothing web frameworks that only work best if you adapt your entire site to their conventions, Refills can be surgically applied inside any site that can support a basic lightweight Bourbon structure with Neat and Bitters, regardless of whether the rest of the site is based around Bourbon. Refills are community supported, but the bulk of the work to compile and curate the library has been done by the developers at Thoughtbot, who are also the force behind Bourbon.

One of the nicest aspects of the Refills library is that each pattern or component is completely independent of the others. The Refills elements are all responsive thanks to Neat, and follow conventions that make them unobtrusive and portable, such as avoiding CSS nesting more than two levels deep, keeping styling to a minimum, and operating with internally-scoped variables.

You can even contribute new patterns and components that you’ve developed to help extend the library, as long as you make sure you’re following the guidelines.

Getting Started with Refills

To use the Refills library successfully, you need to have a few basic requirements present on your site:

  • Bourboun (4.0+)
  • Neat
  • Bitters (10.1+)
  • jQuery (for elements that require JavaScript)

It’s not hard to set up all of these tools to run seamlessly during development, and deploy easily to production. I’ve written some other articles on Sitepoint about Bourbon, Neat, and Bitters, and how to get up and running with them quickly.

That may sound like you’re adding a lot of potential weight to your page if all you want is a quick header, footer, and a few widgets. But keep in mind the way that Bourbon works. When you compile the Sass for your page, Bourbon and Neat practically disappear unless you explicitly use something. Bitters is a very lightweight set of style adjustments that’s comprable in size to a basic CSS reset (which is also recommended for cross-browser consistency). And jQuery is almost ubiquitous, and adds so much value in terms of convenient cross-browser compatible JavaScript that it’s likely you’re already using it. And if you load jQuery from a content distribution network (CDN), it may already be cached on your visitor’s browser by the time they get to your page.

Once you’re set up, all you need to do is browse the Refills pages to find the elements you want to add to your site, and copy and paste the code provided into your HTML, Sass, and JavaScript files.

Yes, I said copy and paste. Calm down. There’s a method to the madness.

Unlike other libraries that live in isolation and get called in dynamically when needed, Refills are designed to be incorporated and modified inside your code. Many Refills elements include sample HTML that you will want to modify with your own content, and most of the Sass and JavaScript is subject to other changes you will probably want to make to adapt it to your own site’s style. Refills just provide you with a starting point, not a final destination.

Adding a modified Refill to your site is like using a custom-generated widget, except that you have total control over what gets changed while you’re making the modifications. Often, the HTML provided can be viewed more as a usage example than as a required piece of code. For example, the HTML for the “Tables” pattern just shows a standard table with a custom class that triggers the Refills styling.

This approach means that the Refills library doesn’t care how you choose to organize your files, as long as each piece is pasted into a place where your stack will be able to find and interpret it. For example, if you use a modular approach to Sass compilation, you might want to create a separate module-name.scss file for the SCSS code of each refill you choose to use, and then @import those files in your main.scss file with any other modular components you may have already defined. Refills will support that approach just as easily as any other.

Patterns

The Refills library contains an appealing selection of familiar-looking presentation components that they call patterns. If you are familiar with the typical appearance of many sites built on top of Twitter Bootstrap or Zurb Foundation, most of these elements will look quite familiar. The difference is that you can pick and choose the ones you want to have in your code, and leave the rest of your site the way you want it to appear.

Among the patterns are tabbed navigation, card-style presentation elements (with optional ribbons overlays), flexible grids for presenting images or information, standard headers with drop-down menu navigation, hero boxes, different footer styles, styled tables, a Google Maps widget, along with several others. You can drop any of them right into an unstyled site to make it look clean and orderly with little or no visual design in advance, and get an acceptable minimalist result to build upon.

The elements are very basic, but that leaves you plenty of room to customize and modify them to suit the needs of the design. Thanks to the integration with Bitters, you can easily change visual aspects such as universal border styling or color palette, and have these changes cascade throughout your design. Refills patterns also derive their responsive nature from a seamless integration with Neat grid layouts for Bourbon.

A typical example pattern is the on-page navigation scroller. This lets you create a table of contents at the top of a page, and navigate down to any section of the page with a smooth animated scroll, returning to the table of content with “Back to top” buttons by default.

This pattern starts with some simple standard HTML, tagged with a couple of classes and IDs that the CSS and JavaScript will use to target the actions:

<div class="scroll-on-page">
  <aside id="scroll-on-page-top">
    <a class="scroll-on-page-link" href="#scroll-link-1">First Scroll Link</a>
    <a class="scroll-on-page-link" href="#scroll-link-2">Second Link</a>
    <a class="scroll-on-page-link" href="#scroll-link-3">Last Link</a>
  </aside>

  <article>
    <section>
      <h4 id="scroll-link-1">First Target</h4>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum aliquid necessitatibus, repudiandae veniam labore, consequatur maiores dolore unde non deleniti, aliquam minima ex nulla error eveniet vel tempore, in incidunt?</p>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum aliquid necessitatibus, repudiandae veniam labore, consequatur maiores dolore unde non deleniti, aliquam minima ex nulla error eveniet vel tempore, in incidunt? Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum aliquid necessitatibus, repudiandae veniam labore, consequatur maiores dolore unde non deleniti, aliquam minima ex nulla error eveniet vel tempore, in incidunt?</p>
    </section>
    <section>
      <h4 id="scroll-link-2">Second Target</h4>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum aliquid necessitatibus, repudiandae veniam labore, consequatur maiores dolore unde non deleniti, aliquam minima ex nulla error eveniet vel tempore, in incidunt?</p>
    </section>
    <section>
      <h4 id="scroll-link-3">Last Target</h4>
      <p>lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum aliquid necessitatibus, repudiandae veniam labore, consequatur maiores dolore unde non deleniti, aliquam minima ex nulla error eveniet vel tempore, in incidunt? Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum aliquid necessitatibus, repudiandae veniam labore, consequatur maiores dolore unde non deleniti, aliquam minima ex nulla error eveniet vel tempore, in incidunt? Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum aliquid necessitatibus, repudiandae veniam labore, consequatur maiores dolore unde non deleniti, aliquam minima ex nulla error eveniet vel tempore, in incidunt?</p>
      <a class="scroll-on-page-link" href="#scroll-on-page-top">Back to top</a>
    </section>
  </article>
</div>

As you can see, this is clearly just placeholder content, and you would most likely use it as a model for developing and tagging your own page content rather than copying it verbatim. The dummy copy is long so you can see how the vertical scrolling works without making the page ridiculously short.

The next code section provides the SCSS for sample styling that responsively keeps the navigation elements in a separate aside from the article containing the navigable sections:

.scroll-on-page aside {
  @include media($large-screen) {
    @include span-columns(4);
  }
}

.scroll-on-page-link {
  border-bottom: 1px solid transparentize($base-link-color, .8);
  padding: $base-spacing / 2 0;
  margin-right: $base-spacing;
  display: block;

  &:last-child {
    margin-bottom: $base-spacing;
  }
}

.scroll-on-page article {
  h4 {
    margin-bottom: .5em;
  }

  section p:last-of-type {
    margin-bottom: 2em;
  }

  @include media($large-screen) {
    @include span-columns(8);
  }
}

// Based on code by http://codepen.io/xmark/

Finally, there’s a section with some JavaScript to facilitate the navigation:

(function (jQuery) {
  jQuery.mark = {
    jump: function (options) {
      var defaults = {
        selector: 'a.scroll-on-page-link'
      };
      if (typeof options == 'string') defaults.selector = options;
      var options = jQuery.extend(defaults, options);
      return jQuery(options.selector).click(function (e) {
        var jumpobj = jQuery(this);
        var target = jumpobj.attr('href');
        var thespeed = 1000;
        var offset = jQuery(target).offset().top;
        jQuery('html,body').animate({
          scrollTop: offset
        }, thespeed, 'swing')
        e.preventDefault();
      })
    }
  }
})(jQuery);


jQuery(function(){
  jQuery.mark.jump();
});

In this case, the complete jQuery implementation is included just the way you would place it inside a <script> element, with the jQuery variable being used in scope as opposed to the more familiar $ variable. As you explore the Refills library, you may notice that some elements only show the jQuery code you would use inside your (function (jQuery) { ... })(jQuery); block. You might also prefer to use the $ inside your function’s scope, since it’s already protected. But these choices are left to you, and you need to pay attention to them as you move from one Refills element to another, since they aren’t consistent.a

Components

Unlike Refills Patterns, the Refills Components tend to be smaller widgets that could live inside of a larger context on a page. However, many of them will still appear quite familiar to people who have worked with other CSS frameworks in the past, or seen the conventions appear on different sites. Some of the smaller ones seem to be little more than logical extensions to the Bourbon Bitters library, while others provide much more functionality.

Among the components you can choose from are accordion menus, breadcrumb trails, badges, button groups, fade-in elements, flash messages, hover animations, pagination, a parallax scrolling implementation, progress bars, a sliding menu, a set of common textures, a tooltip, and several others.

Again, the focus is on making these components as independent and generic as possible, and letting them inherit from the styling carried forward from Bitters.

One of my favorites uses a nifty HTML trick to provide an interactive modal element which doesn’t rely on any JavaScript, but instead takes advantage of the ability to style elements based on the state of a hidden HTML checkbox and the CSS sibling selector.

For this one, the HTML provided is again very straightforward:

<div class="modal">
  <label for="modal-1">
    <div class="btn js-btn">Click for Modal</div>
  </label>
  <input class="modal-state" id="modal-1" type="checkbox" />
  <div class="modal-window">
    <div class="modal-inner">
      <label class="modal-close" for="modal-1"></label>
      <h1>Modal Title</h1>
      <p class="intro">Intro text lorem ipsum dolor sit ametm, quas, eaque facilis aliquid cupiditate tempora cumque ipsum accusantium illo modi commodi  minima.</p>
      <p class="body">Body text lorem ipsum dolor ipsum dolor sit sit possimus amet, consectetur adipisicing elit. Itaque, placeat, explicabo, veniam quos aperiam molestias eriam molestias molestiae suscipit ipsum enim quasi sit possimus quod atque nobis voluptas earum odit accusamus quibusdam.</p>
    </div>
  </div>
</div>

You may want to change some of the classes such as “body” and “intro” to match the way you handle your content classification. The SCSS is where the magic happens. And in this case, it’s been written in such a way that it handles a number of cross-browser issues very cleanly, while following a number of good practices, and remaining responsive:

.modal {
  $modal-padding: 3em;
  $modal-background: $base-background-color;
  $modal-close-color: $light-gray;
  $modal-image-height: 135px;
  $modal-image-width: $modal-image-height;

  label {
    cursor: pointer;
    margin-bottom: 0;
  }

  label img {
    $img-width: 300px;
    border-radius: $img-width/2;
    display: block;
    max-width: $img-width;
  }

  input[type="checkbox"] {
    display: none;
  }

  .btn {
    @extend button;
  }

  .modal-open {
    overflow: hidden;
  }

  .modal-window { // overlay
    @include transition(opacity .25s ease);
    @include position(fixed, 0px 0px 0px 0px);
    background: rgba(0,0,0, .85);
    opacity: 0;
    text-align: left;
    visibility: hidden;
    z-index: 99999999999;

    .modal-bg {
      @include position(absolute, 0px 0px 0px 0px);
      cursor: pointer;
    }
  }

  .modal-close {
    @include position(absolute, ($modal-padding /2) ($modal-padding /2) null null);
    @include size(1.5em);
    cursor: pointer;
    background: $modal-background;

    &:after,
    &:before {
      @include position(absolute, 3px 3px 0 50%);
      @include transform(rotate(45deg));
      @include size(.15em 1.5em);
      background: $modal-close-color;
      content: ';
      display: block;
      margin: -3px 0 0 -1px;
    }

    &:hover:after,
    &:hover:before {
      background: darken($modal-close-color, 10);
    }

    &:before {
      @include transform(rotate(-45deg));
    }
  }

  .modal-inner {
    @include transition(opacity .25s ease);
    border-radius: $base-border-radius;
    background: $modal-background;
    margin: auto;
    max-height: 95%;
    position: relative;
    overflow: auto;
    width: 95%;
    padding: $modal-padding /2;
    margin-top: .6em;

    @include media($medium-screen) {
      padding: $modal-padding;
      width: 60%;
      max-height: 60%;
      margin-top: 10em;
    }

    @include media($large-screen) {
      width: 50%;
      margin-top: 10em;
    }

    h1 {
      color: $base-font-color;
      margin-bottom: .6em;
      text-align: left;
      text-transform: capitalize;
    }

    p.body, p.intro {
      font-size: $base-font-size;
      max-width: 100% !important;
      text-align: left;

      &.intro {
        color: $blue;
        line-height: 1.6em;
      }

      &.body {
        color: $base-font-color;
        line-height: 1.45em;

        @include media($medium-screen) {
          @include columns(2 8em);
        }
      }
    }

    a.cta {
      color: white;
      display: inline-block;
      margin-right: .5em;
      margin-top: 1em;

      &:last-child {
        padding: 0 2em;
      }
    }
  }

  .modal-state:checked + .modal-window {
    opacity: 1;
    visibility: visible;
  }

  .modal-state:checked + .modal-window .modal-inner {
    top: 0;
  }
}

// Based on code by Kasper Mikiewicz

As you can see the responsive code is baked into the SCSS by default, and that is subject to the way you prefer to handle responsiveness. It’s easy to copy and paste these elements in, but it’s vital to read through the code and understand how it does its magic once you get it into your page.

Note that the original code on which this trick was based came from Kasper Mikiewicz, and the curators of Bourbon Refills are careful to credit the source for any code they use.

Type Systems

The third convenience provided by Bourbon Refills is a set of elegant and carefully tuned type systems designed to pick up where Bitters leaves off, providing custom font matching that can give a site that special something extra. These are also set up with consistent vertical rhythm for a pleasing and readable effect with blocks of text. That’s very important if you run a blog and expect your readers to go through multiple paragraphs of text.

The type systems provided include serif, sans-serif, traditional, slab, and others. These names should be familiar to anyone using fonts in the modern web era, but the Refills site gives visual examples with each one, just so you can be sure you’re getting what you want. And once you apply a Type System, you will see its style reflected in any Refills element that falls within the scope you’ve defined.

Another advantage to using Refills is that the fonts are set up to degrade gracefull to native fonts that fulfill the same design goals as the custom fonts if downloadable fonts aren’t supported. This is done in a way that should work well across different operating systems which may not all have the same fonts available.

A typical Type System Refill is the Rounded Sans-Serif. This Refill starts again with sample HTML that you would be more likely to use as a guide than to copy and paste directly into your site. The key thing to notice is that the <head> element includes link elements that pull in the actual font files from Google’s CDN, for fast and consistent access:

<head>
  <link href='http://fonts.googleapis.com/css?family=Nunito:400,700,300' rel='stylesheet' type='text/css'>
  <link href='http://fonts.googleapis.com/css?family=Varela+Round' rel='stylesheet' type='text/css'>
</head>

<article class="type-system-rounded">
  <p class="type">Article Type</p>
  <h1>Article Heading</h1>
  <h2>These override some of the styles specified in the <code>_variables.scss</code> and <code>_typography.scss</code> partials in <a href="//bitters.bourbon.io">Bitters</a>. You can replace the typography variables and the header font specifications in Bitters with these styles. Then you won&rsquo;t need the wrapping class <code>.type-system-name</code>.</h2>
  <p class="date">30 Mar 2014</p>
  <p><span>Lorem ipsum dolor sit amet</span>, consectetur adipisicing elit. Consequatur a, ullam, voluptatum incidunt neque doloremque vel inventore distinctio laudantium harum</a> illo quam nulla dolor alias iure impedit! Accusamus! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur, a, ullam, voluptatum incidunt neque porro numquam doloremque vel inventore distinctio laudantium harum illo quam nulla dolor alias iure impedit.
    <a href="javascript:void(0)" class="read-more">Read More <span>&rsaquo;</span></a>
  </p>
  <h3>Subheading lorem</h3>
  <p><span>Consequatur ullam, voluptatum</span> incidunt neque porro numquam doloremque vel inventore distinctio laudantium harum illo quam nulla dolor alias iure impedit. Accusamus. Consequatur, a, ullam, voluptatum incidunt neque porro numquam doloremque vel inventore distinctio laudantium harum illo quam nulla dolor alias iure impedit! Accusamus.</p>
  <hr>
  <p class="author">Author Name</p>
</article>

The SCSS provided takes advantage of the fonts linked to from the HTML, and applies them in a way that shows them off to their best advantage using standard HTML elements.

article.type-system-rounded {
  $sans-serif: 'Nunito', sans-serif;
  $sans-serif-2: 'Varela Round', sans-serif;

  @include clearfix;
  text-align: left;

  .type {
    border-bottom: 1px solid;
    display: inline-block;
    font-family: $sans-serif;
    font-size: .7em;
    font-weight: 800;
    margin-bottom: 2em;
    padding: .3em 0;
    text-align: left;
    text-transform: uppercase;
  }

  h1 {
    font-family: $sans-serif-2;
    font-size: 1.8em;
    margin-bottom: .5em;

    @include media($medium-screen) {
      font-size: 2.4em;
    }
  }

  h2 {
    font-family: $sans-serif-2;
    font-size: 1.2em;
    font-weight: 400;
    line-height: 1.4em;
    margin-bottom: .9em;

    @include media($medium-screen) {
      font-size: 1.4em;
    }
  }

  code {
    white-space: nowrap;
    font-family: monaco;
    background: #F7F7F7;
    border: 1px solid #E0E0E0;
    border-radius: $base-border-radius * 1.5;
    padding: .1em .4em;
    font-size: .7em;
    font-style: normal;
  }


  h3 {
    font-family: $sans-serif-2;
    font-size: 1.2em;
    font-weight: 400;
    line-height: 1.3em;
    margin-bottom: .4em;
  }

  p.date {
    color: transparentize($base-font-color, .6);
    font-family: $sans-serif;
    font-size: .9em;
    margin-bottom: .3em;
  }

  p {
    font-family: $sans-serif;
    line-height: 1.4em;
    font-size: 1.05em;
    font-weight: 300;
    margin-bottom: 1.5em;

    span {
      font-family: $sans-serif-2;
      text-transform: uppercase;
      font-size: 0.8em;
    }
  }

  a.read-more {
    display: inline-block;
    font-family: $sans-serif-2;
    font-weight: 700;
    font-size: .8em;
    text-transform: uppercase;
    margin-left: .2em;
    position: relative;

    span {
      position: absolute;
      font-size: 1.5em;
      top: -1px;
      right: -12px;
    }
  }

  hr {
    width: 3em;
  }

  p.author {
    font-family: $sans-serif;
  }
}

The SCSS coordinates font weights and line heights to provide the most pleasing reading experience. And of course, if you choose to make any modifications, the code is right there for you to play with and adjust to your taste.

Things to Keep In Mind

While Refills is a great resource for people who don’t want to use a predefined framework or template, there are some things you need to keep in mind when using it. One of the annoyances I found with the Refills site was that there is no feedback provided when you click on the “copy” buttons to copy the text of an example into your clipboard. Once you realize that, you just have to pay attention and make sure you’ve copied and pasted what you expected.

Another gotcha is the fact that the Refills library is a set of static examples, ready to be incorporated into your pages, but they are not provided in a wide range of formats. For example, I often prefer to use HAML when I write my markup, but the code provided is always standard HTML. It’s a personal choice whether you want to use HTML, rewrite the HTML into HAML, Jade, or your own preferred syntax, do some command-line wizardry, or use an automatic conversion tool.

Similarly, the Sass examples are all provided in the popular SCSS format. If you use the traditional indented Sass format, you may need to modify your workflow to allow SCSS code to be interpreted correctly. There are a number of advantages to each syntax, and ultimately it is about how you prefer to do your development, so keep that in mind when considering Refills.

You may also notice some inconsistency in the JavaScript for Refills. Many of the components are community generated, so they may not all follow the exact same coding conventions. For example, I’ve noticed some components that use the older .bind() jQuery syntax for event handling, while others have adopted the more contemporary .on() syntax.

As long as you have conventions you like, it shouldn’t be hard to update Refills elements to follow the style you prefer.

Refills For Everyone

The great thing about Refills is how nicely they play with the Bourbon libraries, and how small and independent they are. The flexibility of your site design won’t be hindered by incorporating Refills into your page, and you can go from no design to something reasonably attractive and ready for styling very quickly.

For a developer who knows what she’s doing, and is looking to style up an inoffensive design for a project while providing a good baseline to hand off to a real designer, Bourbon Refills might just be the most convenient option out there.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

Comments
wayferer

Thanks! Seems like the link to refills should be http://refills.bourbon.io/ not http://refills.bourbon.com

HAWK

Good spotting. I've fixed that. Thanks.

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.