Attribute Modules for CSS

Attribute Modules (AM) is a technique for using HTML attributes and their values rather than classes for styling elements. In doing so, each attribute effectively declares a separate namespace for encapsulating style information, resulting in more readable and maintainable HTML & CSS.

It's not a framework or a library, it's a style that better describes the components you're building. For an introduction to how AM was developed, see the original blog post by Glen Maddern. The specification itself is available on GitHub.

Example: Bootstrap Buttons

Buttons are one of the strongest use-cases for AM. Here we've converted some of Bootstrap's button markup as an example.

<!-- Large primary button -->
<a class="btn btn-primary btn-lg">Large primary button</a>
<a am-Button="primary large">Large primary button</a>

<!-- Default button -->
<a class="btn btn-default">Default button</a>
<a am-Button>Default button</a>

<!-- Small info button -->
<a class="btn btn-info btn-sm">Small info button</a>
<a am-Button="info small">Small info button</a>

<!-- Extra-small danger button -->
<a class="btn btn-danger btn-xs">Extra-small danger button</a>
<a am-Button="danger extra-small">Extra-small danger button</a>

The original Bootstrap markup is heavily convention-based: all buttons require a btn class and a specific button class prefixed by btn-. It results in cluttered, repetitive markup.

The AM version, in contrast, uses the attribute am-Button as an identifier, and allows straightforward, natural, additive modifiers, e.g. large, primary, etc.

The CSS changes are quite straightforward:

.btn [am-Button] { /* Default button styles */ }
.btn-primary [am-Button~="primary"] { /* Primary colours */ }
.btn-large [am-Button~="large"] { /* Large sizing */ }

Example: Flexbox Grid

Using a grid system is commonplace and Flexbox Grid is one we're particularly fond of. Here we've converted some example markup into an AM style.

<div class="row reverse" am-Grid-Row="reverse">
  <div class="column-12--hand column-8--lap" am-Grid-Col="12 lap:8"
    <div class="box" am-Demo="box">Responsive</div>

The original markup shares some problems with all class-based grid systems. Because grid classes are used so frequently, it uses relatively bare css classes like row & reverse, but because columns need to be responsive, it eschews a global col class and instead defines col-breakpoint-number classes.

The AM markup, on the other hand, defines am-Grid-Row and am-Grid-Column modules, and since each of those define a namespace we can be free to use values of our choosing. These values can make use of a wider range of characters than is convenient with classes, so we can use a breakpoint:number syntax, which is easier to understand at a glance. We can also adopt a mobile-first apporach by omitting the hand breakpoint.

Example: Traits

While AM can be used as a drop-in for BEM-style class naming, you can also consider a module defining a more general namespace for grouping related styles. Similar to utility classes in Suit CSS, these can be thought of as reusable style traits, that can be applied on or within components.

<div class="u-posAbsoluteCenter" am-position="absolute center">
  <div class="u-textTruncate u-textCenter" am-text="truncate center">
    Very centered text.

Here, we're able to make use of the fact that values for am-position and am-text operate in different namespaces, so we can use the value center in both places without worrying about naming clashes.

Built with AM

Call for feedback

We'd love to hear suggestions for inclusions to the AM specification, by adding an issue to our tracker or contributing to an existing discussion. If you create an AM-style CSS library or framework, please let us know.