LESS Coding Guidelines

Fruitcake uses coding guidelines to define its LESS code. By using a set of guidelines we aim to produce more effective, clear and consistent LESS code.

Table of contents

General

Performance and specificity

Although in the name (cascading style sheets) cascading can introduce unnecessary performance overhead for applying styles. Take the following example:

ul.user-list li span a:hover { color: red; }

Styles are resolved during the renderer's layout pass. The selectors are resolved right to left, exiting when it has been detected the selector does not match. Therefore, in this example every a tag has to be inspected to see if it resides inside a span and a list. As you can imagine this requires a lot of DOM walking and and for large documents can cause a significant increase in the layout time. For further reading checkout: https://developers.google.com/speed/docs/best-practices/rendering#UseEfficientCSSSelectors

Styling a single class is by far the most efficient method, but not always feasible, e.g. text entered in a CMS will not contain classes for each element. Using the > child selector drastically reduces the amount of DOM walking necessary, as only direct parents of the elements have to be checked. Styling of an element should be defined in the most efficient way, e.g.:

If we want to style a certain a element, we assign a class directly to the a element wherever possible, and style the class.

.tweet-link {
  color: @color-redLight;
}

If it is not possible to assign a class directly to the a element, we define the styling by using the direct child selector.

.tweet > a {
  color: @color-redLight;
}

Only if the above options are impossible to achieve, the a element is styled using a general parent.

.footer a {
  color: @color-redLight;
}

IDs and Classes

Never ever apply styling to an element's ID, ever. It fucks up specificity big time, so don't.

Reusability

Styles should be reusable as much as possible, so try to keep things general. Try to use general components instead of content specific styles, see Components.

Right:
.jumbotron {
  …
}
Wrong:
.photoalbum-page-header-background {
  …
}

.portfolio-page-header-background {
  …
}

If two elements have largely the same styling, use a base style, and extend upon that base style. Again, see Components.

Right:
.page-title {
  font-size: @fontSize-base;
  color: @color-redBright;
  line-height: @lineHeight-base;
}	

.page-title--portfolio {
  margin-bottom: 2rem;
}
Wrong:
.photoAlbum-page-title {
  font-size: @fontSize-base;
  color: @color-redBright;
  line-height: @lineHeight-base;
}	

.portfolio-main-header {
  font-size: @fontSize-base;
  color: @color-redBright;
  line-height: @lineHeight-base;
  margin-bottom: 2rem;
}

JavaScript

syntax: js-<targetName>

JavaScript-specific classes reduce the risk that changing the structure or theme of components will inadvertently affect any required JavaScript behaviour and complex functionality. It is not neccesarry to use them in every case, just think of them as a tool in your utility belt. If you are creating a class, which you dont intend to use for styling, but instead only as a selector in JavaScript, you should probably be adding the js- prefix. In practice this looks like this:

<a href="/login" class="btn btn-primary js-login"></a>

Again, JavaScript-specific classes should not, under any circumstances, be styled.

Components

Syntax: <componentName>[--modifierName|-descendantName]

Component driven development offers several benefits when reading and writing HTML and CSS:

  • It helps to distinguish between the classes for the root of the component, descendant elements, and modifications.
  • It keeps the specificity of selectors low.
  • It helps to decouple presentation semantics from document semantics.

You can think of components as custom elements that enclose specific semantics, styling, and behaviour.

ComponentName

The component's name must be written in camel case.

.myComponent { /* … */ }
<article class="myComponent">
  …
</article>

componentName--modifierName

A component modifier is a class that modifies the presentation of the base component in some form. Modifier names must be written in camel case and be separated from the component name by two hyphens. The class should be included in the HTML in addition to the base component class.

/* Core button */
.btn { /* … */ }
/* Default button style */
.btn--default { /* … */ }
<button class="btn btn--primary">…</button>

componentName-descendantName

A component descendant is a class that is attached to a descendant node of a component. It's responsible for applying presentation directly to the descendant on behalf of a particular component. Descendant names must be written in camel case.

<article class="tweet">
  <header class="tweet-header">
    <img class="tweet-avatar" src="{$src}" alt="{$alt}">
    …
  </header>
  <div class="tweet-body">
    …
  </div>
</article>

componentName.is-stateOfComponent

Use is-stateName for state-based modifications of components. The state name must be Camel case. Never style these classes directly; they should always be used as an adjoining class.

JS can add/remove these classes. This means that the same state names can be used in multiple contexts, but every component must define its own styles for the state (as they are scoped to the component).

.tweet { /* … */ }
.tweet.is-expanded { /* … */ }
<article class="tweet is-expanded">
  …
</article>

Variables

Syntax: <property>-<value>[--componentName]

Variable names in our CSS are also strictly structured. This syntax provides strong associations between property, use, and component.

The following variable defintion is a color property, with the value grayLight, for use with the highlightMenu component.

@color-grayLight--highlightMenu: rgb(51, 51, 50);

Colors

When implementing feature styles, you should aim to only use colors provided by variables.less. I.e. colors that belong to the website's brand, or colors that occur multiple times throughout the website's LESS code, should be defined in variables.less.

If a color belongs to a company's or website's brand, the property should be named accordingly, .e.g.:

@fruitcake-greenLight: rgb(178, 188, 53);

z-index

If you make use of z-indeces, define a scale in variables.less. The scale should range @zIndex-1 - @zIndex-9. Nothing should be higher then @zIndex-9.

Font Weight

With the additional support of web fonts font-weight plays a more important role than it once did. Different font weights will render typefaces specifically created for that weight, unlike the old days where bold could be just an algorithm to fatten a typeface. Always use the numerical value of font-weight to enable the best representation of a typeface.

Refer to variables.less to set the base type size, letter-spacing, and line height. Raw sizes, spaces, and line heights should be avoided outside of variables.less.

To avoid scattering of type sizes throughout the code, define base font sizes in variables.less, e.g.:

@fontSize-micro
@fontSize-smallest
@fontSize-smaller
@fontSize-small
@fontSize-base
@fontSize-large
@fontSize-larger
@fontSize-largest
@fontSize-jumbo

See Mozilla Developer Network — font-weight for further reading.

Line Height

Variables.less also provides a base setting for line height, split into body text and header text. Should you need a more extensive set of line heights, define a scale in variabless.less, e.g.:

@lineHeight-tightest
@lineHeight-tighter
@lineHeight-tight
@lineHeight-baseSans
@lineHeight-base
@lineHeight-loose
@lineHeight-looser

Alternatively, when using line height to vertically center a single line of text, be sure to set the line height to the height of the container - 1.

.btn {
  height: 50px;
  line-height: 49px;
}

Polyfills

A wide variety of mixins is provided in the Bootstrap framework to generate polyfills for browser prefixed properties. See /mixins/vendor-prefixes.less for all mixins. Use these mixins wherever possible.

An example of a box sizing mixin:

.box-sizing(@boxmodel) {
  -webkit-box-sizing: @boxmodel;
     -moz-box-sizing: @boxmodel;
          box-sizing: @boxmodel;
}

Formatting

The following are some high level page formatting style rules.

Spacing

CSS rules should be comma seperated but live on new lines:

Right:

.content,
.content-edit {
  …
}

Wrong:

.content, .content-edit {
  …
}

CSS blocks should be seperated by a single new line. not two. not 0.

Right:

.content {
  …
}

.content-edit {
  …
}

Wrong:

.content {
  …
}


.content-edit {
  …
}

Quotes

Quotes are optional in CSS and LESS. We use double quotes as it is visually clearer that the string is not a selector or a style property.

Right:

background-image: url("/img/you.jpg");
font-family: "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial;

Wrong:

background-image: url(/img/you.jpg);
font-family: Helvetica Neue Light, Helvetica Neue, Helvetica, Arial;