Design Systems: Building for the Future
This post was originally published on CSS-Tricks.
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.
My “a-ha” moment
With the top level goals in mind, I started doing extensive research. I began by reading about HTML semantics and front-end architecture and discovered the benefits of building flexible modules, not pages. That was my “a-ha” moment.
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.
Here is an example of an alert box using this approach:
/* Main 'alert' component */
.alert {}
/* Sub-components that make up the 'alert' */
.alert-text {}
.alert-close {}
/* Modifiers for various styles of the 'alert' */
.alert--warning {}
.alert--error {}
.alert--success {}
.alert--info {}
I also finalized a set of tools to help us along the way, including LESS for our CSS pre-processing needs, and Grunt to compile our LESS files and compress, minify, and concatenate our code.
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:
- core – This would hold our custom variables and mixins.
- vendor – For vendor utilities used, such as LESSHat and REMixins.
- 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
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.
Research. Build. Learn. Repeat.
John Polacek
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.