Styling a Middleman Blog with Bourbon, Neat, and Bitters

Styling a Middleman Blog with Bourbon, Neat, and Bitters

This is a walk-through for styling your own static blog from scratch. We will be using Middleman for our framework and Bourbon, Neat, and Bitters for our Sass libraries.

Middleman is a lightweight static site framework built using Ruby. It compiles Markdown into HTML and is easily deployed to S3, Heroku, or GitHub Pages.

Middleman can also host a blog nicely like this blog.

The following steps will include instructions for installation, setup, deployment, and adding some very basic styles.

Installation

First, we install the Middleman gem and the blog extension gem. We can then initialize the project:

$ gem install middleman-blog
$ middleman init my_blog --template=blog --rack

Let’s start the server and take a look at what we’ve got:

$ cd my_blog
$ bundle exec middleman
$ open http://localhost:4567

You should see something like this in your browser:

Craigslist style

Middleman gives us a default post and just the default styles, which is a great place to start.

Configuration

We’ll be doing a lot of browser refreshing to see our progress, so let’s automate the process. We can use the built-in Livereload service to auto-refresh the page whenever we save. Let’s add the gem:

Gemfile

...
group :development do
  gem 'middleman-livereload'
end

And enable the service by uncommenting the configuration line:

config.rb

...
configure :development do
  activate :livereload
end

Livereload will begin working as soon as you run bundle and restart your server.

$ ctrl + c //shuts down Middleman server
$ bundle
$ bundle exec middleman

Prepare to Deploy

Our blog won’t run on Heroku as-is, but we only need to do a few things to change that.

First, we need to add some code to config.rb that will tell Middleman to put the files Heroku needs in a folder named tmp:

...
set :build_dir, 'tmp'
...

Next, we will create a file that tells Heroku how to build our source files. We will create a file named Rakefile in the root directory of our project and add the code below:

Rakefile

namespace :assets do
  task :precompile do
    sh "middleman build"
  end
end

config.ru

require 'rack/contrib/try_static'

use Rack::Deflater
use Rack::TryStatic,
  root: 'tmp',
  urls: %w[/],
  try: %w[.html index.html /index.html]

FIVE_MINUTES=300

run lambda { |env|
  [
    404,
    {
      'Content-Type'  => 'text/html',
      'Cache-Control' => "public, max-age=#{FIVE_MINUTES}"
    },
    ['File not found']
  ]
}

We’ll also need to include the rack-contrib gem in our Gemfile. Be sure to bundle and restart your server after this step.

Gemfile

...
gem 'rack-contrib'
...

The final step is initializing Git, which we will do next.

Initialize Git

To be able to track our changes and push our blog to Heroku, we need to initialize a Git repo.

$ git init
$ git add .
$ git commit -m 'initial commit'

To commit changes as we continue to work, we’ll run git add . to track new files and stage changes to files already being tracked. Then we can run git commit -m 'your commit message' and we’ll be able to push our latest changes to the remote.

It’s a good idea to commit changes to git at the end of each section of this post.

We’ll be using Heroku as a remote repository.

It would be beneficial to also set up a remote like GitHub for remote version tracking, but it’s not necessary.

We’ll just focus on Heroku for now. If you don’t already have a Heroku account, you’ll need to sign up for one before running heroku create.

$ heroku create
$ git push heroku master

And now, we can run heroku open in the terminal to open the page in our browser. We’ve just created a blog and pushed it live. Next is to add our own styles to customize the design.

Install Libraries

Our goal is to add a custom design to this blog, so let’s install our Sass toolkit and bundle:

Gemfile

gem 'bitters'
gem 'bourbon'
gem 'neat'

Bourbon is a library of vanilla Sass mixins, Neat gives us a responsive grid system, and Bitters sets default styles for Bourbon projects. These gems will make the assets available to our site through Middleman’s asset pipeline.

Since we’ve updated our Gemfile, we’ll need to bundle and restart our server again.

Bourbon and Neat are included by the gem, but Bitters requires an additional install in your stylesheets folder:

$ cd source/stylesheets
$ bitters install
Bitters files installed to /base

Next, we need to create a stylesheet manifest with the correct character encoding and import our design libraries:

source/stylesheets/all.css.scss

@charset "utf-8";

@import "bourbon";
@import "base/base";   /* Bitters needs to be imported before Neat */
@import "neat";

Include all of the stylesheets to be used in this site by adding the link to the manifest in the <head> section of layout.erb:

source/layout.erb

...
<head>
  <%= stylesheet_link_tag "all" %>
...

Let’s see how it looks now:

Bitters default style

Already, we see improvement. What did Bitters just set up for us?

  • Typography - Uses Helvetica as default font-family and sets the sizes for various header elements on a modular scale (e.g. <h1>’s and family)
  • Color - uses variables to systematize colors.
  • Lists - strips all styles from lists including bullets
  • Flash notice styles - very useful in Rails
  • Grid settings to accompany Neat
  • Some basic form styles

Get Stylish

We’ll need to customize a few things in Bitters to optimize our styles for a blog. First, let’s add our own Google font to layout.erb:

source/layout.erb

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

To make use of this font, all we need to do is change the $sans-serif variable in _variables.scss:

source/stylesheets/base/_variables.scss

...
$sans-serif: 'Oxygen', $helvetica;
...

By changing the $sans-serif variable, we’ve quickly and easily changed the font family globally.

Comfortable Reading

Let’s create a partial that will contain all of the layout related styles. We’ll need to import it in our manifest:

source/stylesheets/all.css.scss

...
@import "partials/layout";

Add the outer-container() mixin to the layout to center it in the viewport.

source/stylesheets/partials/_layout.scss

#main {
    @include outer-container;
}

For a good reading experience, we want to keep the length of the lines of text a comfortable length. If the lines are too long, the reader will have a hard time following the flow of the text.

Neat makes this easy to accomplish in as little as two steps. We’ll adjust the max-width property of the outer-container() mixin.

The first step will be to import _grid-settings.scss into Bitters. We can just uncomment that line in _base.scss:

source/stylesheets/base/_base.scss

...
@import "grid-settings";

The second step is to edit _grid-settings.scss. Uncomment the $max-width variable and change its value to em(700). This should give us a comfortable line-length for reading.

source/stylesheets/base/_grid-settings.scss

...
$max-width: em(700);
...

Let’s see what our blog looks like now that we’ve added a few styles of our own:

Custom grid-settings

We see that Bitters has successfully applied our chosen font and centered our content. Don’t worry about some of the content being misaligned. We’re about to fix that.

Modular Structure

Our readers need to be able to easily move around the site, so we’ll add some helpful links in a navigation and footer.

To keep our code modular, we will break up the navigation and footer into separate partials. It’s good practice to make a folder to keep your partials in.

We’ll edit a group of new files:

  source/partials/_nav.erb
  source/partials/_footer.erb

  source/stylesheets/partials/_nav.scss
  source/stylesheets/partials/_footer.scss

Now that we’ve added some structure to our code we can import these partials into layout.erb and our Sass partials into all.css.scss.

source/layout.erb

...
<div id="main" role="main">
  <%= partial "partials/nav" %>
  <%= yield %>
  <%= partial "partials/footer" %>
</div>
...

Improved Markup

We are ready to improve the overall layout of our index page. A few small adjustments to the markup will make it more semantic and easier to style.

Paste the code below into _nav.erb:

source/_nav.erb

<nav>
  <ul>
    <li>
      <%= link_to "Blog Title", "index.html", :class => 'blog-title' %>
    </li>
  </ul>
</nav>

We will move some of the content from layout.erb into the footer. Paste the code below into _footer.erb and remove it from layout.erb:

source/_footer.erb

<footer>
  <ul class="large-column">
    <li><h5 class="heading">Recent Articles</h5></li>
    <li>
      <ol>
        <% blog.articles[0...10].each do |article| %>
          <li>
            <%= link_to article.title, article %>
            <span><%= article.date.strftime('%b %e') %></span>
          </li>
        <% end %>
      </ol>
    </li>
  </ul>

  <ul class="small-column">
    <li><h5 class="heading">Tags</h5></li>
    <li>
      <ol>
        <% blog.tags.each do |tag, articles| %>
          <li><%= link_to "#{tag} (#{articles.size})", tag_path(tag) %></li>
        <% end %>
      </ol>
    </li>
  <ul>
</footer>

Additionally, we’ll improve the markup in index.html.erb:

source/index.html.erb

...
<ul>
  <% page_articles.each_with_index do |article, i| %>
    <li>
      <h3><%= link_to article.title, article %></h3>
      <h5><%= article.date.strftime('%b %e') %></h5>
      <p><%= article.body %></p>
    </li>
  <% end %>
</ul>
...

Adding Custom Styles

As a finishing touch, we’ll add some custom styles to our navigation, footer, and layout: For consistency, we will also create Sass partials for the nav and the footer.

source/stylesheets/all.css.scss

...
@import "partials/nav";
@import "partials/footer";

source/stylesheets/partials/_nav.scss

nav {
  border-bottom: 1px solid $base-border-color;
  margin: em(30) 0;

  ul {
    display: inline-block;
    margin-bottom: em(10);
  }
}

.blog-title {
  font-size: 1.4em;
  font-weight: 700;
  letterspacing: 4px;
  text-transform: uppercase;
}

source/stylesheets/partials/_footer.scss

footer {
  border-top: 1px solid $base-border-color;
  margin: 2em 0;
  padding-top: 2em;
}

Some styles are providing a style pattern we’ll use throughout the blog. We’ll place these styles in the _layout.scss stylesheet since they create a reusable layout pattern.

source/stylesheets/partials/_layout.scss

...
ol {
  font-size: 1em;
  font-weight: 500;

  li {
    margin: .5em 0;

    span {
      display: inline-block;

      &:before {
        content: '/';
        margin: 0 .3em;
      }
    }
  }
}
...

Using the mixin @include span-columns(), Neat will calculate the width of the div based on the number of columns you specify in the argument.

source/stylesheets/partials/_layout.scss

...
.large-column {
  @include span-columns(8 of 12);
}

.small-column {
  @include span-columns(4 of 12);
}

Now we have a basic template set up for our very own blog.

Final Results

All that’s left to do is make sure all of our changes have been committed to Git and then deploy these updates to Heroku.

$ git push heroku master

Completion

Now we have a good foundation upon which to publish our own blog.

Carolann Bonner Designer

Hound reviews Ruby and CoffeeScript code for style violations and comments on your GitHub pull requests. Free for open source repos.