Logo
ManuelSchoebel

Meteor.js and Twitter Bootstrap - The right way

If you are building web applications today you need to make sure that they are displayed correctly not only in different browsers but also on different screen sizes. That is why we build our applications 'responsive' and that means that every component fits itself to the space it has. Doing that with CSS is a big pain because it really is a quite complicated task. Good that we have Twitter Bootstrap which does exactly that. But the CSS framework gives us also a really good start for a good-looking application. Just plain Bootstrap gives you an "okay" design right from the beginning, too. But Twitter Bootstrap is, like Meteor.js itself, structured very modular and you can customize it easily. That is what you ultimately want, a good responsive behavior for the layout but your individual look and design.

##How Bootstrap is structured Twitter Bootstrap is just a bunch of modules and each module has one purpose. So let us have a look at the "less" version of Twitter Bootstrap to see what is inside:

Code Structure of Twitter Bootstrap

What you see is the source code version of bootstrap and not the compiled CSS version. In the less folder you see what the parts of twitter bootstrap are and we see all the components you can use. Also the whole grid system, which is the key component for the responsive layout bootstrap gives us, is in its own file 'grid.less'. And there is one main file, the 'bootstrap.less' file that includes all other files.

    // Core variables and mixins
    @import "variables.import.less";
    @import "mixins.import.less";
 
    // Reset
    @import "normalize.import.less";
    @import "print.import.less";
    ...

You see we can use @import "file.less" to import a file into another using less. This enables us to NOT write just one large file with all the CSS in it and you really do not want to do this. Using a less compiler, this results in one file with all our CSS.

To be clear this is something completely different from the "@import url" of normal CSS because the @import of normal CSS would load a different CSS file and because of different reasons this should be avoided!

Twitter Bootstrap also has some JavaScripts for components like the very popular "modal" and those could be found in the "js" folder you can see in the screenshot above.

##The Wrong Way I bet a lot of you have done one of those options:

meteor add bootstrap            // add core bootstrap package
meteor add someauthor:bootstrap-3      // add bootstrap via community package

What this does is, it adds the compiled version of bootstrap into your app and voila you have the basic bootstrap look, the layout/grid system and the JavaScript components. For quick prototyping this still might be a good and fast option for you. But what this also gets you is a bad way for customizations and organizing your style sheets. There is a better way using the less version of Twitter Bootstrap!

##Using Less There are different reasons why using less is awesome. Using the less version of Twitter Bootstrap gets you mainly two big advantages. Also if you are not familiar with less, don't worry! You could basically just continue to wright normal CSS in the less files if you want to. You will learn what you can do with less over time automatically.

But first things first:

// 1. Add the less compiler so meteor compiles everything for you
meteor add less

// 2. Add the bootstrap
meteor add nemo64:bootstrap

// 3. Clone this stylesheet boiler
// Also delete the .git folder and .gitignore if you don't like those
cd yourapp/client/
git clone https://github.com/DerMambo/stylesheets.git

// 4. Add everything you need into the file
// yourapp/client/vendor/custom.bootstrap.json

Update 09.09.2014: I now use the bootstrap package that originally came from simison and was updated for Meteor 0.9. by nemo64. This means the old bootstraap package I created will not be maintained since the package from Simison/Nemo64 does the exact same and even more.

Important: If you first run your app the bootstrap related parts will be automatically build for you inside the /vendor folder. So do not worry if you cannot find anything after you followed the steps mentioned above. Also make sure you checkout the 'vendor/custom.bootstrap.json' file and enable anything you need for your app. As a default most is disabled.

WARNING: This error message may occure

While building the application:
client/stylesheets/custom.bootstrap.json: Unexpected token ;

Simply remove the ';' at the end of the file mentioned and restart the app. I think this will be fixed soon.


Meteor does not only minify your JavaScript or CoffeeScript but it can also handle less. If we change a *.less file, the coresponding CSS file is generated automatically and also our website is reloaded as we would expect it from Meteor.

There is one thing you have to be aware of: If you use @import "file.less" make sure you name the imported file "file.import.less" (or *.lessimport before Meteor v0.7.1). This way Meteor knows that it does not have to compile the file automatically.

Now let us have a look on how I personally like to organize my style sheets using less. If you have recommendations I would love your feedback in the comments below! This comes automatically if you clone the style sheet boiler mentioned above.

// the main style file which compiles to style.css
// only do @import "file.import.less" in here
app/client/stylesheets/style.less

// some basic styles
app/client/stylesheets/typo.import.less

// all site depending styles
app/client/stylesheets/sites/

// all vendor libraries like twitter bootstrap
app/client/vendor/

// styles for reusable components
app/client/stylesheets/components/

The style.less file is our main style file and only this will be compiled to an actual CSS file.

###First Advantage: Customizing Twitter Bootstrap Since we are using less now, we can easily customize Twitter Bootstrap. For that we have the "vendor/custom.bootstrap.import.less" file. This file is just a copy of the original "variables.less" file from Twitter Bootstrap.

In the variables file of bootstrap you find something like this:

//
// Variables
// --------------------------------------------------


//== Colors
//
//## Gray and brand colors for use across Bootstrap.

@gray-darker:            lighten(#000, 13.5%); // #222
@gray-dark:              lighten(#000, 20%);   // #333
@gray:                   lighten(#000, 33.5%); // #555
@gray-light:             lighten(#000, 60%);   // #999
@gray-lighter:           lighten(#000, 93.5%); // #eee

@brand-primary:         #428bca;
@brand-success:         #5cb85c;
@brand-info:            #5bc0de;
@brand-warning:         #f0ad4e;
@brand-danger:          #d9534f;

...

As you can see you can now very easily change the brand colors. There are really a lot of options for every component that you get with Twitter Bootstrap. There is really no need to overwrite bootstrap CSS if you use the variables, most of the time.

###Second Advantage: Use Bootstraps Mixins Less comes with a great feature called 'Mixins' which basically lets you write functions you could use in your less files to generate CSS. One very simple Mixin of Twitter Bootstrap is this one:

.border-top-radius(@radius) {
    border-top-right-radius: @radius;
    border-top-left-radius: @radius;
}

This simply lets you define the top border in a single line. Really nice is this e.g. if you want to set transitions and you do not need to worry about vendor-prefixes anymore. So using the less version of Twitter Bootstrap also lets you access all its mixins.

##Meteor.js Templates with Twitter Bootstrap No that we know about less and Twitter Bootstrap we want to see how we should (in my opinion) use Twitter Bootstrap to actually build stuff. Let's think of a Collection with a lot of products. This means you have a template for the list, which could look like that:

    <template name="productList">
        <div class="row">
            {{#each products}}
            <div class="col-lg-4">
                <h4>{{title}}</h4>
                <p>{{description}}</p>
            </div>
            {{/each}}
        </div>
    </template>

One thing I would not do, is putting two different things in one template. In this case I see a list AND a list-item. And that's the reason I put the list-item in its own template too:

    <template name="productList">
        <div class="row">
            {{#each products}}
            {{>productListItem}}
            {{/each}}
        </div>
    </template>
 
    <template name="productListItem">
        <div class="col-lg-4">
            <h4>{{title}}</h4>
            <p>{{description}}</p>
        </div>
    </template>

Okay, this looks better now. We have one template for our list-item and now we could use this somewhere else, too! BUT I did something here I also never do and that is: Let the template decide how big it is. In this case the "productListItem" defines its width by the class "col-lg-4". But what if you want to use this template in another context where you have more or less space?! So another rule for me is to always set the width/layout at the parent template, like this:

    <template name="productList">
        <div class="row">
            {{#each products}}
            <div class="col-lg-4">
                {{>productListItem}}
            </div>
            {{/each}}
        </div>
    </template>
 
    <template name="productListItem">
        <h4>{{title}}</h4>
        <p>{{description}}</p>
    </template>

Now we could use the productListItem anywhere and define its width how we actually need it. This is also really great if you create packages and the component you build is responsive and always uses as much space as you give it.

To style our "productListItem" you can create a "product.import.less" file and put it under the /client/stylesheets/components/ folder. Also do not forget to import this file in the main styles.less file, too.

##Conclusion Twitter Bootstrap is great but using the less version is even better because you can customize it much more easily and also use Twitters really great mixins.

Also make components responsive, so you can use them anywhere. Use Twitters grid-classes only in the parent templates not in the child templates.

Aaaand: Organize your styles with style! :P

©️ 2024 Digitale Kumpel GmbH. All rights reserved.