메뉴 보이기
Profile
이온디

2018.12.01

CSS

What’s in a name? A CSS naming convention overview

조회 수 32 추천 수 0

CSS, or Cascading Style Sheets, are used to describe the presentation of an HTML document. We recently organized a workshop where the participants wanted advice on CSS naming conventions. We’ve prepared the summary below, which hopefully you’ll find useful.

The main idea behind CSS naming conventions is to make the CSS selectors as informative and readable as possible. This greatly helps in development, debugging and other issues that can come when creating HTML based layouts. The most popular naming conventions are presented below:

SMACSS

SMACSS stands for “Scalable and Modular Architecture for CSS”. In SMACSS, the selectors are divided into five categories:

  1. Base
  2. Layout
  3. Module
  4. State
  5. Theme

Base

Basic selectors applied to elements, for example:

html, body, form { margin: 0; padding: 0; }

Layout

A page is divided into several sections, which comprise one or more modules. Style layouts are divided into major and minor. Main section names like header and footer are named using IDs. Recurring items on the page are named using classes, usually prefixed with “l-” or “layout-”.

#header, #article, #footer {
  width: 960px;
  margin: auto;
}
.l-grid {
  margin: 0;
  padding: 0;
  list-style-type: none;
}

Modules

Modules are reusable parts of the design. For example, sidebar sections, lists of products, etc. :

.sidebar {}
.callout {}

Elements related to a module use its name as a prefix:

.sidebar-menu {}

State

State classes describe how modules or section pages will appear in a particular state. The selectors are written with the state prefix “is-”:

.sidebar {}
.sidebar.is-collapsed {}

Theme

Themes define how a particular module might look. However, most projects do not use themes. They can also define colors, images and other external characteristics:

//module-name.css
.mod {
  border: 1px solid;
}
//theme.css
.mod {
  border-color: blue;
}

Meaningful CSS

The main emphasis is on new HTML5 elements, their semantics and avoiding redundancy. For example:

<table class=”table”> 

or

<form class=”form”> 

are redundant. In both cases, we already know that this is a table and a form.

<main class=“main”> — It does not make sense to specify class “main”, given that the page can only contain one element <main>.

In HTML5, a role attribute has been added, which allows you to specify the purpose of the element on the page. Examples of values are: banner, contentinfo, definition, navigation, search etc.

Button styles can be defined through the following selectors:

button,
[role=button] {
  ...
}

Other examples, using Bootstrap classes as a starting point:

.form is replaced by form — most forms usually look the same online. Additional classes can be used to separate them.

.form-group can be replaced with form > p or fieldset > p, since W3C recommends using paragraphs for form elements.

.text-input can be replaced with [type=text] — since we already know that it is a text input field.

.btn .btn-primary can be replaced with [type=submit].

An example of the resulting form:

<form method="POST" action=".">
  <p>
    <label for="id-name-field"> What’s Your Name</label>
    <input type="text" name="name-field" id="id-name-field">
  </p>
  <p>
    <button type="submit"> Enter </button>
  </p>
</form>

Using such patterns eliminates redundant information and makes code much cleaner.

Functional CSS

The main focus is on atomicity and reuse of selectors.

Naming Rules

Objects — unrelated to content classes that define a structure of the document (grid, containers, etc.). Identified by the prefix “o-”.

Components — classes that depend on content, but do not define the visual style. Components are usually buttons or custom form elements. Identified by the prefix “c-”.

Utilities — widely reusable classes that do one thing. Responsible for margins, text alignment, positioning, etc. They are identified by the “u-” prefix.

Visual classes — define visual styles of a component, such as colors, fonts, etc. They are prefixed with “v-”.

Main Principles

  • Simplicity — simple styles are easier to remember and use.
  • Reusable classes — it means that the number of rules in classes is minimal, because more rules leads to poor re-usability.
  • Classes have no side effects — the same class always performs the same role and does not change anything it was not designed for.

Example:

// CSS
.questionCard {
  position: relative;
  margin-top: $ scale1;
  padding: $ scale2;
  background-color: #fff;
  box-shadow: $ boxShadow-2;
}
// HTML
<div class="questionCard">...</ div>

Turns into:

// CSS
.u-relative {
  position: relative;
}
.u-mt1 {
  margin-top: $ scale1;
}
.u-p2 {
  padding: $ scale2;
}
.v-bg-white {
  background-color: #fff;
}
.b-bs2 {
  box-shadow: $ boxShadow-2;
}
// HTML
<div class="u-relative u-mt1 u-p2 v-bg-white b-bs2">...</div>

BEM

BEM (Block, Element, Modifier) — a component-based approach to web development. Its fundamentals include separation of an interface into separate components. It allows you to develop interfaces of any complexity quickly and easily and reuse existing code, avoiding copy pasting.

Block

Functionally independent, reusable component in a page. In HTML, blocks are represented using the “class” attribute.

  • A block’s name describes its meaning (“what is it?” — “menu”, “button”), not visual state (“does does it look like?” — “red”, “big”). Here’s an example:
<!-- Good. Semantically meaningful unit `error. -->
<div class="error">...</div>
<!-- Bad. Describes appearance. -->
<div class="red-text">...</div>
  • A block must not have an effect on its environment, i.e you should not set any external geometry for units (margins, border and other properties that affect its dimensions) and positioning.
  • In BEM, it is not recommended to use tags or id based selectors.
  • Blocks can be nested.
  • Any nested structure is allowed.

Element

An element is a part of a block that cannot be separated from it.

  • An element’s name describes its meaning ( “what is it?” — “Item”, “the text”: text), not visual state ( “what does it look like?” — “Red”, “big”).
  • The structure of the full name of an element is: block-name__element-name. The element’s name is separated from the block’s name with two underscores: “__”.
<!-- block 'search-form' -->
<form class="search-form">
 <!-- input element of block 'search-form' -->
 <input class="search-form__input">
 <!-- button element of block 'search-form' -->
 <button class="search-form__button">Search</button>
</form>

When should I create a block and when an element?

  1. If the code can be reused and doesn’t depend on the implementation of other components on the page, it should be a block.
  2. If the code cannot be used independently without a parent (block), you should probably create an element.

The exception is elements that, in order to simplify development, require separation into smaller parts, or sub-elements. The BEM methodology does not allow for creation of elements with elements. In this case, instead one has to create a utility block.

Modifier

Modifiers determine the appearance, state or behavior of a block or element.

  • A modifier’s name describes the appearance (“what size?”, “what theme?”, etc. — “size”: size_s, «theme»: theme_islands), state (‘how different from the rest? “-” off “: disabled, “focused»: focused) and behavior (“how should it behave?”, “how should it interact with users?” — “direction”: directions_left-top).
  • A modifier’s name is separated from the block’s name by one underscore: “_”.

Types of Modifiers

Boolean

  • Used when the presence or absence, and not the value, of a modifier is important. For example: “off”: disabled. It is agreed that the presence of a boolean modifier is equivalent to its value being set to true.
  • The structure of the full name of a boolean modifier follows the following convention:
block-name_modifier-name
block-name__element-name_modifier-name

Here’s a full example:

<!-- Block 'search-form' has a boolean modifier 'focused' -->
<form class="search-form search-form_focused">
  <input class = "search-form__input">
  <!--Element `button` a boolean modifier `Disabled` -->
  <button class="search-form__button search-form__button_disabled">Search</button>
</form>

Key-Value

Used when a modifier’s value is important. For example, “menu with theme islands»: menu_theme_islands. The structure of the full name of a key-value modifier follows the following convention:

unit-name_modifier-name_modifier-value
unit-name__element-name_modifier-name_modifier-value

Full example:

<!-- Block `search-form` is a modifier with` theme` value `islands` -->
<form class="search-form search-form_theme_islands">
  <input class="search-form__input">
  <!-- Element `button` is a modifier with` size` value `m` -->
  <button class="search-form__button search-form__button_size_m">Search</button>
</form>
<!-- It is not possible to simultaneously use two identical modifiers with different values -->
<form class="search-form search-form_theme_islands search-form_theme_lite">
  <input class="search-form__input">
  <button class="search-form__button search-form__button_size_s">Searh</button>
</form>

File Structure

The CSS naming conventions used in BEM can also be applied to your project’s directory and file structure .

Blocks, elements and modifiers are split into separate files, allowing us to include them only when needed. The key points are:

  • One block— one directory.
  • Block names correspond to their directores. For example, a “header” block — directory “/header”, “menu” block — directory “/menu”. The implementation of the blocks is split into separate files, for example: header.css and header.js.
  • A block directory is the root directory for all sub-directories of included elements and modifiers.
  • An element’s directory name starts with double underscores: “__”. For example: “header/__logo/” or“menu/__item/”. A modifier’s directory name begins with a single underscore. For example, “header/_fixed/” or “menu/_theme_islands/”.
  • The Implementation of modifiers and elements is split into separate files. For example: header__input.js and header_theme_islands.css.

Namespaces in CSS

It’s also worth mentioning CSS Namespaces. Namespace can be added to all of the above conventions.

  • 0- — objects
  • c- — components, finished UI elements
  • u- — utilities
  • t- — themes
  • s- — scopes. Just like themes, but deal less with visuals.
  • is-, has- — state of the elements
  • _ — for hacks and workarounds.
  • js- — JavaScript related classes
  • qa- — classes that are used for quality assurance and tests

Summary

To summarize: while interesting from an educational point of view, Meaningful CSS and Functional CSS seem a little awkward to use in practice. While Meaningful CSS requires us to change our HTML and makes it tricky to customize individual components, Functional CSS results in a very long and hard to decipher values for “class” attributes.

SMACCS gives us a solid pragmatic foundation for naming, but doesn’t offer much in the way for naming conventions of classes inside components (or modules). BEM does take care of this, but seems a bit verbose and heavy. As such, SMACCS is probably a good fit for smaller projects, while BEM is ideally suited for larger codebases.

It’s also worth noting that all front end frameworks now tend to encourage the use of components and offer different means of co-locating the styles with the component HTML and logic. This approach eliminates a common problem of having left over, unused CSS selectors. For example in React, one can inline styles defined in JS:

const divStyle = { 
  color: 'blue', 
  backgroundImage: 'url(' + imgUrl + ')', 
}; 
function HelloWorldComponent() { 
  return <div style={divStyle}>Hello World!</div>; 
}

In Vue.js on the other hand, the style and code are separated and scoped:

<style scoped> 
.example { color: red; }
</style>
<template> 
  <div class="example">hi</div> 
</template>

The scoping means that you can use the same class name in different components, since the class names are transformed during the build process. This is similar to style encapsulation in Web Components. So, if you end up using these frameworks, then the CSS naming conventions in use can be drastically simplified.

Would you like to learn more about CSS in general, naming conventions in particular or a frontend framework of your choiceGet in touch with us! We would be happy to run a workshop for your team or offer a free consultation.

Profile
7
Lv
이온디

이온디 홈페이지는 간결하며,

 손쉽게 수정할 수 있습니다.

0개의 댓글

에디터
번호 제목 글쓴이 날짜 조회 수
공지 [사이트 전반] CSS 및 이미지 네이밍에 관심있으신 분은 같이 참여해주세요. :) 이온디 2009.01.22 8330
13 [CSS] Get BEM profile 이온디 2018.12.01 15
[CSS] What’s in a name? A CSS naming convention overview profile 이온디 2018.12.01 32
11 [CSS] #tnb (Top Navigation Bar) 1 profile 이온디 2015.04.27 615
10 [CSS] What Makes For a Semantic Class Name? profile 이온디 2013.03.01 3795
9 [CSS] 레이아웃 네이밍 가이드 6 profile 이온디 2012.01.19 5890
8 [사이트 전반] HTML 마크업 설계 템플릿(한혜진) 이온디 2010.11.03 7574
7 SideNavigationBar (x) 이온디 2009.02.21 5479
6 [CSS] NHN Naming Guidelines (추천) profile 이온디 2009.01.20 6279
5 NHN UI(html, css) 하드코딩 기본룰 이온디 2009.01.20 6921
4 css 네이밍 규칙 7 이온디 2009.01.20 11794
3 [CSS] 모든 디자이너가 해야할 9가지 CSS 원칙 (추천) profile 이온디 2009.01.19 6863
2 CSS 네이밍 이온디 2009.01.14 5610
1 웹 개발자를 위한 네이밍 룰(Naming Rule) 가이드 (최현진, 2002년) 이온디 2003.11.14 9391