With the release of Bootstrap 3, we’ve seen the introduction of actual themes implemented by the bootstrap team. Currently, there are 3. One is unofficial, the others are “examples” that should lead the way. The old convention was to dig into bootstrap.less, vars.less, and other stylesheets in the core codebase in order to tweak variables, change CSS to correspond to the way we want it to look and move on. What’s interesting is that Bootstrap’s two new themes encourage a different method that help keep Bootstrap as a dependency (meaning that it shouldn’t be directly touched) rather than a starting codebase.

Let’s Overwrite

Instead of directly changing bootstrap.css, the new convention is to create a new stylesheet to be included on the page after the initial library is loaded. You can see this executed not only on bootstrap’s own site, but also on its non-responsive theme example, and its “2.3.2-esque” theme. These two themes directly override the original look of Bootstrap without touching bootstrap itself. This is the new, modern way of doing things. It’s akin to using hooks in wordpress rather than messing with the core.

Here’s how Bootstrap accomplishes this task with its 2.3.2-esque theme:

old-esque-bootstrap-themeFirst notice that the main differences in style boil down to gradients and shadows, giving the buttons and the navbar a “plasticy” feel. You can check out the unminified code in whole on github. Let’s take the buttons for instance:

.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
}

As you can see, we’re just adding shadows. The various other effects for :active and :hover selectors are added the same way. In the instance of this theme, little to nothing is overwritten but much is ADDED. What’s more important is that:

The theme fundamentally changed the look of the site without requiring the addition of new classes or different semantics while allowing the original library to be fully intact

This is the core of the new method. If you check the site itself, you’ll notice that it includes the same Bootstrap library file as the home site.

So what about the home page? How did THAT achieve its look?

bootstrap-homepageLooking at it, it looks like some other things have changed, and you’re right. Again, it includes vanilla bootstrap but overwrites it with a docs.css file. But in addition to being a “theme”, it also encompasses new elements and no longer sticks to overwriting and addition. If you check the code, anything “new” is prepended with “bs-” (well, mostly). This is not a convention to follow but I’m glad that the bootstrap theme made it easy for us to see the changes and how they went about using their own tool.

Vars stylesheet is still fair game

With all this said, changing the variables in the vars.less stylesheet is totally fair game. Hell, Bootstrap has its own customizer that relies on this. Touching vars doesn’t necessarily affect anything other than the compiled product. You should (technically) be still able to upgrade BS to a newer version, recompile, and still be okay. You can even use the customize screen for it and plug in all the relevant variables.

Use Bootstrap to modify Bootstrap

If you look at the source file of the theme.less file, you’ll find out that the theme file imports variables AND mixins. What does that mean? When crafting a bootstrap theme, it’s a great idea to take advantage of its built-in mixins (functions) in order to make your job easier. This will ensure that all your properties are properly prefixed and that any additional classes can employ already existing variables. Here’s a great example of how the 2.3.2-esque theme recreated the progress bars:

// Mixin for generating new styles
.progress-bar-styles(@color) {
  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));
}

// Apply the mixin to the progress bars
.progress-bar            { .progress-bar-styles(@progress-bar-bg); }

This should give rise to new tools

One of the problems with CSS has always been the bloating, over-bloating of stylesheets that over-write themselves. We’ve seen linters but nothing to the effect of what I’m thinking. Here’s an idea, let’s say we have a declaration in Bootstrap for a class and its properties:

.btn-default {
color: #333333;
background-color: #ffffff;
border-color: #cccccc;
}

And let’s say we have a bootstrap theme that changes border colors on all button elements to create a darker border, like so:

.btn-default {
text-shadow: 0 1px 0 #fff;
border-color: #e0e0e0;
}

This code is incidentally from Bootstrap’s example theme (sans tons of other declarations and redeclaration of #ccc border, idk wtf is going on there). I think that we should have a rise in new tools where this declaration which will overwrite the border-color for .btn-default class will literally overwrite it. Think of it as a precompile-compile. Basically either before your LESS gets compiled or after, a tool will go through your base library and your theme and replace your overrides in the original library. Again, this would happen only to the final compiled used product, not the .less files. This way, we could work with Bootstrap and other CSS libraries (Foundation, and what have you) in the same manner.

Is this crazy? Not at all. We’ve already implemented minification in our CSS compiling efforts, concatenation (includes in LESS or SCSS), and finally, even the creation of a new CSS language which allows for a more semantic and powerful use of CSS. All of this is currently done with either LESS or SCSS or whatever in between. Adding another layer to this process should not be a burden whatsoever.

My Theme

I wanted to create an example theme to illustrate the process of creating a theme. Here’s my initial design for my new website:

thoughtessays

 

First, let’s figure out what the main points of change are:

  • navbar needs to be transparent rather than colored
  • navbar items need to have a black background and white text (hover will inverse)
  • navbar needs to have a 0 bottom margin to allow a jumbotron to sit right below
  • because of certain functionality, I want the jumbotron to have a transparent background but the text needs to have a white background (I’ll be adding background images to the jumbotron based on what page they’re on.
  • primary button needs to be black with white text and inverse for hover (to mimick navbar)

Since bootstrap doesn’t use “overflow:hidden” on its grid, we can easily figure out how to make those floating images work. Let’s get to work.

Creating an HTML template

Okay, seems a bit backward but the first thing on our list is to create an html template that resembles our final product.

bootstrap-prototypeDidn’t take much but here we go. I’d say that that’s not a bad start. Column sizing is a bit off but I probably won’t correct that (I eyeballed the original design anyways). The first things I found that I need to update (besides the already listed items):

  • 0 top margin for heading text (this will require an additional class, unfortunately)
  • no border for the list group
  • black links in the sidebar
    <div class="navbar navbar-default">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
          </button>
        </div>
        <div class="navbar-collapse collapse">
          <ul class="nav navbar-nav navbar-right">
            <li class="active">
              <a href="#">Home</a>
            </li>
            <li>
              <a href="#about">About</a>
            </li>
            <li>
              <a href="#contact">Contact</a>
            </li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>
              <ul class="dropdown-menu">
                <li>
                  <a href="#">Action</a>
                </li>
                <li>
                  <a href="#">Another action</a>
                </li>
                <li>
                  <a href="#">Something else here</a>
                </li>
                <li class="dropdown-header">
                  Nav header
                </li>
                <li>
                  <a href="#">Separated link</a>
                </li>
                <li>
                  <a href="#">One more separated link</a>
                </li>
              </ul>
            </li>
          </ul>
        </div>
        <!--/.navbar-collapse -->
      </div>
    </div>
    <!-- Main jumbotron for a primary marketing message or call to action -->
    <div class="jumbotron">
      <div class="container">
        <h1>
          Thought Essays
        </h1>
        <br />
        <h2>
            Poetry
        </h2>
      </div>
    </div>
    <div class="container">
      <!-- Example row of columns -->
      <div class="row">
        <div class="col-md-2">
          <img src="#" width="100%" height="100px" />
          <p>
            Antonin Januska
            <br />
            5th of July 2013
            <br />
            blah blah blah
          </p>
        </div>
        <div class="col-md-7">
          <h1 class="post-title">
            Comforts of Life
          </h1>
          <p>...Content goes here...</p>
        </div>
        <div class="col-md-3">
          <div class="widget">
            <h3>
              Search
            </h3>
            <form class="row">
              <div class="col-md-8">
                <input type="text" class="form-control">
              </div>
              <div class="col-md-4">
              <input type="submit" class="btn btn-default form-control">
            </div>
            </form>
          </div>
          <div class="widget">
            <h3>
              Latest Posts
            </h3>
            <ul class="list-group">
              <li class="list-group-item"><a href="#">Article 1</a></li>
              <li class="list-group-item"><a href="#">Article 2</a></li>
              <li class="list-group-item"><a href="#">Article 3</a></li>
              <li class="list-group-item"><a href="#">Article 4</a></li>
            </ul>
          </div>
        </div>
      </div>
      <hr />
      <p>
        &#169; Company 2013
      </p>
    </div>

Not bad! :) Let’s get started on the CSS.

CSS

Okay, we have a couple of options here. Either we will start with a customized bootstrap version via Bootstrap’s customize screen or we overwrite the original properties. Both have their advantages and disadvantages.

Overwrite

Advantages:

  • when an update comes out, you can just drag and drop it in.
  • you can use automation tools to pull the library. For example, using bower to include bootstrap in your project makes it easy
  • changes from the original are very easily distinguishable
  • custom styling is separate from defaults

Disadvantages:

  • additional bloat.
  • large site-wide changes may require lots of overrides

Variables Sheet + Direct Access

Advantages:

  • changing variables will propagate the same look across the library
  • direct access means less bloat from custom styling

Disadvantages:

  • difficult upgrades

What do we do?

The best decision is to get the best of both worlds. Using the variables less file, you can easily preconfigure major changes. In my case, making almost everything black and white. Our extra stylesheet will then directly override several styles (like changing margins). While upgrading in the future can be a hassle, it’s a sacrifice I’m willing to make.

First, copy or clone the bootstrap repo and use the less folder. Remember that the bootstrap.less file compiles into your base bootstrap.css library while your theme.less compiles into your theme. The advantage of using less files is that both the theme and bootstrap files can share certain files. In our case, we’ll include the mixins and variables in our theme file.

Here’s what the bootstrap theme looks like BEFORE adding a theme file but after variable changes. When making your own theme, use your own discretion as to what needs to changed. Most variables have pretty easy names to understand:

variable-change-bootstrapClose but,errr..no cigar. I made only a few changes:

  • created a @white and @black variables (my main colors)
  • set @brand-primary to @black (to change color of links and fundamentals of bootstrap)
  • updated @navbar-default background colors, link colors and backgrounds. I decided to change backgrounds to white until I override them with transparent (the background color variables have dependencies that I don’t want to break)
  • updated list-group outline to white
  • updated jumbotron to white background

Sweet. As you can see variable updates can take you only so far. If I need to upgrade my bootstrap install in the future, I’ll have to either pull in all less files sans variables.less or just compare the two files (old and new).

Let’s move onto theme.less add the following to the top:

@import "variables.less";
@import "mixins.less";

Now we can really dig into our changes:

.navbar {
  min-height: 40px;
}

.navbar-default {
  background: transparent;
  border: 0;
  margin-bottom: 0;
}

.navbar-nav > li {
  background: @black;

  a{
    padding: 10px;
  }
}

So, we’ve just fundamentally changed how the navbar looks. The height is smaller to match my original design. The navbar has a transparent background with no border and no margin and finally, the navbar items have a black background and small padding to fit the new navbar height.

Let’s move onto the jumbotron (the next major piece):

.jumbotron {
  padding: 48px 0 36px;
  margin-top: -40px;
  background: url('');

  h1 {
    display: inline-block;
    padding: 10px;
    background: @white;
    margin: 0;
  }

  h2 {
    display: inline-block;
    background: @white;
    margin-bottom: 0;
    padding: 5px;
    margin-left: 124px;
    margin-top: 8px;
    font-size: 40px;
  }

}

We’ve just placed the jumbotron behind the nav so that when we declare its background, it will encompass the navbar area as well. On top of that, we changed the headings in the jumbotron so that it matches the design. Lastly, let’s change the list-group-item:

.list-group-item {
  padding-left: 0;
}

Sweet. Here’s what I’ve got so far:

thought-essays-bootstrap

Not bad! Almost there. Notice that I added a background image to the jumbotron. Okay, so what’s left? Stuff that I’ll have to add and ID in the content itself:

  • I’ll be adding a “content” id to the content and a “title” id to the title so that I can fix the spacing there.
  • I’ll be adding special “pull” classes to the images to get them to stick out of their columns

Okay, awesome. I don’t have the mobile view quite right so that’s something to look at. The “active” button is not something I’m a fan of either so I’ll be adding onto it.

Here’s how I dealt with it:

 //navbar active button
.navbar-default .navbar-nav > .active > a {
  background: @white;
  @shadow: inset 0 0 3px rgba(0, 0, 0, 0.5);
  .box-shadow(@shadow);
}

//site specific CSS
.post-title{
  margin-top: 0;
}

#sidebar {
  h3:first-child{
    margin-top: 0;
  }
}

As you can see, bootstrap’s mixins come in handy! :)

To compensate for some media query changes, I added some HTML and took advantage of bootstrap’s responsive utilities:

        <div class="col-md-2 visible-md visible-lg">
          <img src="#" width="100%" height="100px" />
          <p>
            Antonin Januska
            <br />
            5th of July 2013
            <br />
            blah blah blah
          </p>
        </div>

Ah, so we made this stuff disappear because it looks like crap on smaller screens (this is the sidebar with my name and date on it, leftmost column). I instead, opted to add this information under the article title like so:

          <h1 class="post-title">
            Comforts of Life
          </h1>
          <p class="meta visible-sm visible-xs">
            Antonin Januska | 5th of July 2013 | blah blah blah
          </p>

This makes sure that the text is visible ONLY to mobile/tablets. Neat. Last thing, let’s add the “extra pull” classes to our images:

@media (min-width: @screen-md-min) {
  .extra-left{
    margin-left: -55px;
    padding: @font-size-base;
  }

  .extra-right{
    margin-right: -55px;
    padding: @font-size-base;
  }
}

And to finalize everything, we need to make sure that the collapsed navbar looks good:

@media (max-width: @screen-xs-max) {
  .navbar-default{
    background-color: @black;
  }

  .navbar-default .navbar-collapse{
    border: 0;
  }
}
.navbar-default {
  background: transparent;
  border: 0;
  margin-bottom: 0;
  .navbar-toggle {
    background: @white;
  }
}

The first bit ensures that the color of the navbar is black and no border is shown. Why? Well, by pushing up the jumbotron and making the navbar transparent globally, we create a few problems. One of them is that colors get all wonky, the other is that a border gets introduced (it’s always there by default).

Final Product

final-thought-essay

thought-essays-mobileNot bad!

Bootstrap 3 Thoughts Theme Preview