Skip to content

PIE CSS Naming Scheme

Ashley Watson-Nolan edited this page Jul 23, 2024 · 2 revisions

Naming in CSS can be tricky but it is worth getting right.

To ensure our naming is consistent across PIE components we use a naming scheme based on the SUIT methodology.

Using a naming scheme helps clarify the intent of the author as well as defining the relationships between classes. Good naming provides better context not just in the styles, but also when viewing the HTML markup, and makes it easier to distinguish which classes are being used for state, layout or as a utility helper.

Our Naming Scheme

/* We use a number of class prefixes to categorise our CSS classnames */

/*
 *  Objects are prefixed: .o-
 *  An object is a type of component that can be implicitly linked to an HTML tag.
 *  For example, the base styling for buttons or form elements.
 */
.o-btn {
    ...
}

/*
 *  Components are prefixed: .c-
 *  A component is basically anything that isn’t classified as an object.
 *  For example a modal, notification or star ratings component.
 */
.c-rating {
    ...
}

/*
 *  Utility or Trump classes are prefixed: .u-
 *  These are generic, reusable classes that could potentially be used across many components.
 *  For example, for reusable responsive classes
 */
.u-showAboveMid {
    ...
}

/*
 *  Layout classes prefixed: .l-
 *  These are classes specific to global site layout.
 *  It's rare that these will be used in components themselves.
 */
.l-container {
    ...
}

/* Descriptors in a classname use camel-case if more than one word: e.g. myComponentName */
.c-myComponentName {
    ...
}

/* ========= */

/* Child elements are indicated using a single hyphen: - */
.o-form-controlGroup {
    ...
}

/* ========= */

/* Modifier classes are indicated with a double hyphen: -- */
.o-btn--primary {
    ...
}

Modifier Classes

Modifier classes are used to show when an object or component class is being modified slightly. Think of them as helping to define one or more extensions to your component.

A typical example is when defining buttons. Usually, all buttons share common styles that are defined using the o-btn class. However, buttons may have various design treatments – some may have a different background colour and font-size, others may have different border styles. In PIE for instance, we have primary, secondary, ghost and destructive variations (among others).

To define these different button styles we can use modifiers, allowing us to use the base o-btn class alongside a modifier that will extend those base styles.

.o-btn {
    font-size: 16px;
    color: #333;
}

.o-btn--primary {
    background-color: Gold;
}

.o-btn--secondary {
    background-color: LightGrey;
}
<button class="o-btn o-btn--primary">My Button</button>
<button class="o-btn o-btn--secondary">My Other Button</button>

State Classes

We use the is- or has- prefixes to indicate state that changes via JavaScript.

A state class is usually needed to show an action has been performed by the user, but could also come from an API response or similar system level event.

/* Element state: .is- or .has- */
.is-active {
    ...
}