Advertisement
Complete Websites

Build a Modular Dashboard Interface With Pure

by

Today, we will be making a beautiful, minimal dashboard using Pure (view the project on GitHub), the new mini-CSS module library from Yahoo!. We will be talking about and using some of the principles of SMACSS (Scalable and Modular Architecture for CSS). We'll also be using icons from WeLoveIconFonts.com.

Note: Before we go any further, there is a minimum emphasis on graphs for the dashboard we will be creating. Graphs are best executed with something more JavaScript heavy, and in order to keep the focus on CSS and minimal JavaScript, this tutorial will generally avoid graph drawing techniques.


A Bit About Pure

Pure was built by the team at Yahoo! and YUI to be a very lightweight set of modules (less than 6k). Think of this as an extended Normalize that also includes styles for very common things like grids, forms, buttons, tables, and menus.

pure-base

The YUI team built Pure to be a starting point, not a complete solution. From this starting point, they expect developers to expand and build their custom CSS as an extension of this base.

For this reason, a lot of what we teach in this tutorial are techniques for extending a basic foundational library like Pure to suit application interaction, like when using a dashboard.


A Bit About SMACSS

SMACSS, short for Scalable and Modular Architecture for CSS, and the brain child of Jonathan Snook, is a set of practices designed for building CSS that is easily understood, easy to extend, and avoids the CSS specificity war.

pure-smacss

This is futher assisted by not using IDs for styling and limiting the nesting of selectors as much as possible. The basic idea is that CSS can be categorized as base, layout, modules, states, and themes. Structuring CSS around these categories and following naming conventions that allude to these categories makes SMACSS readable and immediately meaningful. This avoids class names that have arbitrary styles associated with them. The basic idea of categorization follows this naming convention.

  • Base: no name (default elements, no classes)
  • Layout: .layout, .grid, .grid-column, .grid-column.five.columns
  • Modules: .btn (module name), .btn-default, .btn-calltoaction; .modal, .modal-header
  • State: .is-hidden, .is-active (implies JavaScript-trigger class changes)
  • Theme: .theme-background, .theme-border, .font-1, .font-2

These types of classes describe their functionality and category. The rules of SMACSS are more "guidelines" and ways of thinking; look through the source of Pure CSS to see examples of SMACSS in action.


Diving in

First, let's create a simple project directory using the HTML5 Boilerplate, and drop Pure in in place of Normalize.css. For this tutorial, we will be using Pure's YUI CDN link, <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.1.0/pure-min.css">. We'll also drop in Font Awesome, Twitter's icon font collection, and add a line to our CSS (instructions taken from weloveiconfonts). Throughout the markup, you will see icons defined with classes like "fontawesome-calendar".

/* in main.css */

[class*="fontawesome-"]:before {
  font-family: 'FontAwesome', sans-serif;
}
<!-- in index.html, in place of normalize -->
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.1.0/pure-min.css">
<link rel="stylesheet" href="http://weloveiconfonts.com/api/?family=fontawesome">

We're ready to start using these tools in design! Let's start out by defining some skeleton CSS to hold our elements in. Let's put this in our 'body'.

<header>
	<nav></nav><!-- this is where our nav menu will go -->
</header>
<section class="dashboard">
	<!-- our dashboard pieces will go here -->
</section>
<footer>
	<!-- copyright information can go here-->
</footer>

We've decided to use a color palette we found on colourlovers called Yellow Tree Frog by user LJK.

pure-frog

For now, we are going to reference them in a comment at the top of the CSS file.

/*
	red: #E73F3F
	orange: #F76C27
	yellow: #E7E737
	blue: #6D9DD1
	purple: #7E45D3
*/

Tip: You might benefit from starting out by using the CSS color keywords and find/replace the hex codes later so you don't have to copy and paste the hex code constantly.


Defining the Menu

PureCSS gives us a drop-in menu module that we can use to define a menu for our dashboard. We begin by using Pure's class-based module naming, following the guidelines of SMACSS.

<nav class="pure-menu pure-menu-open pure-menu-horizontal">
    <a href="#" class="pure-menu-heading">WebDesignTuts</a>
    <ul>
        <li class="pure-menu-selected"><a href="#">Dashboard</a></li>
        <!-- other items ... -->
    </ul>
</nav>

Note that this menu isn't going to be functional for this tutorial. Viewing the page, we can see our menu has been created with default horizontal styling. Let's go ahead and change the background of the menu to a semi-transparent black.

.pure-menu {
    font-weight: lighter;
}
.pure-menu.pure-menu-fixed {
    position: fixed;
}
.pure-menu.pure-menu-blackbg {
    background: #222;
}
.pure-menu.pure-menu-blackbg .pure-menu-heading:hover {
    color: #efefef;
}
.pure-menu.pure-menu-blackbg a {
    color: #fff;
}
.pure-menu.pure-menu-blackbg a:hover {
    background: #666;
}
.pure-menu.pure-menu-blackbg .pure-menu-selected a {
    background: #7E45D3;
}
.pure-menu.pure-menu-blackbg .pure-menu-selected a:hover {
    color: #efefef;
}

Here, we see an adoption of the conventions used by SMACSS and Pure. We define a two new classes, 'pure-menu-blackbg' and 'pure-menu-fixed', and then the sub-styles needed to support that class. We also see some overriding of underlying classes (like the existing 'pure-menu' class to change to a lighter font weight).

pure-menu

Creating a Dashboard Module

Next, we will create a dashboard module. We'll use some basic styles for our base-level dashboard "block" piece.

.dashboard-piece {
    min-height: 300px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    color: #fff;
    text-align: center;
    position: relative;
    padding-bottom: 40px;
}

Now that we have this base module defined, we will extend this by creating new classes with the 'dashboard-piece' prefix. First, we will create background color classes.

.dashboard-piece-redbg {
    background-color: #E73F3F;
}
.dashboard-piece-orangebg {
    background-color: #F76C27;
}
.dashboard-piece-yellowbg {
    background-color: #E7E737;
}
.dashboard-piece-bluebg {
    background-color: #6D9DD1;
}
.dashboard-piece-purplebg {
    background-color: #7E45D3;
}
.dashboard-piece-graybg {
    background-color: #798388;
}

Next, we will define the markup for the different dashboard pieces. We include an inline SVG of the Envato logo, which will stretch the entire width of the grid.

pure-envato-logo
<section class="dashboard pure-g-r clearfix">
    <div class="pure-u-1 dashboard-piece dashboard-piece-redbg dashboard-piece-logo">
        <h1>
            <svg x="0px" y="0px" width="132.89669167px" height="120px" viewBox="0 0 73.351 82.791" enable-background="new 0 0 73.351 82.791" xml:space="preserve">
                <g><path fill="#FFFFFF" d="M7.372,27.487C-1.903,39.206-2.261,55.13,5.369,67.05c6.858-17.611,15.499-37.423,26.14-55.114
                C21.514,16.159,12.19,21.405,7.372,27.487z M73.333,2.971c-0.11-0.924-0.589-1.7-1.276-2.216C71.4,0.204,70.53-0.084,69.612,0.021
                c0,0-2.738,0.589-7.093,1.704C41.722,21.698,24.654,48.459,11.43,74.155c0.492,0.427,0.991,0.857,1.512,1.268
                c14.784,11.696,36.239,9.194,47.936-5.57C74.349,52.822,73.333,2.971,73.333,2.971z"/></g>
            </svg>
        </h1>
    </div>
    <div class="pure-u-1-3 dashboard-piece dashboard-piece-bluebg">
        <div class="dashboard-content">
            <h2><i class="fontawesome-twitter"></i></h2>
            <p class="dashboard-metric">+20 followers<span class="light"><i class="fontawesome-angle-up"></i>6.8%</span></p>
        </div>
    </div>
    <div class="pure-u-1-3 dashboard-piece dashboard-piece-orangebg">
        <div class="dashboard-content">
            <h2><i class="fontawesome-github"></i></h2>
            <p class="dashboard-metric">
                142 Commits
                <div class="light bar-horizontal">
                    <div class="bar-horizontal-bar" style="width:57%">
                        57% Capacity
                    </div>
                </div>
            </p>
        </div>
    </div>
    <div class="pure-u-1-3 dashboard-piece dashboard-piece-yellowbg">
        <div class="dashboard-content">
            <p class="dashboard-metric">
                <h2><i class="fontawesome-check"></i></h2>
                <div class="dashboard-metric">
                    <strong>63 / 90</strong><br><small>Tasks Complete</small>
                </div>
            </p>
        </div>
        <div class="bar-vertical" style="height:70%;"></div>
    </div>
</section>

There's a lot to cover in this markup. First, we're using 'pure-u-1-3' (and other pure-u-* classes) inside a grid row element, 'pure-g-r'. These classes are a part of the Pure grid system. To understand these completely, check out the full YUI grid documentation; the basic concept is that the grid class pure-u-1-3 is 1/3rd the width of the full grid; a class of pure-u-3-4 would be 3/4th the width of the grid. The module with the logo in it has the class pure-u-1, which allows it to span the full width of the grid.

The other elements of the dashboard pieces are used to show different types of metrics. The following CSS rules are used to present these metrics and other internal parts of the dashboard pieces.

.dashboard-piece-logo h1 {
    line-height: 100px;
}
.dashboard-piece-logo svg {
    margin-top: 80px;
}
.dashboard-piece h1 {
    line-height: 300px;
    font-size: 3.6em;
    margin: 0;
}
.dashboard-content {
    position: relative;
    z-index: 999;
}
.dashboard-content p {
    font-weight: lighter;
}
.dashboard-content .light {
    opacity: 0.4;
    display: block;
}
.dashboard-content h2 i {
    font-size: 4em;
    opacity: 0.4;
}
.dashboard-metric {
    text-transform: uppercase;
    font-size: 1.6em;
    line-height: 1;
}
.dashboard-metric i {
    margin-right: 0.6em;
}
pure-modules

We also define the horizontal and vertical bar classes separately from the dashboard-content modules.

.bar-horizontal {
    height: 36px;
    background-color: rgba(255,255,255,0.4);
    position: relative;
    display: block;
    margin-top: 20px;
}
.bar-horizontal-bar {
    background: #fff;
    height: 36px;
    line-height: 36px;
    color: #444;
    text-transform: uppercase;
    font-weight: bold;
    font-size: 0.8em;
    letter-spacing: 0.2em;
    position: absolute;
    top: 0;
    left: 0;
}
.bar-vertical {
    position: absolute;
    bottom: 0px;
    left: 0px;
    width: 100%;
    background: rgba(200,200,200,0.5);
}

Finally, we use more of Pure's built-in modules to create a styled table for an "events" module, and we reuse the horizontal bar class for the weather module. We extend these classes with customized CSS as well. Here is the markup for the last two modules.

<section class="dashboard pure-g-r clearfix">
    <div class="pure-u-2-3 dashboard-piece dashboard-piece-graybg dashboard-piece-events">
        <div class="dashboard-content">
            <p class="dashboard-metric">
                <h2><i class="fontawesome-calendar"></i></h2>
                <h3>Upcoming Events</h3>
                <table class="pure-table pure-table-center pure-table-horizontal pure-table-dark">
                    <thead>
                        <tr>
                            <th>With:</th>
                            <th>Where:</th>
                            <th>When:</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>John Smith</td>
                            <td>WDTuts Office</td>
                            <td>Jun 20, 9:30AM</td>
                        </tr>
                        <tr class="pure-table-odd">
                            <td>George Bluth</td>
                            <td>Sudden Valley</td>
                            <td>Jun 23, 4PM</td>
                        </tr>
                        <tr>
                            <td>Michael Scott</td>
                            <td>Scranton, PA</td>
                            <td>Jun 24, 2:45PM</td>
                        </tr>
                    </tbody>
                </table>
            </p>
        </div>
    </div>
    <div class="pure-u-1-3 dashboard-piece dashboard-piece-purplebg weather weather-rain">
        <div class="dashboard-content">
            <p class="dashboard-metric">
                <h2><i class="fontawesome-umbrella"></i></h2>
                <div class="dashboard-metric">
                    <strong>80% Chance</strong><br><small>of Precipitation</small>
                    <div class="light bar-horizontal">
                        <div class="bar-horizontal-bar" style="width:80%">80%</div>
                    </div>
                </div>
            </p>
        </div>
    </div>
</section>
<footer>
    &copy; 2013 Envato
</footer>

And the extended Pure table classes.

.pure-table-center {
    margin: 0 auto;
}
.pure-table-dark { color: #ddd; }
.pure-table-dark .pure-table-odd { color: #444; }

Lastly, we want to slightly pad the top of the weather module so that it fits more in line with the events module. We do so by simply utilizing the extra "weather" class and adjusting the top padding. Along with these last pieces, we'll add some simple footer styling to match the top nav menu.

.weather {
    padding-top: 60px;
}
footer {
    background: rgb(20,20,20);
    color: #aaa;
    padding: 10px;
    font-size: 0.6em;
    font-weight: bold;
}

Extending Responsiveness

Pure comes with built-in responsive grid elements. They are defined with the following selector.

.pure-g-r>[class ^="pure-u"]

This is a tricky looking selector (take a look at The 30 CSS Selectors you Must Memorize for in depth explanations) which first points to direct children of ".pure-g-r" elements. Those children must then have a class attribute which starts with the "pure-u" prefix. Phew.

It points, for example, to this div:

<section class="dashboard pure-g-r clearfix">
    <div class="pure-u-2-3 dashboard-piece dashboard-piece-graybg dashboard-piece-events">

This selector is used inside @media queries to collapse the grid. However, these unit elements collapse to 100% below 767px. We want to change this to allow the elements to collapse down to 50% between 480 and 767. We do so with the following @media queries.

@media only screen and (max-width:767px) {
    .pure-g-r>[class ^="pure-u"]{width:50%; float: left;}
}
@media only screen and (max-width:480px) {
    .pure-g-r>[class ^="pure-u"]{width:100%; }
}

A Splash of JavaScript

In 'main.js', we will write some JavaScript to make sure all of the modules on a single row are the same height.

(function(){
var to;

	function pieceHeights(){
		to = setTimeout(function(){
			$(".pure-g-r").each(function(i,el){
				var contentPieces = $(el).find(".dashboard-piece");
				var max = 0;
				contentPieces.css("min-height","");
				$.grep(contentPieces, function(el,i){
					max = Math.max($(el).outerHeight(),max);
				});
				contentPieces.css("min-height", max);
			});
		}, 400);
	}

	$(window).on("resize", function(){
		clearTimeout(to);
		pieceHeights();
	}).trigger("resize");

}());

This JavaScript defines a function that loops through each of the elements with a class of "dashboard-piece" in each row, and subsequently finds the tallest module in that row. It then sets all elements in that row to the height of the tallest element in the row.


Conclusion

This tutorial only shows some of the modules defined in Pure. With patterns like those used in this tutorial, you can create easily maintainable, readable, and scalable CSS. Using a small library like Pure allows you to leverage a powerful, tested, and well documented solution to common problems.

What else would you do with Pure? Let us know in the comments!

Related Posts