Our Markup & CSS Approach

Cantilever’s frontend development approach is minimalist. We like to wait for new technologies to be tried and tested before jumping in. We are often late to bandwagons, but always avoid fads.

We want our code to be usable by anyone. Part of digital hospitality is accessibility. All code should be written with accessibility in mind from the start. Don’t push it off until “we have more time.” That point has never actually come...

We like “native code.” We want to write code that is visually close to what the browser will actually read and parse. We like to be “close to the metal” so that we have the greatest possible understanding of what we are asking the browser to render, and we leave ourselves less vulnerable to bugs.

Markup

Markup should be written in the ideal semantic structure for the content of the page. If you look at the HTML of a given template/object as an XML document, it should pretty much make sense. Leverage semantic tags, headings and structural elements to maximize accessibility.

CSS should be subservient to markup. Markup should not become less semantic because of a CSS concern. Write clean semantic markup first, and then write CSS around it.

We are writing more comprehensive docs to capture our HTML approach. For now we recommend this writeup on semantic HTML and why it’s important:

All Markup will be run through the Development Accessibility Checklist, so it’s wise to get acquainted with it ASAP.

WAI-ARIA

Markup should utilize ARIA attributes in line with modern accessibility best practices. As a rule of thumb, if a certain piece of functionality can be accomplished using a valid ARIA attribute rather than a class or ID, use it.

The goal of ARIA is to create a standardized API for markup to provide screen readers or other non-visual technology information about the nature and state of HTML elements.

CSS

At Cantilever, we embrace the utility-first approach to CSS to ensure efficiency, reusability, and scalability in our web development projects.

Utility-First CSS Philosophy

Utility-first CSS, unlike traditional CSS methods, encourages the use of small, composable utility classes that apply single rules or a small set of rules. This approach allows developers to build complex UIs from a low-level toolkit without writing custom CSS.

Benefits of Utility-First CSS

  • Rapid Prototyping: Speed up the development process by assembling designs directly in the browser.
  • Reusability: Maximizes CSS reusability, minimizing code duplication.
  • Consistency: Ensures design consistency across projects by reusing utility classes.
  • Maintainability: Reduces the complexity of maintaining styles, as changes to utility classes propagate across all uses.

Implementing Utility-First CSS in Your Projects

Tailwind

At Cantilever, we use are moving to a utility-first css approach using Tailwind CSS, enabling us to build custom designs without leaving the HTML.

Abstract Components Wisely

While utility classes are powerful, abstraction into reusable components is necessary for commonly repeated patterns. Use utility classes to build these components but avoid tying them tightly to specific content or contexts. This approach keeps your components flexible and reusable across different parts of your application.

Embrace Composition

Utility-first CSS shines with composition. Combine utility classes to create complex UI elements without writing new CSS. For example, a button component can be composed of utility classes for padding, background color, text color, and hover states.

Optimize for Production

Utility-first CSS can lead to heavier HTML files due to the repeated use of utility classes. Use tools like PurgeCSS to remove unused CSS classes from your production builds, ensuring that your stylesheets remain lean and fast.

Legacy CSS Design Systems at Cantilever

Previously we developed our CSS based on an ITCSS architecture. Over time we have shifted our methodology and to a utility first approach. Some of our clients still use our BEM style approach for CSS which you fill find outlined here.

We used BEM syntax to write our classes. BEM allows us to clearly scope styles to the DOM elements which need them. The style leads to somewhat more wordy classes, and in some cases, code duplication, but we prefer the structure and predictability of it. BEM can be used with any CSS architecture, so do not confuse BEM with ITCSS – one is syntactical, the other is architectural.

We are typically used LESS as a preprocessor and compiling down to a single styles.css file. A typical structure looked like:

  • source
    • less
      • 01-settings: Global styling like resets
      • 02-tools: Re-usable tokens and variables, mixins, etc.
      • 03-generic: Site-wide styling, such as for the body or html element
      • 04-elements: Styles to apply to any HTML element of a given type, like `a` or `article`. Many basic styles of this type go in the reset though.
      • 05-objects: Styles associated with specific BEM-namespaced HTML object patterns which can be used many places within a page and also nested within other objects, components, or templates.
      • 06-components: Styles associated with patterns that cannot be encapsulated within other patterns, such as a Hero.
      • 07-templates: One-off styles associated with full page templates, like `home` or `404`.
      • 08-utilities: Overrides and accessibility utility classes