The HAL system of helpers, appearance and layout came as an idea based on SMACSS. It came out of the need to develop front end designs quickly without needing to continually add new styles to an ever growing stylesheet.

There are three pieces to this system:

  • Leverage the use of helper classes on elements for styling.
  • Seperate the appearance of an element from its layout.
  • Easily memorizable and repeatable code for front end developers.

A System for Front End Developers

This part isn't in the HAL acronym, but making your CSS framework easy to work with is the most important takeaway of the system.

HAL keeps us out of our stylesheets. The only reason we edit those stylesheets is to either add additional helpers, or tweak existing styles. Because of this, HAL really demands the usage of HTML Components, like what you would see in frameworks like Vue and Svelte.

HAL still has global stylesheets, and I suggest organizing these stylesheets under SMACSS guidelines.

Design elements that need a specific class or HTML structure must be a component.

HAL deviates from SMACSS in that is does not like modules of CSS in stylesheets. In the HAL system we want to avoid needing to memorize abstract, arbitrary or semantic class names. You should never need to remember that `<input type="button">` needs to have a class combination of `btn btn-small btn-primary`.

By using components we can remove the human error element from styling. It's frightently easy even for front end developers to forget a particular class already exists and create duplicate a selector as a result. It also reduces the amount of styling other developers have to contend with, a common complaint I hear from backend developers isn't working with HTML, it's having to work with CSS and CSS class names. This brings me to the next point...

HAL is meant to be easy to understand for front end developers

I initially tried to create a CSS architecture that would be backend developer friendly. What I ended up creating was a system that was easy for front end developers to understand.

Helper classes are a big part of HAL for rapidly laying out elements and overriding base styles. All of the helper classes have names based on their CSS instructions:

A typical helper class.

.display-flex { display: flex; } .justify-content-center { justify-content: center; }
undefined

I actually found a lot of similarities to the helper classes I was creating for HAL to what Bootstrap was already doing. The similarities were close enough that I began to rewrite helper classes to conform with Bootstrap's naming. Since HAL is philosophy, it's also possible to plug Bootstrap into a project and use that as a helper library. Bootstrap has it's pros and cons that I won't get into, but HAL functions great with it.

Keep appearance seperate from layout.

This is a fairly simple rule at heart. The idea is to keep styles that dictate what elements look like seperate from how elements are arranged. When we do this, it's easier to rearrange elements without changing their appearance, and vice versa. It also helps us decide where best to put styles.

The simplest application of this is for the main layout of a given application, your header, footer, sidebars and content box. Suppose you have the following design:

Our HTML

<div class="main"> <div class="header"> Header </div> <div class="left-sidebar"> Sidebar </div> <div class="content"> B </div> <div class="right-sidebar"> Sidebar </div> <div class="footer"> Footer </div> </div>
undefined

Our CSS

.main { display: grid; grid-template-areas: 'header header header' 'left-sidebar content right-sidebar' 'footer footer footer'; grid-template-columns: 1fr 4fr 1fr; grid-template-rows: auto 1fr auto; grid-gap: 10px; height: 100vh; } .header { grid-area: header; } .left-sidebar { grid-area: left-sidebar; margin-left: 0.5rem; } .content { grid-area: content; } .right-sidebar { grid-area: right-sidebar; margin-right: 0.5rem; } .footer { grid-area: footer; }
undefined

It can be quite tempting to blend our background styles right into our layout styles:

.left-sidebar { background: gray; grid-area: left-sidebar; margin-left: 0.5rem; }
undefined

For our simple use case is this entirely innocuous, but we run into problems in larger applications where we have the following factors to deal with:

  • Logic integrated with front end code, such as conditionals, loops and variables.
  • Large components with hundreds of lines of code.
  • Elements within elements.

As an application grows and design changes are made, this tends to lead to technical debt, excessive CSS overrides and broken layouts.

Components make it real easy to seperate appearance from layout, using Svelte as the example here:

Our layout component.

<div class="main"> <div class="header"> Header </div> <Sidebar class="left-sidebar" /> <div class="content"> B </div> <Sidebar class="left" side="right" /> <div class="footer"> Footer </div> </div>
undefined
.left-sidebar { grid-area: left-sidebar; margin-left: 0.5rem; }
undefined

Our sidebar component.

<div> Sidebar </div>
undefined
div { background: gray; }
undefined

There are a few other methods that can be done to keep appearance styles seperate from layout styles, but components don't come with hidden drawbacks like the following methods have:

  • Using seperate selectors.
  • Using seperate classes.
  • Applying styles in seperate code blocks.

Using Helpers Effectively

This is the last section in HAL because on their own, helper classes look like a terrible mess of an idea.

Let's first build something like the following element a few different ways. This way we can see the extreme bell end of helper classes:

Using Helper Classes
Using CSS Only

The CSS Only example is going to look really nice here:

Our HTML

<div class="example-card"> <div class="example-card-header">Using CSS Only</div> <div class="example-card-body"> <div> <label class="example-card-label">Name</label> <input type="text" class="example-card-input" /> </div> <div> <label class="example-card-label">Summary</label> <input type="text" class="example-card-input" /> </div> </div> </div>
undefined

Our CSS

.example-card-header { background: var(--magenta-50); border-top-left-radius: var(--border-radius); border-top-right-radius: var(--border-radius); padding: 0.25rem 0.5rem; color: var(--white-50); } .example-card-body { background: var(--gray-400); border: 1px solid var(--magenta-50); border-bottom-left-radius: var(--border-radius); border-bottom-right-radius: var(--border-radius); padding: 0.5rem 0.5rem 1rem; } .example-card-body > div { margin-bottom: 0.5rem; } .example-card-body > div:last-child { margin-bottom: 0; } .example-card-label, .example-card-input { display: block; } .example-card-input { border-radius: var(--border-radius); border: 1px solid var(--gray-75); padding: 0.25rem; }
undefined

Using only helper classes we don't need any CSS, though we do end up with excessively long class attributes:

<div> <div class="background-magenta-50 text-white-50 padding-1 padding-left-2 padding-right-2 border-radius-top-left border-radius-top-right"> Using Helper Classes </div> <div class="border-magenta-50 border-radius-bottom-left border-radius-bottom-right padding-2 padding-bottom-4 background-gray-400 row-margin-4"> <div> <label class="display-block">Name</label> <input type="text" class="background-gray-500 border-gray-50 border-radius padding-1" /> </div> <div> <label class="display-block">Summary</label> <input type="text" class="background-gray-500 border-gray-50 border-radius padding-1" /> </div> </div> </div>
undefined

We can see why Bootstrap decided to abbreviate class names like margin, padding and background resulting in a more convincing and concise look for helpers only. This is also why we still have global stylesheets that establish base styles for elements like label and input:

<div> <div class="bg-magenta-50 text-white-50 p-1 ps-2 pe-2 border-radius-tl border-radius-tr"> Using Helper Classes </div> <div class="border-magenta-50 border-radius-bl border-radius-br p-2 pb-4 bg-gray-400 row-margin-4"> <div> <label>Name</label> <input type="text" /> </div> <div> <label>Summary</label> <input type="text" /> </div> </div> </div>
undefined

HAL does not dictate which of the two methods above to use, or to which extent both methods can be blended together. HAL only requires of the CSS only example that all custom CSS is confined to a immediate and relavent component.

The big no-no with HAL is to create CSS class modules in our global stylesheets:

<div> <div class="bg-magenta-50 text-white-50 p-1 ps-2 pe-2 border-radius-tl border-radius-tr"> <!-- DON'T DO THIS --> <div class="card-title">Card title is a class in base.scss!</div> <!-- JUST DON'T --> </div> <div class="border-magenta-50 border-radius-bl border-radius-br p-2 pb-4 bg-gray-400 row-margin-4"> <div> <label>Name</label> <input type="text" /> </div> <div> <label>Summary</label> <input type="text" /> </div> </div> </div>
undefined

Where helpers really shine is when you have a concise grouping of elements, take the following design:

We can get away with just two helper classes:

<div class="display-flex justify-content-around"> <Container /> <FirstContainer /> <LocalNavigation /> </div>
undefined

Which I find to be much easier and faster than writing up one off classes in a style tag at the bottom of a component:

Our HTML

<div class="come-up-with-something-creative-here-okay"> <Container /> <FirstContainer /> <LocalNavigation /> </div>
undefined

Our CSS

.come-up-with-something-creative-here-okay { display: flex; justify-content: around; }
undefined

This last example is important, because we will find these micro-styling situations everywhere within a web application. The CSS Only example is fine until you start to find yourself repeatadly having to invent a new class name for another element that contains some combination of display: flex; justify-content: around;. Helper classes not only keep our stylesheets neat and tidy, they also help keep the style tags in our components free from repeat instructions that can cloud out our more complex styles (like transitions and animations).