An open API service indexing awesome lists of open source software.

https://github.com/dsheiko/pcss

Guidelines for writing scalable and maintainable style-sheets
https://github.com/dsheiko/pcss

bem css naming-conventions styleguide

Last synced: 6 months ago
JSON representation

Guidelines for writing scalable and maintainable style-sheets

Awesome Lists containing this project

README

          

PCSS
=====
ver. 1.2.2

**Pragmatic CSS** is a collection of guidelines for writing scalable and maintainable style-sheets. PCSS divides the
whole UI into **portable** and **reusable** components. Every component is described in a separate CSS (SASS/LESS/etc) module.
PCSS's naming convention makes it easier to locate a module corresponding to a problem and encourages developer
on producing optimized object-oriented CSS.

PCSS is standing on the shoulders of giants. It borrows Base, State and Theme rules from [SMACSS](https://smacss.com/),
element and subclass (modifier) naming conventions from [BEM](https://en.bem.info), the idea of common OOP principles in CSS (inheritance, OCP, SRP)
from [OOCSS](http://oocss.org/), context-independent cascading from
[Modular CSS naming conventions](http://thesassway.com/advanced/modular-css-naming-conventions)

# Contents
* Key concepts
* [Component/Element/Subclass](#component)
* [State](#state)
* [Theme](#theme)
* [File Structure Example](#a-fs)
* [Naming Conventions](#a-nc)
* [Selector Conventions](#a-sc)

## Component
Class | Location
----|----
`.panel` | `./component/panel/_index.scss`
`.nav-bar` | `./component/nav-bar/_index.scss`

**Component** is a reusable module of UI (e.g. `nav-bar`, `panel`, `form`).
Component consists of elements (e.g. `form__title`) and can be extended by subclasses.

![](images/a-component-diagram.png)

## Element
Class | Location
----|----
`.panel__header` | `./component/panel/_index.scss`

Component is built of elements. Elements is an integral parts of a component and
cannot be reused outside of component scope.

## Subclass
Class | Location
----|----
`.panel--primary` | ./component/panel/_primary.scss

Following OOP practices, we inherit from a base component to a subclass
For example, when we are required of a dialog window, we create `./component/dialog/_index.scss` where we put the base styles for
any dialogs in the application. Then we add `./component/dialog/_alert.scss` where we set the extending styles
for the concrete modal window. Now we refer to a concrete component in the HTML like that:

```

..

..

```

### Subclasses and elements
Elements are styled in scopes of subclasses:
```sass
.shopping-cart {
// Base styles
}
.shopping-cart--default {
.shopping-cart__heading {
color: $color-white;
}
}
.shopping-cart--inverse {
.shopping-cart__heading {
color: $color-block;
}
}
```
Here we have an abstract component `.shopping-cart` extended by `.shopping-cart--default` and `.shopping-cart--inverse`
where the first has white heading and the second black one.

## Component Example

![](images/a-component.png)

#### HTML
```html



Install is 70% complete



pause




```

#### ./component/progressbar/_index.scss
```sass
.progressbar {
position: relative;
}
.progressbar__progress {
border: 0;
position: absolute;
width: 100%;
bottom: 0;
left: 0;
appearance: none;
&::-webkit-progress-bar {/*..*/ }
&::-webkit-progress-value {/*..*/ }
&::-moz-progress-bar {/*..*/ }
}
.progressbar__status {
display: flex;
position: relative;
font-size: 1rem;
}
.progressbar__actions {
position: absolute;
bottom: 0;
right: 0;
> .icon { /*..*/ }
}
```

#### ./component/progressbar/_big.scss
```sass
.progressbar--big > .progressbar__status {
font-size: 1.6rem;
text-transform: uppercase;
padding: 16px;
}
```
#### ./component/progressbar/_small.scss
```sass
.progressbar--small > .progressbar__status {
font-size: 1.1rem;
text-transform: lowercase;
padding: 11px;
}
```

Top

## State

States are toggable sets of rules that:
- describe component/element states: `.is-expanded`, `.is-hidden`, `.has-error`.
- alternate presentation: `.is-uppercase`, `.is-sticky`, `.is-pointer`.

State CSS classes usually consist of a few rules. Unlike components they do not represent entities, but
modify object state.

##### HTML
```html


...

```

##### ./component/_main.scss
```css
.main {
/* default style */
&.has-error {
/* state modified style */
}
}
```

##### ./base/_global-state.scss
```css
/* Global state */
.is-hidden {
display: none !important;
}
```

Top

## Theme
Theme classes used to alternate the style of a component
depending on the context.

##### HTML
```html


...

```

##### ./component/sidebar/_index.scss
```css
.sidebar {
/* default style */
}
.theme-foo .sidebar {
/* alterntive style */
}
```

#### Programmatic Theming

If we need components to change styles according to a set theme (`.theme-baz` and
`.theme-qux`), we can use a mixin like:

```sass
@mixin theme-dialog($theme) {
$bg: get-theme-style($theme, "bg");
.theme-#{$theme} .dialog {
background-color: #{$bg};
}
}
@each $theme in $themes {
@include theme-dialog($theme);
}
```

Where we have in `./base/_defenitions.scss`:
```sass
$themes: baz qux;
@function get-theme-style($theme, $key) {
$baz-map: (
"bg": $baz-bg
);
$qux-map: (
"bg": $qux-bg
);
@if $theme == "baz" {
@return map-get( $baz-map, $key );
}
@if $theme == "qux" {
@return map-get( $qux-map, $key );
}
@return map-get( $baz-map, $key );
}
```

#### Theme Example

![](images/a-theme.png)

```html



Lorem ipsum dolor





Lorem ipsum dolor





Lorem ipsum dolor





Top


File Structure
-------

```
Styles
├───component
│ ├───btn
│ │ _index.scss
│ │ _primary.scss
│ │
│ └───form
│ │ _index.scss
│ │
│ ├───auth
│ │ _index.scss
│ │ _login.scss
│ │
│ └───nav
│ _index.scss
│ _search.scss

└───base
│ _h5b-normalize.scss
│ _base.scss
│ _definitions.scss
│ _global-state.scss
│ _animations.scss

└───mixin
_media.scss

```

Top


Naming Conventions
-------

* Class name represents source location. Let's say styles for `.form--nav--search` is expected in the file
`component/form/nav/_search.scss` [File Structure](#a-fs)).
* State classes are prefixed with `is-` or `has-` (e.g. `.is-hidden`, `.has-success`).
* Theme classes are prefixed with `theme-`.

Class | Entity
----|----
`.btn`, `.main-nav` | a component (only hyphen delimited names)
`.main-nav__title` | element (subcomponent)
`.btn--primary`, `.main-nav--landing-page` | subclass
`.is-hidden`, `.has-success` | a state
`.theme-default`, `.theme-garland` | a theme

##### Further readings
* [Modular CSS naming conventions](http://thesassway.com/advanced/modular-css-naming-conventions)
* [Naming CSS Stuff Is Really Hard](http://seesparkbox.com/foundry/naming_css_stuff_is_really_hard)

Top


Selector Conventions
-------

### Keep selectors short
Remember that browser reads selectors from right to left, long selectors may give it an extra workload. Besides it is
a unwanted contribution to production style-sheet file size. Deep nesting in CSS-preprocessor sources may cause
the described problems even without your awareness. So, keep nesting no more than 3-4 levels.

Avoid excessive `@extend`-ing in SASS/LESS. It adds a long CSS selectors in a compiled code.

### Use classes for styling, IDs and data-attributes to bind JavaScript

IDs can be used in HTML for fragment identifiers and JavaScript hooks, but IDs should never be used in CSS.
Functional element attributes can be quite handy for styling (e.g. input[disabled]), but we rather avoid styling via custom attributes (data-attr)
for a better separation of concerns. When you use only classes for styling and keep IDs and attributes for
JavaScript binding you get much more flexibility in moving styles across the document.

### Loose Coupling (Tag Independence)
Avoid qualified selectors (prepended with tag). Thus you will gain additional agility in moving classes around components.

### Loose Coupling (Location Independence)
Avoid long selectors with descendant/child combinators (.feed nav ul li h2).
Long selectors besides harmful affect on selector performance mean that style rule-set is tied to particular
location in the DOM. Independent selectors allow us to move components around our markup more freely.

Top

## Further Reading

* [When using IDs can be a pain in the class...](http://csswizardry.com/2011/09/when-using-ids-can-be-a-pain-in-the-class/)
* [Code smells in CSS](http://csswizardry.com/2012/11/code-smells-in-css/)

[![Analytics](https://ga-beacon.appspot.com/UA-1150677-13/dsheiko/pcss)](http://githalytics.com/dsheiko/pcss)