High Reuse Web Interfaces
Writing HTML and CSS that can be used anywhere without breaking
September 10, 2016
HTML and CSS maintainability, scalability and reusability is often taken for granted. Just because HTML Just Works™ and we can just pop in a CSS framework that Just Works™ doesn't mean it doesn't require the same amount of attention as your JS architecture, your PHP code quality or your awesome Java code. In most cases, it's actually HTML and CSS spaghetti that will slow you down. Here's how you can cut down development time by keeping these 5 little steps in mind when building web interfaces.
Phase 1: Look for common design elements
We have this piece that looks like a "Pinterest card": A box with a linked image, linked title and some summary text. It appears in 7 types of pages... but was implemented in 7 different ways. It was because it was done by different developers, had slight cosmetic differences, and were spread in different sprints. These, along with other factors, distorted how the developers saw the piece and squandered reusability.
Ignore implementation, ignore slight cosmetic differences, ignore development schedules and ceremonies, and look at the bigger picture. When you start implementing a piece, be pro-active. Scan your design documents and gather information about this piece, whether it's a recurring item or not. This should give you a clue if this piece is specific to the page or if you should be writing with reusability in mind.
Phase 2: Write semantic markup
Writing semantic markup is a forgotten art but will pay dividends down the line. If you write semantic markup, you won't be staring at a pile of <div>
s and instead, stare at markup that actually makes sense. Since you won't be dealing with real data just yet, you can drop in your favorite flavor of Lipsum and placeholder images.
<article>
<header>
<a href="...">
<img src="...">
</a>
<a href="...">
<span>...</span>
</a>
</header>
<section>
<p>...</p>
</section>
</article>
Phase 3: Name your elements
(I won't discuss what BEM is, how it works, or what problems it solves. You can read that on their website.)
One of the hardest things in computer science, besides cache invalidation, is naming. And it's no different in CSS, where half of the work is coming up with sensible names for your selectors. Luckily, designers unknowingly did the work for you.
Designers need to convince stakeholders to use a design. To do so, they will come up with easy to remember names for pieces of functionality on the pages. Once approved, these names end up in the design document. This strategy works as all parties, including stakeholders, know what everyone is talking about.
<article class="content-pod">
<header class="content-pod__header">
<a class="content-pod__image-link" href="...">
<img class="content-pod__image" src="...">
</a>
<a class="content-pod__title-link" href="...">
<span class="content-pod__title">...</span>
</a>
</header>
<section class="content-pod__content">
<p class="content-pod__text">...</p>
</section>
</article>
Phase 4: Write 1-to-1 CSS
CSS is not meant to style application interfaces, I've mentioned that in my other article.
When you style a "panel" in Swing, or XCode, or Visual Studio, or Flex Builder, you select the panel, go over the styles pane, and update the attributes, done. But that's not the case in CSS. When you apply color
and font-size
to a <div>
, it's not just the <div>
or its children that gets affected. It applies to everything under the <div>
. And that's not even a guarantee. There might be other style definitions that can override it. You are never sure how the <div>
will come out with all these colliding CSS.
So instead of having to worry about this non-deterministic behavior, we do CSS by not doing CSS. We throw away what makes CSS, well... CSS. We are going to enforce the 1-to-1 style system that other systems use. With this, you can guarantee 90% of the time that your element will look like what you wrote. The other 10% would come from the inherent styling behavior of CSS and HTML that you'll have to look out for.
.content-pod{}
.content-pod__{}
.content-pod__header{}
.content-pod__image{}
.content-pod__image-link{}
.content-pod__title-link{}
.content-pod__title{}
.content-pod__content{}
.content-pod__text{}
Phase 5: Apply everywhere
We now have the markup and the styles that go with it. All we need now is to pop it in our app and fill in the blanks, rinse, and repeat. The structure and styles have been immortalized. You don't have to write CSS anymore. If something requires the same design, just copy over the same markup. Once you apply the same markup, it will look the same.
Here's the piece used in a Drupal template:
<article class="content-pod">
<header class="content-pod__header">
<a class="content-pod__image-link" href="<?php print render('field_article_link'); ?>">
<img class="content-pod__image" src="<?php print render('field_article_image'); ?>">
</a>
<a class="content-pod__title-link" href="<?php print render('field_article_link'); ?>">
<span class="content-pod__title"><?php print render('field_article_title'); ?></span>
</a>
</header>
<section class="content-pod__content">
<p class="content-pod__text">
<?php print render('field_article_body'); ?>
</p>
</section>
</article>
Here's the same piece but used in an Angular template:
<article class="content-pod">
<header class="content-pod__header">
<a class="content-pod__image-link" href="{{article_link}}">
<img class="content-pod__image" src="{{article_image}}">
</a>
<a class="content-pod__title-link" href="{{article_link}}">
<span class="content-pod__title">
{{article_title}}
</span>
</a>
</header>
<section class="content-pod__content">
<p class="content-pod__text">
{{article_body}}
</p>
</section>
</article>
If this phase sounds familiar to you, it's because it's the same approach as every CSS framework out there. If you want to create a modal in Bootstrap, what you normally do is copy the modal markup from their site to your app and assuming you have Bootstrap in place, everything it Just Works™. No writing of CSS required to get that base modal. The only difference is that CSS frameworks already did phases 1-4 for you.
Conclusion
This is by no means a foolproof solution and you should take it with a grain of salt. But that's what conventions are for. They're not strict rules, you can totally break them, but if you follow them they make life easier.