Tags : CSS

Classic CSS approaches: Strong vs Loose Coupling

Tags : CSS

In this article, we will be revising the different approaches that can be taken to class naming and writing CSS.

Some front-end developers may not be familiar with the terms ‘strong coupling’ and ‘loose coupling’. It’s more of a programmer’s concept, but it applies to the world of CSS in a similar way.

A good understanding of these concepts, when to apply them and how, can lead to better maintainability or safer code.

Strong Coupling

Imagine you had a widget on your website – ‘Latest Blog Posts’.

<div class=”latest-blog-posts”>
<h2>Blog Posts</h2>
<article>
<h3>Blog Post</h3>
<p>Lorem ipsum dolor…</p>
</article>
<article>
<h3>Blog post</h3>
<p>Lorem ipsum dolor…</p>
</article>
</div>

This widget needs to be styled, these are the requirements:

  • The latest blog posts heading is 24px and blue.
  • Each article heading is 18px and green.
  • Articles are separated by a grey horizontal border.

It’s easy now to write the css based on each point:

.latest-blog-posts h2 {
      font-size: 24px;
      color: blue;
}
.latest-blog-posts article {
      border-bottom: solid 1px grey;
}
.latest-blog-posts h3 {
      font-size: 18px;
color: green;
}

The end result is strongly coupled CSS. It’s semantic, logical and enforces an html structure. The ‘latest-blog-posts’ div must contain an h2, h3s and article tags.

The benefit here is that it reduces ‘classitis’ – The presence of a lot of classes in the code - which many developers find difficult to work with. However, the drawback is that it is inflexible.

Imagine if we wanted to use the same widget on another page, but we wanted the following changes:

  • h2 to be a h1 and the h3s to be h2s.
  • The main heading should be outside of the ‘latest-blog-posts’ div, and the div to have a grey border.
  • Each article is side by side.

To accomplish these changes on the new page, we would need to take one of the following approaches:

  • Give the whole thing a surrounding div with another class name. This can be used to override previously set styles.
  • Change the class name in the new HTML (EG: ‘latest-blog-posts-2’) and make another copy of the CSS accordingly; or
  • Add an extra class to ‘latest-blog-posts’ to override everything we need to change. EG: ‘<div class=”latest-blog-posts alt-1”></div>’

The first option adds an extra div. If we wanted a third page in the future with some other changes, we would need to go through this process again. Going the first route would be consistent, but would create an inception of DIVs, as well as ever increasing specificity.

The second option safe, it means that any changes to the original widget wouldn’t affect the new widget. However, it also means duplication of code. If there are changes or bug fixes to be done, it needs to be done twice. When there are 3 or 4 or even more variations of this widget, you can see how the code can become bloated and more time consuming to maintain.

The third option requires some bloat as well, in the form of CSS values that need to be reset. It’s not much in this example, but in the real world, with a real widget, there would be a lot more overriding to do.

The second and third options also require us to add a class to the h1 to style it. Because the HTML and CSS are strongly coupled, it cannot withstand this change in structure.

You can probably see how these issues could become major problems when dealing with a widget more complex.

Loose Coupling

So let’s go back to the original code and imagine a different class structure.

<div class=”latest-blog-posts“>
<h2 class=”latest-blog-posts-heading”>Blog Posts</h2>
<article class=”latest-blog-post”>
<h3 class=”blog-post-title”>Blog Post</h3>
<p>Lorem ipsum dolor…</p>
</article>
<article>
<h3 class=”blog-post-title”>Blog post</h3>
<p>Lorem ipsum dolor…</p>
</article>
</div>

In this example, the HTML and CSS are loosely coupled. This means that it can withstand changes in structure without changing the classes or CSS selectors. Here is the example CSS:

.latest-blog-posts-heading {
      font-size: 24px;
      color: blue;
}
.latest-blog-post {
      border-bottom: solid 1px grey;
}
.blog-post-title {
      font-size: 18px;
color: green;
}

Changing the heading levels or moving the headings to a different location no longer poses any issues. The drawback is the addition of extra classes. With more complex widgets, you can imagine the classitis that would be present.

Choose what suits your project

The key is to determine what you require in your projects and find a balance. Do you want to enforce a clean, readable HTML structure and enforce consistency across the site? Should developers create their own copy of widget code for any semi-unique implementations of your original widget? Then lean towards strong coupling. Your widgets will be much safer, modifying one widget will not unintendedly modify another.

This approach is suited to a waterfall process and websites that have a lot of consistency in the design. With such consistency, you won’t be copy + pasting CSS very much as the widgets should appear the same in each of their implementations, therefore they should use the same HTML classes.

However, if the design doesn’t have much consistency, (EG: if heading styles are swapped between widgets) then it may be better to use a more loosely coupled approach. In this case, you will have less code repetition, more flexibility and better maintainability.

I would also lean towards this approach in an agile environment, as you never know what diabolical Frankenstein’s monster of a widget the client will have us create in the future. If you think that an element may be used somewhere else, it’s usually best to take a loosely coupled approach.

Non semantic approach

CSS Frameworks provide a generic library of classes that can be applied to your html. Using a framework means that when you want to alter a style, you will be changing the class within your HTML instead of, or in addition to, adding a new CSS rule. This is a very popular approach, but it’s shunned by a lot of developers for a variety of reasons.

Frameworks are often hard to customise, are bloated, only contain some of what you need and a lot of what you don’t. They can be buggy, inaccessible and may not be suitable for your project. Websites build using frameworks tend to look very similar and template-like.

Another issue is the separation of concerns ideology. Basically, the idea is that HTML should contain structured content with semantic class names and CSS should be for styling purposes only.

With frameworks, the class names describe the CSS styling instead of the HTML content. When you want to make a change to the styling, you need to change the HTML. If there are many pages with the same element that needs to be changed, you will end up changing multiple HTML pages instead of one line in the CSS.

Repetition

All of the aforementioned approaches to CSS will involve repetition. The only question is, “what repetition do you prefer? “

  • Repetition of properties in the style sheet?
  • Repetition of class names in the HTML?

The key is to control and isolate as much of the repetition as possible. It must be predictable and easy to refactor when required. When working in a digital agency with hundreds of projects that span many years and dozens of developers, you want to avoid having to take over a mess of a project or creating a mess for others down the line.

Tips for your CSS approach

I would recommend adopting a naming convention and a modular CSS pattern. You need to write things down – Create a coding standards and approach document. The more you specify as a part of your standard, the more control you will have in the future. Any future developers will know what to expect and how to work with the project in the future.

When taking a more loosely coupled approach, separate structure and theme in your CSS. A class that contains floats, widths and positions should not also contain colours, padding and fonts. This way you can re-use and switch structure classes without changing the theme of a particular element and vice-versa.

If you want to go further down this path, consider separating your CSS into structure, component and theme.

  • Structure is the positioning, width and floats. Anything that affects where the element is positioned or how much of the page it takes up.
  • Component is the padding, border width, border radius, font size. Anything that affects the look of the element in a black and white view.
  • Theme is just the colours – border, text, background etc.

You can also create utility classes if something doesn’t fall into this category.

The last tip is to prefix all of your class names. This makes them less likely to conflict with any libraries that you use in the future. It also means that you can easily identify the purpose of all of your classes and ensure that you only use one of each ‘type’ per element. For example, you may prefix your layout classes with ‘l-‘, your component classes with ‘c-‘ and your theme classes with ‘t-‘. Each element can then only use up to three classes – one of each type listed above. This prevents conflicts and unexpected results.

In the next article we will take a look at a modern CSS approach – with CSS pre-processors.