The ‘nav’ abstraction

This post comes in a similar vein to Nicole Sullivan’s genius The media object saves hundreds of lines of code.

An abstraction is basically removing a pattern from a specific idea and making a more generic idea out of it. That is to say, rather than writing the same similar patterns over and over, create a single more generic representation of those patterns and reuse that instead.

Nicole does this with her media block by taking a series of similarly constructed but different components and sharing their common aspects in a more generic way. This is a really sensible and useful abstraction whereby she can make a pretty much infinite amount of pretty different blocks of content using only the same handful of lines of CSS each time. Genius!

Her media block abstraction is a pretty common one, and one I’ve used myself. Today I’m going to share another abstraction that may well be even more common and hopefully just as handy; the nav abstraction.

I’m sure you’ve had loads of projects where you’ve had a horizontal nav, and also maybe a breadcrumb trail and possibly a list of logos that go in a banner-style list…?

If this is the case then I also imagine you might have written something like:

#nav{
  list-style:none;
  margin-left:0;
}
#nav li{
  display:inline;
}
#nav a{
  ...
  [styles]
  ...
}

.breadcrumb{
  list-style:none;
  margin-left:0;
}
.breadcrumb li{
  display:inline;
}
.breadcrumb a{
  ...
  [styles]
  ...
}

.sponsors{
  list-style:none;
  margin-left:0;
}
.sponsors li{
  display:inline;
}
.sponsors a{
  ...
  [styles]
  ...
}

Here we can see that, although we’re building three different things, we’re reusing quite a few repeated patterns to create similar looking things. We need an abstraction.

The nav abstraction

Now, I’m not sure whether nav is actually the best word to use; these three examples are all types of navigational constructs, but that’s more coincidence than anything else. As such I encourage you to please offer up your alternative recommendations in the comments, please!

What we need to do now is take out the shared patterns and create a fourth class of .nav:

.nav{
  list-style:none;
  margin-left:0;
}
.nav li{
  display:inline;
}
.nav a{
  display:inline-block;
}

Here we define our abstraction. We take the repeated bits and make the most granular construct we can. This will throw any list into a very basic/crude horizontal series of links which we can then extend to adopt more specific styles, like so:

.nav{
  list-style:none;
  margin-left:0;
}
.nav li{
  display:inline;
}
.nav a{
  display:inline-block;
}

.site-nav{
  width:100%;
  background:#eee;
}
.site-nav a{
  padding:5px 10px;
}

.breadcrumb li:before{
    content:"» "
}
.breadcrumb li:first-child:before{
    content:normal;
}

.sponsors{
  text-align:center;
}

Using a base abstraction and then extending it we can create our breadcrumb with this HTML:

<ol class="nav breadcrumb">
    <li><a href="/">Home</a></li>
    <li><a href="/about/">About</a></li>
    <li><a href="/about/us/">About us</a></li>
</ol>

Writing abstractions gives smaller CSS, removes unnecessary repetitions and makes simple elements of your design much more reusable. Nice!

By Harry Roberts on Thursday, September 22nd, 2011 in Web Development. Tags: , , , , | 9 Comments »

+

9 Responses to ‘The ‘nav’ abstraction’


  1. trovster said on 22 September, 2011 at 5:17 pm

    I use a similar technique, but much prefer to add multiple selectors to the abstraction than litter my HTML with extra classes — although I’m not completely adverse to using .button or similar. Both have their benefits, don’t get me wrong, but I just despise seeing class=”clearfix” everywhere in the HTML. Instead, I have the clearfix code in a block, then add the selectors I want to that.

    #content,
    footer,
    article.special {clearfix code goes in here}

    I do the same for image replacement, screen-reader friendly hiding of elements and resetting lists (as per your example). See;

    /* @group Hide */
    form legend,
    p.more a span {
    position: absolute; left: -9999px;
    overflow: hidden;
    height: 0; width: 0;
    font-size: 0; line-height: 0;
    }
    /* @end */

    /* @group Image Replacement */
    .logo,
    .button,
    .previous,
    .next {
    overflow: hidden;
    display: block;
    margin: 0; padding: 0;
    font-size: 0; line-height: 0; text-decoration: none; text-indent: -9999px;
    background: transparent no-repeat 0 0;
    border: 0;
    -moz-border-radius: 0; -webkit-border-radius: 0;
    -o-border-radius: 0; -ms-border-radius: 0;
    border-radius: 0;
    }
    /* @end */

    /* @group Reset Lists */
    nav,
    nav ul,
    nav li,
    .categories,
    .categories li,
    .tags,
    .tags li {
    margin: 0; padding: 0;
    list-style: none;
    background-image: none;
    }
    /* @end */


  2. Ivan Nikolić said on 22 September, 2011 at 5:32 pm

    Couldn’t agree more and I think everyone should revisit their written code on regular basis when working on project to refactor and restructure it for easier maintenance.


  3. Ben Cooper said on 23 September, 2011 at 7:39 am

    @Trovster – This is the way i used to code but over the months i’ve been thinking more and more around front end performance …. I agree with Harry as i feel this approach is a lot cleaner and performance wise it is a lot quicker but i do understand where your coming from. I hate .clearfix too :( erghhhhh


  4. kikito said on 24 September, 2011 at 10:30 am

    I usually call that abstraction “hlist”. As in “horizontal list”.

    I know some people will cringe on seeing that (presentational classes!). I don’t know what to say. I’ve used it on several projects and it just … feels right.


  5. Daniel said on 24 September, 2011 at 4:15 pm

    This is very interesting! I will now try to use elements for their intended purpose, not just because that is the “norm”. Nice article :)


  6. Fabio Venni said on 25 September, 2011 at 3:38 pm

    These are small things that are totally sensible especially when working with other people that will have to reuse your css. BTW I usually call this “crumbs”.

    I use this pattern to also apply rounded corners, paddings, backgrounds to boxes and for that I use the .panel or .widget class.

    @Trevoster well, one might argue that “nav” is semantically valid metadata, it didn’t propose items-that-will-get-rendered-side-by-side
    it ain’t comparable to “clearifx” that is just pure layout crap that brings no value to the content!


  7. John Faulds said on 27 September, 2011 at 11:46 am

    I’ve been doing the same for some time now except rather than using a class of .nav these days I use [role=navigation].


  8. Bruno said on 5 October, 2011 at 3:20 pm

    Totally agree: abstraction is key (and semantic abstraction even more).

    My proposal as a replacement for nav (although I find hlist is adequate): ribbon.

    And regarding the debate initiated by @trovster, I’d only wish that CSS classes could inherit from one another (you know, like classes in object-oriented languages).


  9. Aurélien said on 22 June, 2012 at 1:06 pm

    To answer your comment, instead of .nav we could say .link-series :)


Leave a Reply

Respond to The ‘nav’ abstraction

Hi there, I am Harry Roberts. I am a 21 year old web developer from the UK. I Tweet and write about web standards, typography, best practices and everything in between. You should browse and search my archives and follow me on Twitter, 7,791 people do.

via Ad Packs