Skip to content

Instantly share code, notes, and snippets.

@necolas
Last active March 28, 2024 20:34
Show Gist options
  • Save necolas/1309546 to your computer and use it in GitHub Desktop.
Save necolas/1309546 to your computer and use it in GitHub Desktop.
Experimenting with component-based HTML/CSS naming and patterns

NOTE I now use the conventions detailed in the SUIT framework

Template Components

Used to provide structural templates.

Pattern

t-template-name
t-template-name--modifier-name
t-template-name__subcomponent-name--subcomponent-modifier-name

Examples

t-icon
t-icon--large

t-btn
t-btn--large

t-media
t-media__img
t-media__img--large
t-media__opt
t-media__body

State Components

Used to indicate the state of a component

Pattern

is-state-type

Examples

is-hidden
is-collapsed
is-expanded
is-selected

JavaScript Components

Used to provide JS-only hooks for a component. Can be used to provide a JS-enhanced UI or to abstract other JS behaviours.

Pattern

js-action-name

Examples

js-submit
js-action-save
js-ui-collapsible
js-ui-dropdown
js-ui-dropdown--control
js-ui-dropdown--menu
js-ui-carousel

About theming Components

Could reuse the Template Component naming convention, for example:

specific-name
specific-name--modifier-name
specific-name__subcomponent-name
specific-name__subcomponent-name--subcomponent-modifier-name

Or just let anything go.

<!--
What if we used more white-space around class values?
Does it make the code more readable and surface/separate the components
among the rest of the info in the HTML?
-->
<div class=" t-unit t-media ">
<div class=" t-media__img ">
<a href="#">
<img class=" product-img " src="http://example.com" alt="">
</a>
</div>
<form class=" t-media__opt js-action-rate ">
<button class=" product-rating " type="submit">
<div class=" product-rating__panel ">
<span class=" product-rating__points ">
5
</span>
<span class=" product-rating__label ">
upvotes
</span>
</div>
<strong class=" product-rating__action t-btn btn-normal ">
Upvote
</strong>
</button>
</form>
<div class=" t-media__body ">
<h2 class=" h2 ">
<a href="#">Product title</a>
</h2>
<p>[content]</p>
<ul class=" t-uilist--hz ">
<li><a class=" tag " href="#">tag name</a></li>
<li><a class=" tag " href="#">tag name</a></li>
<li><a class=" tag " href="#">tag name</a></li>
</ul>
</div>
</div>
@bjankord
Copy link

bjankord commented Mar 6, 2013

@asakurayoh Looking at the jsperf tests for querying class selectors vs. data attribute selectors, I lean towards keep JS hooks as classes. It would be nice if querying performance was the same or at least not as big of a diff between the two. It would be nice to keep JS hooks separate from CSS hooks in the HTML markup.

I've started to adopt this BEM like syntax as well and mixing it with my understanding of SMACSS.

.module {...}
.module--modifier {...}
.module__component {...}
.module__component--modifier {...}

I've seen Jonathan Snook talk about using a syntax like:

.module {...}
.module-submodule {...} /* Module Modifier */
.module--subcomponent{...}

.product-rating {...}
.product-rating-modifier {...}
.product-rating--label {...}

I like this naming convention as well, though I like the double dash for modifiers.

Another naming convention I've thought about similar to the one above looks like:

.module {...}
.module--modifier {...}
.module-component {...} /* Single dash instead of underscores */
.module-component--modifier {...} 

.product-rating {...}
.product-rating--modifier {...}
.product-rating-label {...}

The issue I see with this is it is hard to see the difference between modules and components when module names are made up of multiple words like product rating.

product-rating {...} /* Module */
product-rating-label /* Component with single dash. Harder to understand label is component of product rating. */
product-rating__label /* Component with double underscores. Easier to understand */

One way to get around this would be to use camelCase for module names and not use dashes in module names, only for modifiers (double) and components (single)

.productRating {...}
.productRating-label {...}
.productRating--modifier {...}

All of the naming conventions look odd at first. I think it is important to remind others the overall goal of a HTML class naming convention would be to add clarity for developers, I prefer the BEM like syntax the most, though it can take a while for other developers to understand the thinking behind it and go accustom to it .

I've put together a repo with a collection of common class naming patterns I've seen. CSS-Modules-Subcomponents-And-Modifiers-Collection

@suissa
Copy link

suissa commented Jun 10, 2013

@mindplay-dk
Copy link

Here's a pattern I've been experimenting with:

http://jsfiddle.net/mindplay/XmfBa/

I know the leading hyphen looks odd at first glance, but give it a chance - read through the description in the comments and review the example.

I'd love to get your feedback.

@mlarcher
Copy link

We've been playing around with the BEM syntax since late 2012, and we arrived at the following naming convention:

.componentName {...}
.componentName_Element {...}
.componentName_Element.componentName_Element--modifier {...}

  • camelCase is used for names that a single word can't depict (ex: displaySwitcher)
  • A single underscore is used to separate Blocks and Elements (Perhaps we'll get back to __ if we realize that some coders in our team use the _ wrongfully, but for now _ seems enough)
  • We separate modifiers with two dashes to make it stick out and make its role obvious. Also text editors will usually stop the selection on the hyphen when double-clicking, so it makes sense to use it there and not in any other separator.
  • We prefix all modifier classes with the non modified class to ensure the specificity will always be a bit higher, as we've had issues with that (due to modernizr classes iirc).

This convention along with the use of Sass and a semantical file system organisation has boosted our productivity and made maintenance a breathe.

@TheDutchCoder
Copy link

I love the BEM approach in cases where there's a strict hierarchy, but I find it very verbose when working with more global components.

For example:

.header {}
.article .header {}

is much more flexible and reusable than:

.article__header {}

which is very specific to that block.

I use BEM mainly for widgets and cases where I know I really need the namespace, but doing everything the BEM way kind of defeats the Cascading part of CSS in my opinion.

I totally love the states and js hooks though, I think that's great practice as it instantly shows what the component is for.

@rafaelrinaldi
Copy link

Let's say I have a menu and within this menu I have the list of items. What's the correct naming then?

Menu and menu list should be:

.menu {}
.menu--list {}

But what about the items? Should be .menu--list--item or .menu__list--item?

@mykz
Copy link

mykz commented Oct 24, 2013

rafaelrinaldi

.menu {}
.menu--list {}

The item naming would then fall like this if you needed to modify the menu item

.menu__item--list {}

You could call the modifier what you wanted but it makes sense to keep the modifier name the same as the parent modifier. Then you can couple the new menu item modifier with the parent modifier.

@rafaelrinaldi
Copy link

Gotcha! Thanks @mykz.

@Zeokat
Copy link

Zeokat commented Mar 9, 2014

Zeokat interesting code, i have to adjust it a little. Thanks.

@viT-1
Copy link

viT-1 commented Aug 10, 2016

Another variant of writing css-rules is using AMCSS.
For example: http://codepen.io/viT-1/pen/VjXybd

Copy link

ghost commented Jan 1, 2017

Hi nicolas,

What is the different between a Template Components and theming Component? I can see some of your classes start with a t and some don't. I just want to know the reason and the logic please. Thanks

@ldexterldesign
Copy link

ldexterldesign commented Feb 23, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment