A summarized guide for organizing CSS, from class names to file structure
Note, this guide is currently still a draft
This is a style guide promoting consistent, maintainable styling in web development.
I incorporated and summarized ideas that most inspired me from BEM, Harry Roberts, and other sources.
There is nothing to download; the scss/ directory contains some examples files with empty classes file structure example below.
Preliminary notes:
- Only style with classes, not ids
- Limit (or totally avoid) use of CSS combinators
- Aim for maximum abstraction and reusability
We'll be using BEM-style class names (see: http://getbem.com/naming/), but changing the double underscore __ to a more relaxed single dash -.
Component are divided into three parts, blocks, elements, and modifiers. This creates a connection between classes which greatly enhances clarity. No longer must one wonder if two classes are related, or if one depends on another; it's all in the name.
.block-element--modifier
- Blocks are a top-level class which hold meaning on their own
- Blocks begin a context in which child elements can reside
Examples: menu, modal
- Elements are a subcomponent of a block that have no meaning outside of the block
Examples: menu-item, modal-header
- An suffix to a block or element signifying a modification to the base class, such as a different color or size
- Can be thought of as a
flag
Examples: menu--large, menu-header--blue
Here's an example navbar, showing BEM class names (modified from csswizardry):
/* The top-level 'block' of a component, in this example, a navbar */
.navbar {}
/* An 'element' that is part of the larger block */
.navbar-title {}
/* Another 'element' that is part of the navbar */
.navbar-item {}
/* A 'modifier' of a 'block'; a version of the navbar that is blue */
.navbar--blue {}
/* A 'modifier' of an 'element' */
.navbar-item--new {}
Putting it together:
<div class="navbar navbar--blue">
<div class="navbar-title"></div>
<div class="navbar-item"></div>
<div class="navbar-item navbar-item--new"></div>
</div>
In addition to naming, we'll be adding namespace prefixes to further clarify the role of a specific class.
Using namespaces enhances readability in HTML and facilitates organization into files. All classes will have a namespace prefix, except distinct components. A class without a namespace is presumed to be a distinct component.
We'll use six distinct namespaces, and they're all pretty straightforward:
l-for global layout utilitiesu-for specific purpose utilitiest-for typography related stylingis-andhas-to reflect temporary statesjs-for javascript hooksa-for abstract objects- no prefix for distinct components
- Prefix layout classes with
l- - Layout classes are the organizational building blocks of the page
- Layout classes do not logically have descendent elements or modifiers
Examples: l-grid, l-row
- Prefix utility classes with
u- - Utilities have a specific role, such as centering text or adding padding
- They are not tied to any individual piece of UI and are often atomic
- Utility classes do not logically have descendent elements or modifiers
Examples: u-zindex-2, u-display-none, u-text-center
- Prefix typography related classes with
t- - These include font sizes, families, weights, and styles
- Do not change padding or margins in typography classes
- Typography classes are similar to utilities in that they have are often atomic and have a single, specific effect, while not tied to a context
Examples: t-lg, t-roboto, t-italic
- Prefix state classes with
is-orhas- - State classes do not logically have descendent elements or modifiers
Examples: is-hidden, has-dropdown
- Prefix classes that are used as javascript hooks with with
js- - Do not style these; they should not appear in CSS files
- Prefix abstracts with
a- - Abstracts are general and highly reusable
- Abstracts may be used in any number of unrelated contexts
- Abstracts should not change any structure outside itself (e.g.
margin,position,display) - Abstracts should not contain components, only other abstracts and sub-elements
- Abstracts are a subset of components that aren't tied to a specific piece of UI
Examples: a-button, a-media, a-list, a-card, a-menu
- Components are distinct, specifically-purposed part of the UI
- Components need no prefix
- Components start a context
- Components can contain other components and objects
- Components are basically any of your custom elements!
Examples: chatbox, sidebar, staff-list
Now let's reflect these additions in our navbar example, and add a couple more elements: ``html
We'll separate our scss partials (or css files) into five directories, which import into a master style.scss file to be compiled for distribution:
base/ contains resets/normalize, and HTML element modifying code
layout/ contains a partial for high-level, global layout classes
utilities/ contains a partial for types of non-layout utilities, including typography
abstracts/ contains a partial for each abstract, with relevant state classes, sub-elements, and modifiers
components/ contains a partial for all components, with relevant state classes, sub-elements, and modifiers
Here's an example directory structure:
scss/
├─ abstracts/
│ ├─ _button.scss
│ └─ _media.scss
├─ base/
│ ├─ _normalize.scss
│ ├─ _root.scss
├─ components/
│ ├─ _sidebar.scss
│ └─ _footer.scss
├─ layout/
│ ├─ _grid.scss
│ └─ _container.scss
├─ utilities/
│ ├─ _spacing.scss
│ └─ _typography.scss
└─ style.scss
Here _root.scss is the only location in which HTML elements themselves are styled. You don't have to use a specific _root.scss file, but all styled HTML elements should be in base/ only.
This is useful for a few resets, or common actions like removing margins from headings or something like
html {
font-size: 62.5%
}
style.scss is composed entirely of imports in the following order:
base/, layout/, utilities/, abstracts/, components/
http://nicolasgallagher.com/about-html-semantics-front-end-architecture/
https://www.lullabot.com/articles/bem-atomic-design-a-css-architecture-worth-loving
https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/
http://www.jamesturneronline.net/blog/bemit-naming-convention.html