How to use Hacss within your code

Hacss uses a style rule syntax resembling CSS embedded within HTML classes. For the most part, your existing CSS knowledge still applies. However, the use of statically-analyzed HTML classes introduces some minor but notable constraints:

  1. Whitespace is strictly forbidden. Since some CSS values (e.g. box shadows) require whitespace, you can use a pair of underscores (__) in place of a space character.

  2. Dynamically-generated class names are not supported because Hacss generates the style sheet at build time. In practice, this is not much of a limitation, particularly if you make good use of selectors, described below.

  3. Hacss supports a large subset, but not all, of CSS. This guide will help you to understand which features are supported.


A rule can include:

  • declarations only, e.g. background:red;color:white;
  • a selector, e.g. .err{background:red;color:white}
  • an at-scope, e.g. @sm{padding:0}
  • a combination of a selector and an at-scope, e.g. @sm{.err{width:100%}}

Note that declarations are always separated by semicolons. A rule consisting only of declarations is also terminated by a semicolon. However, for a rule that includes a selector and/or at-scope, the trailing semicolon must be omitted.


Selectors are surprisingly useful within inline styles because they allow you to activate various style rules conditionally, similar to what might otherwise be accomplished with JavaScript or an external style sheet. They can also be used to create pseudo-elements, which can sometimes optimize your markup for accessibility or performance.

Selectors can include:

  • a context
  • a class list
  • a pseudo-element

Each of these selector components is optional.


A context describes the element's relationship to another element in the DOM tree. It consists of a class list (described below) followed by one of the following combinators:

  • Ancestor: _
  • Parent: >
  • Adjacent sibling: +
  • General sibling: ~

Class List

A class list consists of a series of named classes followed by a series of pseudo-classes.

Named Class

A named class consists of a dot followed by lowercase letters and hyphens. Examples of named classes include:

  • .error
  • .focus-group

A pseudo-class consists of a colon generally followed by a series of lowercase letters and hyphens. For example:

  • :hover
  • :focus-within

Hacss also supports a few more advanced pseudo-classes:

  • :not(<classes>), where <classes> is a class list
  • :nth-child(<expr>), where <expr> is a formula like 2n+1, even, odd, etc.
  • :lang(<code>), where <code> is a standard language code like en, en-US, etc.

Named classes and pseudo-classes are each optional components of a class list.


A pseudo-element consists of ::, followed by lowercase letters and hyphens. Examples of pseudo-elements include:

  • ::after
  • ::placeholder
  • ::-webkit-slider-thumb

Selector rule examples

  • .err{color:red}
  • :nth-child(odd){background:$gray50}
  • .err_:disabled{color:pink}
  • :checked~{text-decoration:line-through}
  • ::placeholder{color:$gray50}


An at-scopes consists of an at sign followed by lowercase letters and hyphens. You can use them for media queries and feature queries. Each at-scope must be added to your Hacss configuration. Note that the at sign is omitted within configuration.


A variable consists of a dollar sign followed by lowercase letters and hyphens. You can use variables as CSS values or even interpolate them into other values. For example:

  • color:$red500;
  • left:calc(50%+#{$len4});

Variables must be included in your Hacss configuration. Note that the dollar sign is omitted wthin configuration.


Hacss places at-scope rules at the end of the generated style sheet; but, beyond that, it offers no rule ordering guarantees. You should use specificity instead to prioritize rules.

Sometimes two rules have the same specificity by default, and it is necessary to increase the specificity of one of them. For example, :hover{color:blue} and :active{color:red} have the same specificity, but you might want the red color to be applied when both selectors match.

To increase the specificity of any rule, simply attach an exclamation point to the end, e.g. :active{color:red}! or display:none;!

You can also increase the specificity as needed by adding more exclamation points, e.g. display:none;!!

The exclamation point may remind you a bit of the !important exception, generally regarded as a bad practice. Fortunately, Hacss' notion of priority incrementally increases specificity rather than relying on the brute force of an !important exception.