Design Systems: Building for the Future

The modern web design and development process is rapidly evolving, and responsive websites are quickly becoming the norm. Frameworks like Bootstrap and Foundation are showing us the value of creating robust systems of components to make building things on the web faster, better, and easier.

About a year ago, I joined LA-based web hosting and cloud services company (mt) Media Temple as a UX Engineer. Tasked with leading the front-end development of (mt)’s website redesign, I took the opportunity to slow down and revisit my front-end development approach. That’s how I realized that the way I was previously building large websites was a little flawed. I wanted to share some of my learning process and shed some light on the high-level approach I chose to take while learning about and building a design system.

But what exactly is a design system?

At FOWA 2013 in London, Mark Otto described a design system as “everything that makes up your product” (see his entire talk here: Build your own Bootstrap).

Everything? Everything. From typography, layouts and grids, colors, icons, components and coding conventions, to voice and tone, style-guide and documentation, a design system is bringing all of these together in a way that allows your entire team to learn, build, and grow.

At first, I wasn’t sure whether I should start building something custom or begin with an existing framework like Bootstrap. Ultimately, I decided against using the latter for a few reasons:

We already had a custom design. When I started at Media Temple, the visual designs for the new site were just about complete. If I used a framework, I’d have to significantly customize it to fit our designs.

I wanted to establish coding conventions and structure based on my team’s preferences. Again, I’d have to spend a ton of time re-naming classes or reorganizing things to fit our needs.

The amount of time I would spend essentially gutting the framework didn’t seem worth it. I felt like building our own framework would be beneficial to us in the long run, more maintainable, and, as a bonus, would be an incredible learning experience. It also helped that I had the time to do it, and an entire team that was excited to be a part of it.

Establish Top Level Goals

When rebuilding a legacy website, you're presented with the opportunity to improve a lot of things. Before I began any actual development, I started out by establishing some top level goals:

Organization: A messy codebase can become a nightmare to work with. Making sure we had a well thought-out structure and approach was very important.

Maintainability: Over time, there are going to be new developers jumping in to fix bugs and add features. We needed to have proper guidelines and conventions to make it easy for people to do things correctly.

Responsiveness: Having seen a steady rise in mobile/tablet traffic, it was very important to make the experience platform-agnostic.

Scalability: The company will grow in the future, and so should its website. Creating promotional pages and/or new product pages should no longer be an unpleasant (and near impossible) task.

Previously, while building large websites, I was used to dividing the work by page templates. I’d tackle a set of related templates, then move on to another set. The problem with this approach is that, if the communication between the team isn’t exceptional, you’ll end up with many similar — sometimes identical — modules and components marked up and styled in different ways. If you don’t spend the extra time refactoring them, your codebase will turn into an absolute mess.

I decided to study two excellent — but different — projects very deeply: InuitCSS by Harry Roberts and Bootstrap by Mark Otto and Jacob Thornton, and I quickly realized the next step I needed to make was to establish guidelines around how our HTML, CSS, and JavaScript should be coded and what our overall front-end approach should be.

Coding Conventions and Guidelines

Inspired by Idiomatic HTML, CSS Guidelines, and Idiomatic JavaScript, I began adapting these into our own set of coding guidelines. In the process, I discovered and adopted an interesting naming methodology called BEM (Block, Element, Modifier). It’s essentially a clever way of naming your CSS classes to make them more meaningful and simpler to understand.

Our slightly modified convention is:

.block {} - Represents the main component.

.block-elementName {} - A child element that helps make up the component as a whole.

.block--modifier {} - A modifier class that is used to alter the state or appearance of the component.

Developing Base Styles

Similar to InuitCSS and Bootstrap, I created a primary stylesheet called mt-global.less which would import all of the site styles together and create the final mt-global.css file. In an effort to keep things organized, I created a few folders:

base - For all of the underlying base styles like typography, colors, and structure.

I started out with normalize.css, adapting it as needed, and continued styling general elements such as headings, links, lists, form elements, and tables.

Identify and Build Components

With the base styles in place, it was time to take a look at the website as a whole, and start identifying individual components. I started building a custom grid system based on the grid used for the designs. From there I continued on to common elements like buttons, call to action links, hero units, and navigation.

As I was building components, I started figuring out ways to abstract common styles into reusable objects, similar to the media object. InuitCSS was a huge help here as it contains tons of useful objects. All of these styles were put into folder called components.

Identify and Build Modules

With most of the components ready to go, it was time to use these building blocks to create each page’s various modules. I created another folder called modules, and began putting them together, starting with global modules like the site header, footer, and hero unit.

Establishing Patterns

Sections of the preliminary style-guide.

As I was building components and modules I started to plug them into a style guide using the Style-Guide Boilerplate. The result was a single point of reference for any team member interested in learning how to contribute to the website. Once the whole team had access to the style guide, building page templates was a breeze. It was just a matter of mixing and matching modules, and extending or customizing them when necessary.

In Conclusion

Building a design system is a long process filled with trial and error. Established frameworks can save you weeks of development time, but if you’ve built your web project with a framework that has since gone through many releases, maintaining it can be difficult. Do you upgrade your codebase with each release? What if you have customized it so much that updating it isn’t even an option?

If you have the opportunity to rebuild a site from the ground up, building a custom solution solves a lot of issues: It helps establish a custom tailored system enabling your entire team to quickly and easily learn how to contribute to your project; it’s built by you and specifically for your company’s needs; and, most importantly, it’s built for the future. Without being tied down to another project’s evolution and direction, it’s free to scale at your companies pace.

Above all, it was an incredible learning experience and a great source of pride for our team. I encourage everyone to study the many resources available about design systems and the ever-changing web design process.

Share this:

Related

Comments

I’ve successfully used a BEM variant on a couple projects and I felt that it made support quite a bit easier. I strongly recommend using __ as a separator between blocks, elements, and subelements. It allows you to use standard hyphenated names for blocks and elements.

I find foo-bar and foo-bar__baz easier to read than fooBar and fooBar-baz, but YMMV.

That said, it takes some getting used to and can be easy to mess up. Developers new to BEM often forget that they need to add both the block and block--modified classes to elements, or will mix up modifiers by using something like:

<!-- THIS IS WRONG, DON'T DO IT THIS WAY -->
<div class="block block--modified">
<div class="block__element block__element--modified">...</div>
<!-- ^^^^^^^^^^^^^^^^^^^^^^^^ -->
</div>

I’m still fairly new to web design, but I would love to get this concept down. Your article answers several questions I’ve had regarding designing systems, namely where to begin. You’ve posted some great inspirational links.

The idea of designing systems feels intimidating, I will admit, but this helps clarify how to develop my own workflow. I have one question, though. Do you think a team of one would benefit from this approach, e.g. building a personal website/blog?

Certainly! In the worst case scenario, you’ll quit the idea, will use a framework like Foundation and have learned a lot about design systems. In any case it is a win.

Also you’ll polish it every time you use it and have an awesome boilerplate for your next projects!

I’ve already used a lot of – great – frameworks, but now I’ve done my own boilerplate with the minimal code necessary and I’m more than happy with the end results of my projects. It’s easier to maintain and performances much better than any other framework I ever used (bytes count and real time performance).

Great article. We share the thinking that it is – a lot of times – a better idea to build your own “framework”. It is not that hard if you focus in the real needs of the project. Use others framework as a reference is a good thing too.
I think that the important is to have a coding convention (whatever it is BEM, OCSS or anything else), be organized and think about performance and maintainability.

It’s good to see a case of success of anyone not using a framework! Keep up the good work!

This post is so timely for me. In recent days I’ve been considering what my “position” is on using prebuilt frameworks for a large website design project. I was close to leaning towards that being a great idea because they have solved many problems with their components/modules that they saw as patterns. The issue is, the problems were solved in the context of their design. Their design problems won’t necessarily be the same as my large project’s design problems. However, I really resonate with your approach of still learning from these excellent frameworks. And I also love the idea that, in the end, the team that has built the framework from the ground up will feel more rewarded from both seeing the fruit of their work and being confident in their ability to continue maintaining and customizing it effectively.

So I wowed at your modified syntax, which sports a single “-” for children elements.

But then I wondered (and here’s the question): what about elements composed of 2 words? Camel casing is just about as ugly as double underscores, so what’s your proposition? Maybe avoid 2-words elements at all?

I used to distinguish between components and modules, too. But those categories are often very vague. It is often not clear whether something should be considered a module or a component. You could say anything that is used by modules should be a component but that didn’t always work for me.

Another question: Where do you put basic layout styles? E.g. wrapper elements for sticky footers, main element (could be also considered a module with submodules)

Thank you so much for the useful article. Will certainly try and use these resources for upcoming tasks. We face a similar situation at work where we used a previous version of the framework and the framework has been refactored quite a bit in the next release. We decided to stay back.

This is pretty uncanny. After playing around with OOCSS, BEM and SMACSS. I’ve pretty much formed the exact same pattern as you guys even down to the way that you structure your modifiers and children with — and -. I’m really happy with this approach it’s simple enough that it doesn’t get in your way and still keeps everything nicely structured. Thanks for the great article.

I would love to do this at work, but I’ve been getting no support for the idea despite how badly it’s needed. We have multiple designers who code the designs and hand them off for polishing, so it’s non-coders all coding differently, essentially. I feel like this would save soooo much time and headaches!

I do have to say that double dashes in class names scare me, though. Other than that, I totally structure my personal code like that, a semantic item and its sub-items all named similarly. I never have to keep looking back to remember a class name. ;)

Excellent article Ara. I actually just finished a complete front-end redesign for my company myself, and it’s amazing how similar our thought processes are. From similar goals, to using the LESS pre-processor, all the way to conceptualizing page elements using BEM methodology. I chose to use a slight variant of the BEM naming convention though, by prefixing modifiers with a double underscore instead:

block--element__modifier

A popular practice is to separate skin from structure, did you try this? Personally I found that keeping both skin and structure styles within the same selector was more convenient (as opposed to having to switch between multiple stylesheets/locations to style the same element). Instead, for most of my resuable “skin” related styles, I opted to abstract them into mixins and variables.

I also tried to separate skin from structure in SASS. Didn’t work for me either, I was always asking myself “is this property in the structure or in the skin?”. It was a matter of seconds, but in the end it wasn’t worth it.

I found way more useful to create a set of variables at the beginning of the file, which managed both the structure (height, padding, etc) and the presentation (color, borders, etc). Cleaner and easier to maintain, IMO.

Very interesting article. I love the strap-line of “Create your own Bootstrap”. I always learn from resources like Bootstrap but rarely use them on projects as i prefer to keep the code as waste-less as possible.

Congratulations on taking the plunge, and thanks for a nice positive summary of what you and your team accomplished. I’ve been inventing systems like this for the past few years and there is a lot to consider to truly keep the system modular and prevent it from becoming a white elephant.

My own ‘a-ha’ moment has been a slow realisation that it is a highly complex system that needs input, buy-in and support from more than just myself. Researching what is out there and discussing your ideas and assumptions with other people is really important to ensure that what you build is truly useful rather than just an expensive showpiece, and isn’t reinventing a wheel that already exists.

Great stuff. Thanks for the inspiration. No doubt this gets filed under: “If it were easy, everyone would do it.”

A couple thoughts:

1) While I appreciate the effort to develop your own framework, if you think of the entire effort as an integrated end-to-end system then to me it makes more sense to maintain modularity across all vectors within the system. A specific example would be the human resources slice and training. That is, finding someone who is Bootstrap-centric is going to be much easier than finding someone who knows your system (i.e., which is no one aside from the people you hire and train). Yours might be a better mouse trap, but does the benefit outweigh the added friction?

2) Mind you, I understand there were extenuating circumstance, but to build out a framework because design was done in a silo / void also feels a bit “out of character” to me. Or as I like to ask: Name me a successful product company that does product design without any consideration for manufacturing. Toyota, for example, certainly doesn’t design a product (i.e., car) and then ask, “Okay, how are we going to build this? At a price the market will bear?” It’s an integrated system, not a series of silos connected by some spit & scotch tape process., yes?

3) Which leads me to: Ara (or Chris) is any any chance of taking these concepts and ideals and doing an article / series to discuss how to (best) apply them in an agency setting? That is, one team (read: some core, some revolving) servicing many clients / brands? What are the must-dos, the watch-out-fors, etc.? How do you build a core tool box and then extend and customize that for individual projects and/or clients?

This comment thread is closed. If you have important information to share, please contact us.