{"id":13465079,"url":"https://github.com/chris-pearce/css-guidelines","last_synced_at":"2025-04-04T20:14:18.410Z","repository":{"id":25477092,"uuid":"28907793","full_name":"chris-pearce/css-guidelines","owner":"chris-pearce","description":"Sensible CSS Guidelines for large scale projects 🚀","archived":false,"fork":false,"pushed_at":"2021-01-01T04:26:16.000Z","size":32,"stargazers_count":812,"open_issues_count":2,"forks_count":77,"subscribers_count":39,"default_branch":"master","last_synced_at":"2025-03-28T19:09:13.064Z","etag":null,"topics":["css","css-architecture","css-convention","css-guidelines","naming-conventions"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chris-pearce.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-07T09:27:18.000Z","updated_at":"2025-03-07T10:21:34.000Z","dependencies_parsed_at":"2022-09-13T10:00:42.888Z","dependency_job_id":null,"html_url":"https://github.com/chris-pearce/css-guidelines","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-pearce%2Fcss-guidelines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-pearce%2Fcss-guidelines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-pearce%2Fcss-guidelines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-pearce%2Fcss-guidelines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chris-pearce","download_url":"https://codeload.github.com/chris-pearce/css-guidelines/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247242680,"owners_count":20907134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["css","css-architecture","css-convention","css-guidelines","naming-conventions"],"created_at":"2024-07-31T14:00:57.791Z","updated_at":"2025-04-04T20:14:18.380Z","avatar_url":"https://github.com/chris-pearce.png","language":null,"funding_links":[],"categories":["Others","Learn HTML"],"sub_categories":["Learn CSS"],"readme":"# CSS Guidelines\n\n\n\n\n## Contents\n\n- [Terminology And Conventions Used In These Guidelines](#terminology-and-conventions-used-in-these-guidelines)\n- [General Principles](#general-principles)\n    - [Acknowledgements And Credit](#acknowledgements-and-credit)\n- [Syntax And Formatting](#syntax-and-formatting)\n    - [CSS Ruleset](#css-ruleset)\n    - [Sass Specifics](#sass-specifics)\n    - [Declaration Order](#declaration-order)\n    - [More On Ordering](#more-on-ordering)\n    - [80 Characters Wide](#80-characters-wide)\n    - [Meaningful Whitespace](#meaningful-whitespace)\n- [Commenting](#commenting)\n    - [DocBlock-*esque*](#docblock-esque)\n    - [Partial Heading](#partial-heading)\n    - [Partial Intro](#partial-intro)\n    - [Inline Comments](#inline-comments)\n    - [Number Labelling](#number-labelling)\n    - [Component-extension Pointers](#component-extension-pointers)\n    - [Section Comment](#section-comment)\n- [Naming Conventions](#naming-conventions)\n    - [BEM-like Naming](#bem-like-naming)\n    - [Hyphen-delimited](#hyphen-delimited)\n    - [Namespace](#namespace)\n        - [What We Namespace](#what-we-namespace)\n        - [The Namespaces](#the-namespaces)\n            - [JS Hooks](#js-hooks)\n            - [State Hooks](#state-hooks)\n            - [Server-side Hooks](#server-side-hooks)\n            - [QA Hooks](#qa-hooks)\n            - [Tracking Hooks](#tracking-hooks)\n    - [Settings](#settings)\n        - [Global Settings](#global-settings)\n        - [Local Settings](#local-settings)\n    - [Sizes And Sides](#sizes-and-sides)\n- [Tooling](#tooling)\n    - [Text Editor Configuration](#text-editor-configuration)\n        - [Sublime Text](#sublime-text)\n    - [Linting](#linting)\n    - [EditorConfig](#editorconfig)\n- [Writing And Architecturing CSS](#writing-and-architecturing-css)\n    - [Further Reading](#further-reading)\n\n\n\n\n## Terminology And Conventions Used In These Guidelines\n\n- Sass variable = setting\n- An ellipsis (`…`) = a placeholder for code used in a code example block\n- Written for a team\n\n\n\n\n## General Principles\n\n\u003e \"Part of being a good steward to a successful project is realizing that writing code for yourself is a Bad Idea™. If thousands of people are using your code, then write your code for maximum clarity, not your personal preference of how to get clever within the spec.\" — [Idan Gazit](http://gazit.me/)\n\nIn working on large, long-running projects, with dozens of developers of differing specialities and abilities, it is important that we all work in a unified way in order to—among other things—\n\n- keep stylesheets maintainable;\n- keep code transparent, sane, consistent, and readable;\n- keep stylesheets scalable.\n\nNo matter the document, we must always try and keep a common formatting. This\nmeans:\n\n- [consistent syntax](#syntax-and-formatting);\n- [consistent and meaningful commenting](#commenting);\n- and [consistent naming](#naming-conventions).\n\nAll our CSS is written in [Sass](http://sass-lang.com/). Sass provides a lot of incredibly powerful features, however, we don't want to become a platform to showcase Sass' capabilities; we should strive to keep the Sass we write as simple and CSS-like as possible.\n\n### Acknowledgements And Credit\n\nWe've borrowed (shamelessly) a lot of our guidelines from [Harry Roberts](http://csswizardry.com/) excellent [CSS Guidelines](http://cssguidelin.es/), and some other sources of inspiration:\n\n- [Sass Guidelines](http://sass-guidelin.es/)\n- [Idiomatic CSS](https://github.com/necolas/idiomatic-css)\n\n\n\n\n## Syntax And Formatting\n\nStarting right at the top, we want\n\n- four (4) space indents, no tabs;\n- [80 character wide](#80-characters-wide) columns;\n- multi-line CSS;\n- [meaningful use of whitespace](#meaningful-whitespace).\n\n**N.B.** our [Tooling](#tooling) will automate and enforce most of our syntax and formatting rules.\n\n### CSS Ruleset\n\nFor your reference here is an anatomy of a CSS ruleset:\n\n```\n[selector] {\n    [property]: [value];\n    [\u003c- Declaration -\u003e]\n}\n```\n\nOur chosen format for how CSS rulesets should be written\n\n- each selector on its own new line;\n- a space before the opening brace (`{`);\n- the opening brace (`{`) on the same line as the last selector;\n- a space after the colon (`:`);\n- each declaration on its own new line;\n- each declaration indented by four (4) spaces;\n- a trailing semi-colon (`;`) at the end of all declarations;\n- the closing brace (`}`) on its own new line;\n- long, comma-separated property values—such as collections of gradients or shadows—arranged across multiple new lines, making sure all values are indented at the same level as the first;\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n// Not having each selector on its own line\n.selector-1, .selector-2\n// Not having the opening brace (`{`) on the same line as the last selector\n{\n    // Not having each declaration on its own line\n    background-color: $color-brand; background-image: linear-gradient($color-white, $color-grey-mercury), linear-gradient($color-black, $color-grey-alabaster);\n    // Not using new lines for the comma-separated property values and not\n    // indenting all the values at the same level as the first\n    box-shadow: 1px 1px 1px $color-black, 2px 2px 1px 1px $color-grey-mercury inset;\n    // Not using a space after the colon (`:`)\n    color:$color-text-base;\n  // Not indenting a declaration with four (4) spaces\n  display: block;\n    // Not using a trailing semi-colon (`;`) at the end of the declaration\n    // and not having the closing brace (`}`) on its own new line\n    padding: rem($spacing-base) }\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.selector-1,\n.selector-2 {\n    background-color: $color-brand;\n    background-image: linear-gradient($color-white, $color-grey-mercury),\n                      linear-gradient($color-black, $color-grey-alabaster);\n    box-shadow: 1px 1px 1px $color-black,\n                2px 2px 1px 1px $color-grey-mercury inset;\n    color: $color-text-base;\n    display: block;\n    padding: rem($spacing-base);\n}\n```\n\nAdding to the above, we also want to pay attention to\n\n- use lowercase and preferably the shorthand version for all hexadecimal units—if you wish to use the longhand version then this is fine;\n- use shorthands for properties and property values where it makes sense; where it doesn't make sense is using a shorthand property that makes you declare zero-values, here it is better to be explicit even if it means more lines of CSS;\n- use single quotes for strings, `url()` values, etc;\n- wrap attribute selector values in double quotes;\n- include a space after each comma in comma-separated values;\n- parentheses should not be padded with spaces;\n- when a decimal mark is needed always include the zero;\n- use double colons (`::`) for pseudo elements;\n- use relative units—pretty much everything is `rem` based and outside of font sizing `em`s may be used for spacing within a component for scaling based on font size, but this should be checked to see what the current approach is as we want consistency with this;\n- use the `px` unit for fixed-sized things—this is rare nowadays as we're building responsive layouts—and for the following CSS properties:\n  - `border-radius`\n  - `border`\n  - `box-shadow`\n  - `text-shadow`\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n.selector {\n    // Not using single quotes around the `url()` value\n    background-image: url(/path/to/image);\n    // Not using lowercase for the hexidecimal unit\n    color: #EEEEEE;\n    // Not using spaces after each comma in the `rgba` value and padding the\n    // parentheses with spaces\n    color: rgba( 0,0,0,0.8 );\n    // Not including a zero before the decimal mark\n    font-size: .98rem;\n    // Not using shorthand for the property value\n    padding: rem(12) rem(12) rem(12) rem(12);\n    // Declaring zero-values due to shorthand property being used and not\n    // removing the unit from a zero-value\n    margin: 0rem rem(6);\n\n    // Not using the double colon format\n    \u0026:before {\n        // Not using shorthand for the property (should be `background-color`)\n        background: $color-black;\n        // Not using single quotes around the `content` string\n        content: \"✌\";\n    }\n\n    // Not using double quotes around the attribute selector value\n    \u0026[type=text] {\n        …\n    }\n}\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.selector-1 {\n    background-image: url('/path/to/image');\n    color: #eee;\n    color: rgba(0, 0, 0, 0.8);\n    font-size: 0.98rem;\n    padding: rem(12);\n    margin-left: rem(6);\n    margin-right: rem(6);\n\n    \u0026::before {\n        background-color: $color-black;\n        content: '✌';\n    }\n\n    \u0026[type=\"text\"] {\n        …\n    }\n}\n```\n\nTo expand on this rule: *use shorthands for properties and property values where it makes sense*, treating your properties this way makes for more maintainable and robust CSS.\n\nA good example of this is using the shorthand `background-color` property instead of the longhand `background` property when you only need to declare a colour. Using the shorthand `background-color` property means we now don't have to worry about potentially having to override all of the properties that come bundled with the longhand `background` property, which are:\n\n```scss\nbackground-image: initial;\nbackground-position-x: initial;\nbackground-position-y: initial;\nbackground-size: initial;\nbackground-repeat-x: initial;\nbackground-repeat-y: initial;\nbackground-attachment: initial;\nbackground-origin: initial;\nbackground-clip: initial;\nbackground-color: transparent;\n```\n\n*Phew!*\n\n### Sass Specifics\n\nSyntax and formatting rules specifically for Sass code\n\n- only use the parent selector reference (`\u0026`) for these use cases\n    - appending it to pseudo classes;\n    - appending it to pseudo elements;\n    - appending it to [State hooks](#state-hooks) in order to chain it to the selector it's referencing;\n    - referencing itself when combined with any of the above to avoid duplicating CSS properties;\n- only use silent placeholder selectors with the `@extend` directive, however, we'd rather avoid `@extend` as much as possible;\n- avoid selector nesting, if you have to nest then limit it to one level deep;\n- when adding a unit to a number stored in a setting, you have to multiply the number by 1 unit;\n- hexadecimal units should not exist outside of global and local partial settings i.e. all colours need to be stored in a setting using a meaningful name;\n- always use colour settings for `rgb` values;\n- avoid writing parentheses for argument-less mixins;\n- all Sass functions and mixins to use the [SassDoc](http://sassdoc.com/) documentation guidelines;\n- for conditional statements:\n    - no parentheses unless they are necessary;\n    - always an empty new line before `@if`;\n    - `@else` statements on the same line as previous closing brace (`}`);\n    - always an empty new line after the last closing brace (`}`) unless the next line is a closing brace (`}`);\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n.selector {\n    // Extending a class selector\n    @extend .selector;\n    // Including parentheses for an argument-less mixin\n    @include h-text-truncate();\n    // Not using colour settings\n    background-color: rgba(0, 0, 0, 0.5);\n    color: #eee;\n    // Not multiplying the unit to a number stored in a setting\n    padding: $padding-setting + rem;\n\n    // Using the parent selector (`\u0026`) to chain to the selector it's\n    // referencing when it is not a State hook\n    \u0026.selector--modifier {\n        …\n    }\n\n    // Using the parent selector (`\u0026`) to target a class that is applied at a\n    // higher level in the DOM\n    .parent-selector \u0026 {\n        …\n    }\n\n    // Nesting selectors more than one level deep\n    .nested__selector .nested__selector {\n        …\n    }\n}\n\n// An incorrectly formatted conditional statement\n@if ($support-legacy == true) {\n    …\n}\n@else {\n    …\n}\n\n// Not using SassDoc documentation guidelines\n@function strip-unit($number) {\n    @if type-of($number) == \"number\" and not unitless($number) {\n        @return $number / ($number * 0 + 1);\n    }\n    @return $number;\n}\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.selector {\n    @extend %selector;\n    @include h-text-truncate;\n    background-color: rgba($color-black, 0.5);\n    color: $color-text-base;\n    padding: $padding-setting * 1rem;\n}\n\n.selector--modifier {\n    …\n}\n\n.parent-selector .selector {\n    …\n}\n\n.nested__selector {\n    …\n}\n\n@if $support-legacy {\n    …\n} @else {\n    …\n}\n\n/// Remove a unit from a number.\n///\n/// @author Chris Pearce\n///\n/// @access private\n///\n/// @param {Number [unit]} $number — Number to remove unit from\n///\n/// @returns {Number}\n///\n/// @todo Add @exception rules, see: https://gist.github.com/terkel/4373420\n///\n/// @example scss - Usage\n///     strip-unit(24px)\n///     strip-unit(2.3em)\n\n@function strip-unit($number) {\n    @if type-of($number) == \"number\" and not unitless($number) {\n        @return $number / ($number * 0 + 1);\n    }\n    @return $number;\n}\n\n// Correct use of the parent selector reference (`\u0026`)\n.selector {\n    …\n\n    \u0026,\n    \u0026:hover,\n    \u0026:focus {\n        color: $color-text-base;\n    }\n\n    \u0026:hover,\n    \u0026:focus {\n        …\n    }\n\n    \u0026::before {\n        …\n    }\n\n    \u0026.is-active {\n        …\n    }\n}\n```\n\n### Declaration Order\n\nProperties should be ordered alphabetically, that's it.\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n.selector {\n    display: inline-block;\n    padding-right: rem(10);\n    padding-left: rem(10);\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    z-index: 10;\n}\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.selector {\n    bottom: 0;\n    display: inline-block;\n    left: 0;\n    padding-left: rem(10);\n    padding-right: rem(10);\n    position: absolute;\n    right: 0;\n    top: 0;\n    z-index: 10;\n}\n```\n\n### More On Ordering\n\nBecause we use Sass we can have more than just declarations between the opening and closing braces (`{ }`) of a ruleset therefore we want to follow a specific order, which is\n\n1. extend calls (`@extend`);\n2. mixin calls (`@include`) *with no* `@content`;\n3. declarations;\n4. pseudo classes—combining [State hooks](#state-hooks) here is fine;\n5. pseudo elements;\n5. mixin calls (`@include`) *with* `@content`—mainly being media queries;\n6. nested selectors, limit to one level deep or best to avoid in most cases;\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n.selector {\n    // Declarations should not come first and should all be grouped together\n    bottom: 0;\n    display: inline-block;\n    left: 0;\n    position: absolute;\n    right: 0;\n    // Mixin calls should come after extend calls and not mixed in with\n    // declarations\n    @include hidpi-bg-img('path/to/image/image.png', 32px);\n    top: 0;\n    z-index: 10;\n    // Extend calls should come first\n    @extend %some-silent-placeholder-selector;\n\n    // Pseudo elements should not come before pseudo classes\n    \u0026::before {\n        …\n    }\n\n    \u0026:hover,\n    \u0026:focus,\n    \u0026.is-active {\n        …\n    }\n\n    // Nested selector should come last\n    .nested-selector {\n        …\n    }\n\n    @media (min-width: bp(lap)) {\n        …\n    }\n}\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.selector {\n    @extend %some-silent-placeholder-selector;\n    @include hidpi-bg-img('path/to/image/image.png', 32px);\n    bottom: 0;\n    display: inline-block;\n    left: 0;\n    position: absolute;\n    right: 0;\n    top: 0;\n    z-index: 10;\n\n    \u0026:hover,\n    \u0026:focus,\n    \u0026.is-active {\n        …\n    }\n\n    \u0026::before {\n        …\n    }\n\n    @media (min-width: bp(lap)) {\n        …\n    }\n\n    .nested-selector {\n        …\n    }\n}\n```\n\n### 80 Characters Wide\n\nWhere possible, limit CSS files' width to 80 characters. Reasons for this include\n\n- the ability to have multiple files open side by side;\n- viewing CSS on sites like GitHub, or in terminal windows;\n- providing a comfortable line length for comments.\n\nThere will be unavoidable exceptions to this rule—such as URLs, or gradient syntax—which shouldn't be worried about.\n\n### Meaningful Whitespace\n\nWhitespace is free, use it liberally and judiciously as it greatly improves the readability of our CSS.\n\nWe want our rulesets, the [discrete sections within our rulesets](#more-on-ordering) and the discrete sections within our partials, to *always* have at least one (1) empty line between them—two (2) empty lines is also fine but never more than two (2). One (1) empty line should *always* be between setting declarations, partial import directives, and a [DocBlock-*esque*](#docblock-esque) style comment and its subject.\n\nFour (4) empty lines are needed between entirely new sections (see [Section Comment](#section-comment)) however this will hardly ever be needed as we use highly concentrated partials—the most common application for this is within a global master stylesheet.\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n/* ============================================================================\n   COMPONENTS -\u003e SEARCH INPUT\n   ========================================================================= */\n/**\n * A component for the most common type of search input which has deep rounded\n * corners, shadows, and a background image of a magnifying glass icon\n * positioned to the left or right side. Visit: /subscribers/ to see an\n * example.\n * @markup\n   \u003cform action=\"\" class=\"c-search-input [modifier]\"\u003e\n       \u003clabel for=\"[id.value]\" class=\"c-search-input__label  h-hide-visually\"\u003eLabel text\u003c/label\u003e\n       \u003cinput type=\"search\" id=\"[value]\" class=\"c-search-input__input\"\u003e\n       \u003cspan class=\"c-search-input__icon\"\u003e\u003c/span\u003e\n  \u003c/form\u003e\n */\n\n/**\n * Settings.\n */\n\n$c-search-input-padding-top: 5;\n$c-search-input-padding-bottom: $c-search-input-padding-top + 1;\n\n.c-search-input {\n    position: relative;\n}\n\n\n\n\n/**\n * The input.\n */\n.c-search-input__input {\n    border: 1px solid $color-grey-alto-4;\n    box-shadow: $input-box-shadow;\n    color: $color-grey-tundora;\n    padding: rem($c-search-input-padding-top);\n    padding-bottom: rem($c-search-input-padding-bottom);\n    transition: $input-transition;\n    \u0026:focus {\n        border-color: $color-blue-pigeon-post;\n        box-shadow: $input-box-shadow-focus;\n        // Can remove this as we're providing a good custom outline\n        outline: none;\n    }\n}\n/**\n * The magnify icon.\n */\n\n.c-search-input__icon {\n  background: url('/img/icons/icon-small/search.png') no-repeat;\n  height: $c-search-input-icon-size;\n  left: $c-search-input-icon-position-left;\n  width: $c-search-input-icon-size;\n}\n/**\n * Modifier: when icon is positioned on the right side.\n */\n.c-search-input--icon-right .c-search-input__icon {\n    left: auto;\n    right: $c-search-input-icon-position-left;\n}\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/* ============================================================================\n   COMPONENTS -\u003e SEARCH INPUT\n   ========================================================================= */\n\n/**\n * A component for the most common type of search input which has deep rounded\n * corners, shadows, and a background image of a magnifying glass icon\n * positioned to the left or right side. Visit: /subscribers/ to see an\n * example.\n *\n * @markup\n   \u003cform action=\"\" class=\"c-search-input [modifier]\"\u003e\n       \u003clabel for=\"[id.value]\" class=\"c-search-input__label  h-hide-visually\"\u003eLabel text\u003c/label\u003e\n       \u003cinput type=\"search\" id=\"[value]\" class=\"c-search-input__input\"\u003e\n       \u003cspan class=\"c-search-input__icon\"\u003e\u003c/span\u003e\n  \u003c/form\u003e\n */\n\n\n/**\n * Settings.\n */\n\n$c-search-input-padding-top: 5;\n\n$c-search-input-padding-bottom: $c-search-input-padding-top + 1;\n\n\n.c-search-input {\n    position: relative;\n}\n\n\n/**\n * The input.\n */\n\n.c-search-input__input {\n    border: 1px solid $color-grey-alto-4;\n    box-shadow: $input-box-shadow;\n    color: $color-grey-tundora;\n    padding: rem($c-search-input-padding-top);\n    padding-bottom: rem($c-search-input-padding-bottom);\n    transition: $input-transition;\n\n    \u0026:focus {\n        border-color: $color-blue-pigeon-post;\n        box-shadow: $input-box-shadow-focus;\n        // Can remove this as we're providing a good custom outline\n        outline: none;\n    }\n}\n\n\n/**\n * The magnify icon.\n */\n\n.c-search-input__icon {\n  background: url('/img/icons/icon-small/search.png') no-repeat;\n  height: $c-search-input-icon-size;\n  left: $c-search-input-icon-position-left;\n  width: $c-search-input-icon-size;\n}\n\n\n/**\n * Modifier: when icon is positioned on the right side.\n */\n\n.c-search-input--icon-right .c-search-input__icon {\n    left: auto;\n    right: $c-search-input-icon-position-left;\n}\n```\n\n\n\n\n## Commenting\n\nWell commented code is *extremely* important and we really need to be heavily commenting our CSS. Take time to describe components, how they work, their limitations, and the way they are constructed. We don't want to leave others in the team guessing as to the purpose of uncommon or non-obvious code.\n\nWe want to be using a comment style that is simple and consistent.\n\nStarting right at the top, we want\n\n- to place comments on a new line above their subject;\n- to keep line-length to a sensible maximum: [80 columns](#80-characters-wide);\n- to make liberal use of comments to break CSS code into discrete sections;\n- to use 'sentence case' comments and consistent text indentation.\n\n### DocBlock-*esque*\n\nThe default style of comment we use is a [DocBlock](http://en.wikipedia.org/wiki/PHPDoc#DocBlock)*-esque* style comment. This type of comment begins with `/**` and ends with `*/` and has an `*` at the beginning of every line except when referencing code—the absence of the `*` is so that the code can easily be copied.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/**\n * A component for the most common type of search input which has deep rounded\n * corners, shadows, and a background image of a magnifying glass icon\n * positioned to the left or right side. Visit: /subscribers/ to see an\n * example.\n *\n * @markup\n   \u003cform action=\"\" class=\"c-search-input [modifier]\"\u003e\n       \u003clabel for=\"[id.value]\" class=\"c-search-input__label  u-hide-visually\"\u003eLabel text\u003c/label\u003e\n       \u003cinput type=\"search\" id=\"[value]\" class=\"c-search-input__input\"\u003e\n       \u003cspan class=\"c-search-input__icon\"\u003e\u003c/span\u003e\n  \u003c/form\u003e\n */\n```\n\nWe should be commenting each discrete piece of CSS in a partial and it should start with a DocBlock*-esque* style comment. One (1) or two (2) empty lines are always used between each discrete piece and one (1) empty line used between the comment and its subject.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/**\n * The underlay which is the wrapper of the modal dialog which uses Flexbox\n * to position the modal dialog smack in the middle of the viewport,\n * includes a fall-back for non-supporting Flexbox browsers.\n */\n\n.c-modal-dialog-underlay {\n    …\n}\n\n/**\n * Fall-back for non-supporting Flexbox browsers, using the Modernizr\n * feature detection technique via the `:not` CSS selector to get around\n * any lag of the Modernizr JS loading.\n */\n\nhtml:not(.flexbox) .c-modal-dialog-underlay {\n    …\n}\n```\n\n### Partial Heading\n\nEvery partial needs a partial heading type comment at the very top of the file.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/* ============================================================================\n   CORE -\u003e MIXINS -\u003e CONVERT PX TO EM/REM\n   ========================================================================= */\n// [empty line]\n```\n\nBreaking this down we have\n\n- uppercase for text;\n- a breadcrumb pattern showing where the partial belongs in the CSS architecture, the last part being the same name as the partial filename;\n- one (1) empty line to come after.\n\n### Partial Intro\n\nA partial intro type comment follows a [Partial Heading](#partial-heading) type comment, think of this like a books Prologue/Preface/Introduction.\n\nIt should be structured like this\n\n- a description—be as detailed as you can here;\n- any attention grabbing comments prefix with **N.B.**;\n- mandatory sections prefixed with `@`\n    - `@markup`: if applicable the markup that the CSS applies too—this is typically for components—*this should always come last* if you have a living style guide this will no longer be required;\n    - `@demo`: if applicable any URL(s) to demonstration(s);\n    - `@credit`: if applicable any URL(s) to credit where any ideas came from;\n- non-mandatory sections prefixed with `@`\n    - `@todo`: any outstanding tasks;\n    - `@consideration`: any things to consider;\n- One (1) empty line between each of the above sections and two (2) empty lines coming after the intro.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/**\n * A generic drop down helper powered by some JavaScript which toggles a\n * class e.g. `is-visible` on the drop down trigger (the button that makes the\n * drop down visible and invisible) and the target (the actual drop down).\n * This class will be used to make the drop down target visible when the\n * trigger is selected. There is also a version for showing the drop down via\n * the `:hover` pseudo class which is turned off for touch devices.\n *\n * N.B. this helper is dependent on the \"Align\" helper.\n *\n * @credit\n * http://www.stubbornella.org/content/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code\n *\n * @markup\n   \u003cdiv class=\"h-drop-down [modifier(s)]\"\u003e\n     \u003c!-- The trigger --\u003e\n     \u003cbutton class=\"h-drop-down__trigger\"\u003e[text node]\u003c/button\u003e\n     \u003c!-- The target --\u003e\n     \u003cdiv class=\"h-drop-down__target\"\u003e[child elements]\u003c/div\u003e\n   \u003c/div\u003e\n */\n// [empty line]\n// [empty line]\n```\n\nIn the `@markup` section we want to be indicating that the component has [BEM](#bem-like-naming) *Modifier(s)*. We do this by including a `[modifier]` placeholder, like in the example above, if there are more than one then simply add `(s)` to the end of the “modifier” word, like so: `[modifier(s)]`. Also we want to use sensible placeholders between elements, so if an element only has text as its child then use `[text node]`, if an element features other elements that are not part of the component then use `[child elements]`, like in the example above.\n\n### Inline Comments\n\nSass allows us to use less verbose CSS comments prefixed with two forward slashes.\n\nThis type of comment can be used for inline type comments, typically when you want to comment above a declaration within a ruleset or when you want to use a *sub* type comment under a [DocBlock*-esque*](#docblock-esque) type comment.\n\nThese comments should always be above their subject with a space coming after the two forward slashes.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/**\n * Settings.\n */\n\n// Colours\n$c-pagination-background-color: #000;\n\n$c-pagination-foreground-color: #333;\n\n// Padding\n$c-pagination-padding-left: $spacing-base;\n\n$c-pagination-padding-right: $spacing-half;\n\n\nh1 {\n  font-size: rem($font-size-heading-1);\n  // This is needed to turn off the top margin set in normalize.css\n  margin-top: 0;\n  // This is needed to fix a stupid bug in IE 9 ಠ╭╮ಠ\n  width: 100%;\n}\n```\n\n### Number Labelling\n\nA number labelling type comment is used when [Inline Comments](#inline-comments) would need to be repeated.\n\n**N.B.** this is the only time when comments—the numbers—don't need to be on a new line above their subject.\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\nimg {\n  // Make responsive\n  max-width: 100%;\n  // Make responsive\n  height: auto;\n  // So that `alt` text is visually offset if images don't load\n  font-style: italic;\n}\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/**\n * Images.\n *\n * 1. Make responsive.\n * 2. So that `alt` text is visually offset if images don't load.\n */\n\nimg {\n  max-width: 100%; // [1]\n  height: auto; // [1]\n  font-style: italic; // [2]\n}\n```\n\n### Component-extension Pointers\n\nSometimes you may need to apply some styles to a component within the context of another component when these two components exist in their own individual partials. For example, you may have a Button component that needs some unique padding applied when used in the context of a Search component.\n\n*Make sure that this type of treatment is needed and that its not just a [BEM](#bem-like-naming) Modifier of your component.*\n\nWhen this occurs we want to document this relationship across partials using a simple Component–extension Pointer type comment, and we want to include the comment in the partial where the component styles are being extended. So using the example above the comment will live in the Search component partial.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/**\n * Extend `.c-button` in Components -\u003e Button.\n */\n\n.c-search .c-button {\n    …\n}\n```\n\n### Section Comment\n\nWhen we have really long stylesheets we need a comment that stands out more than a [DocBlock*-esque*](#docblock-esque) type comment.\n\nThis type of comment is rare due to us working in highly concentrated partials—the most common application for this is within a global master stylesheet. Four (4) empty lines come between each section and one (1) empty line between the comment and its subject.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/* Some section\n   ========================================================================= */\n\n    …\n// [empty line]\n// [empty line]\n// [empty line]\n// [empty line]\n/* Some section\n   ========================================================================= */\n```\n\n\n\n\n## Naming Conventions\n\nWe always want to ensure that all of our classes and settings are meaningfully named and adhering to our set conventions and to not worry about the length of our class names as gzip will compress well written code incredibly well.\n\nStarting right at the top, we use\n\n- lowercase;\n- [BEM-like naming](#bem-like-naming) for most classes;\n- [hyphen-delimited](#hyphen-delimited) for everything else;\n- [namespaces](#namespace) for almost everything.\n\nWe don't want\n\n- CamelCase;\n- underscores with the exception of being used in BEM *Element* selectors;\n- `id`s, **never**.\n\n### BEM-like Naming\n\nWe apply BEM as described in the [BEM-like naming](http://cssguidelin.es/#bem-like-naming) section of [Harry Roberts](http://csswizardry.com/) excellent [CSS Guidelines](http://cssguidelin.es/). For further reading check out this article: [MindBEMding – getting your head 'round BEM syntax](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/), again by Harry Roberts.\n\nSo rather than rehashing everything about BEM please read the above resources.\n\n### Hyphen-delimited\n\nWe use hyphen-delimited for:\n\n- Settings\n- Mixins\n- Functions\n- Animation names\n- Filenames\n- [State hooks](#state-hooks)\n- [JS hooks](#js-hooks)\n- [Server-side hooks](#server-side-hooks)\n- [QA hooks](#qa-hooks)\n- [Tracking hooks](#tracking-hooks)\n\n### Namespace\n\nMostly everything in our CSS is namespaced so that our CSS is as transparent and self-documenting as possible.\n\n#### What We Namespace\n\n- Classes\n- Settings\n- Mixins\n- Functions\n- Filenames\n\nThey are all prefixed with a letter followed by a hyphen.\n\n#### The Namespaces\n\n- `l-`: **Layout Modules** ([read more here](https://github.com/chris-pearce/scally/blob/master/layout/README.md))\n\n    *Examples:*\n    - `.l-grid`\n    - `$l-grid-gutter`\n    - `_l-grid.scss`\n\n- `c-`: **Components** ([read more here](https://github.com/chris-pearce/scally/blob/master/components/README.md))\n\n    *Examples:*\n    - `.c-button`\n    - `$c-button-foreground-color`\n    - `_c-button.scss`\n\nTaken from [Harry Roberts](http://csswizardry.com/) article [More Transparent UI Code with Namespaces](http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/)—*visit the linked sections to learn more*:\n\n- `h-`: [Helpers](http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/#component-namespaces-u-), **N.B.**, we use the name **Helpers** instead of **Utility**.\n\n    *Examples:*\n    - `.h-text-small`\n    - `$h-text-small-size`\n    - `_h-text-sizes.scss`\n\n- `t-`: [Themes](http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/#theme-namespaces-t-)\n\n    *Examples:*\n    - `.t-dark`\n    - `$t-dark-background-color`\n    - `_t-dark.scss`\n\n- `s-`: [Scoped](http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/#scope-namespaces-s-)\n\n    *Examples:*\n    - `.s-subtext-alignment`\n    - `$s-subtext-alignment-bottom-spacing`\n    - `_s-subtext-alignment.scss`\n\nAnd the rest:\n\n- `js-`: [JS hooks](#js-hooks)\n- `is-`/`has-`: [State hooks](#state-hooks)\n- `ss-`: [Server-side hooks](#server-side-hooks)\n- `qa-`: [QA hooks](#qa-hooks)\n- `track-`: [Tracking hooks](#tracking-hooks)\n\n##### JS Hooks\n\nRather than rehashing everything about JS hooks let's instead defer to the [JavaScript Hooks](http://cssguidelin.es/#javascript-hooks) section in [Harry Roberts](http://csswizardry.com/) excellent [CSS Guidelines](http://cssguidelin.es/).\n\nJS hooks—and [Server-side](#server-side-hooks), [QA](#qa-hooks), and [Tracking hooks](#tracking-hooks)—should always be scoped to the component it is part off to avoid clashing with other hooks of the same category, and to keep them highly readable—not much different to how we structure our classes for styling.\n\n###### :heavy_multiplication_x: NOT GOOD\n\n- `js-trigger`\n- `js-target`\n- `js-list`\n- `js-close-button`\n\n###### :heavy_check_mark: GOOD\n\n- `js-drop-down-menu-trigger`\n- `js-drop-down-menu-target`\n- `js-drop-down-menu-list`\n- `js-drop-down-menu-close-button`\n\n##### State Hooks\n\nCertain styles are *state* based, for example\n\n- a navigation link may be in an active state;\n- an accordion section may be in an expanded state;\n- a drop down menu may be in a visible state;\n- a third party widget may be in a state where it has finished loading.\n\nStyles that are needed to be applied to an elements state are applied by a class using either the `is-` or `has-` namespace. For example, we could use the following state hooks for the four examples listed above:\n\n- `is-active`\n- `is-expanded`\n- `is-visible`\n- `has-loaded`\n\nJavaScript or server-side logic is typically used to apply state hooks. A classic example is using server-side logic to apply a state hook to highlight the active link in a primary navigation component, the server-side code would append the `.is-active` state hook to the relevant `\u003ca\u003e` element.\n\nTo keep things consistent and to reduce the cognitive load of having to come up with names for state hooks we should try to stick with a set list of common state hook names, something like:\n\n- `is-active`\n- `has-loaded`\n- `is-loading`\n- `is-visible`\n- `is-disabled`\n- `is-expanded`\n- `is-collapsed`\n\nWe can safely use a set list of state hook names because they are always scoped to the selector they are being applied too i.e. we never have to worry about state hook styles clashing with other state hook styles.\n\nWe achieve this by chaining the state hook to the selector it needs to be applied too, for example:\n\n```scss\n.nav-main__link {\n  color: red;\n\n  \u0026.is-active {\n    color: blue;\n  }\n}\n```\n\nWhich compiles too:\n\n```css\n.nav-main__link {\n  color: red;\n}\n\n.nav-main__link.is-active {\n  color: blue;\n}\n```\n\n##### Server-side Hooks\n\nServer-side hooks are classes namespaced with `ss-` that are used to hook into the DOM for the purpose of referencing DOM elements in server-side code, for example: C#.\n\nYou the front end developer will typically not be applying these hooks.\n\n##### QA Hooks\n\nQA hooks are classes namespaced with `qa-` that are used to hook into the DOM for the purpose of applying automated UI tests.\n\nYou the front end developer will typically not be applying these hooks.\n\n##### Tracking Hooks\n\nTracking hooks are classes namespaced with `track-` that are used to hook into the DOM for the purpose of collecting data for analytics.\n\nYou the front end developer will typically not be applying these hooks.\n\n#### Settings\n\n##### Global Settings\n\nGlobal settings—settings defined in the global settings partial (`_settings.scss`)—are namespaced with `g-` (\"g\" stands for \"global\") then followed by the name of the group they are a part of as the first word then after that any sub-groups.\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n$color-error: #dc322f;\n\n$color-success: #859900;\n\n$color-warning: #b58900;\n\n$color-information: #268bd2;\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n$g-color-state-error: #dc322f;\n\n$g-color-state-success: #859900;\n\n$g-color-state-warning: #b58900;\n\n$g-color-state-information: #268bd2;\n```\n\n##### Local Settings\n\nLocal settings—settings defined in your partials outside of the global settings partial (`_settings.scss`) —should start with their relevant [namespace](#namespace), followed by the name of what it belongs too, for example, a component, a helper, etc., followed by what the setting is targeting. The main goal is to make your settings as readable as possible.\n\n###### :heavy_multiplication_x: NOT GOOD\n\n```scss\n/**\n * Settings.\n */\n\n// Colours\n$c-drop-down-menu-background: $g-color-white;\n\n$c-drop-down-menu-color-outline: rgba($g-color-black, 0.19);\n\n$c-link-color: $g-color-grey-rolling-stone;\n\n// Widths and heights\n$c-drop-down-width: 194px;\n\n$drop-down-menu-width-narrow: 170px;\n\n$arrow-width: 13;\n\n$arrow-height: 7;\n\n// Padding\n$c-drop-down-menu-padding-all: 7;\n\n$c-drop-down-menu-link-padding-left-padding-right: 15px;\n\n$c-drop-down-menu-link-padding-top-padding-bottom: 8px;\n```\n\n###### :heavy_check_mark: GOOD\n\n```scss\n/**\n * Settings.\n */\n\n// Colours\n$c-drop-down-menu-background-color: $g-color-white;\n\n$c-drop-down-menu-outline-color: rgba($g-color-black, 0.19);\n\n$c-drop-down-menu-link-color: $g-color-grey-rolling-stone;\n\n// Widths and heights\n$c-drop-down-menu-width: 194px;\n\n$c-drop-down-menu-width-narrow: 170px;\n\n$c-drop-down-menu-arrow-width: 13;\n\n$c-drop-down-menu-arrow-height: 7;\n\n// Padding\n$c-drop-down-menu-padding: 7;\n\n$c-drop-down-menu-link-padding-sides: 15px;\n\n$c-drop-down-menu-link-padding-ends: 8px;\n```\n\n### Sizes And Sides\n\nWe use a naming convention for sizes and for targeting an element's top and bottom, left and right sides, which we use to keep things consistent and to reduce the cognitive load in coming up with our own names.\n\nThe main naming convention for sizes:\n\n- Tiny\n- Small\n- Large\n- Huge\n\nAnd occasionally for something really small or big we use:\n\n- Micro\n- Mega\n\nThe base size is simply *Base*.\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.c-pagination--tiny {\n  padding: rem($c-pagination-padding-tiny);\n}\n\n.c-pagination--small {\n  padding: rem($c-pagination-padding-small);\n}\n\n.c-pagination--large {\n  padding: rem($c-pagination-padding-large);\n}\n\n.c-pagination--huge {\n  padding: rem($c-pagination-padding-huge);\n}\n```\n\nA secondary naming convention for sizes is the `x` pattern where `x` is short for \"extra\".\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.c-pagination--small {\n  padding: rem($c-pagination-padding-small);\n}\n\n.c-pagination--x-small {\n  padding: rem($c-pagination-padding-x-small);\n}\n\n.c-pagination--xx-small {\n  padding: rem($c-pagination-padding-xx-small);\n}\n\n.c-pagination--xxx-small {\n  padding: rem($c-pagination-padding-xxx-small);\n}\n```\n\nThe `x` naming convention is better suited when you have *many* sizes as it scales more sensibly. This pattern is rarely needed and it is probably a good time to reassess your component before implementing.\n\nAnother naming convention we use is *Ends* and *Sides* which are used to target either an element's top and bottom (ends) or its left and right (sides).\n\n###### :heavy_check_mark: GOOD\n\n```scss\n.c-pagination--padding-only-ends {\n  padding-bottom: rem($c-pagination-padding);\n  padding-top: rem($c-pagination-padding);\n}\n\n.c-pagination--padding-only-sides {\n  padding-left: rem($c-pagination-padding);\n  padding-right: rem($c-pagination-padding);\n}\n```\n\n### Containers\n\nThe names we give to classes that act as containers should be *container* e.g. `.l-container`, we shouldn't use *wrap*.\n\nAnd for inner containers we should simply use *inner* e.g. `.c-card__inner`.\n\n\n\n\n## Tooling\n\nMaking it easier to apply our guidelines and to prevent wasting time picking apart nonconforming code in code review (PR's).\n\n### Linting\n\nWe recommend using the excellent [stylelint](http://stylelint.io/) CSS linter.\n\nYou'll be able to create a configuration file that enforces pretty much all of these guidelines. Stand by for such a file.\n\n### EditorConfig\n\nWe use an [EditorConfig](http://editorconfig.org) file which enforces our indenting rules.\n\nThe contents of the `.editorconfig` file should look something like this:\n\n```\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n```\n\n### Text Editor Configuration\n\nYou should configure your text editor to adhere to as much of these guidelines as possible.\n\nAt the bare minimum configure your editor to *show invisibles* or to automatically remove end-of-line whitespace.\n\n#### Sublime Text\n\nIf you use Sublime Text editor then install [this package](https://github.com/SublimeText/TrailingSpaces) and use these settings in your `Settings — User` file which can be found here: `Sublime Text -\u003e Preferences -\u003e Settings — User`:\n\n```json\n\"tab_size\": 4,\n\"translate_tabs_to_spaces\": true,\n\"trim_automatic_white_space\": true,\n\"trim_trailing_white_space_on_save\": true,\n\"word_wrap\": true,\n\"wrap_width\": 80\n```\n\nAlso install [this package](https://sublime.wbond.net/packages/DocBlockr) to make writing DocBlock style comments super easy.\n\n\n\n\n## Writing And Architecturing CSS\n\nAll of the above is about how we structure and form our CSS; they are very quantifiable rules.\n\nFor how to deal with our attitude and approach to writing and architecturing CSS we are yet to document this—it is coming soon so watch this space.\n\nIn the interim we can link to relevant parts of [Harry Roberts](http://csswizardry.com/) excellent [CSS Guidelines](http://cssguidelin.es/):\n\n- [CSS Selectors](http://cssguidelin.es/#css-selectors)\n- [Specificity](http://cssguidelin.es/#specificity)\n- [Architectural Principles](http://cssguidelin.es/#architectural-principles)\n\n### Further Reading\n\n- [SOLID CSS](http://blog.millermedeiros.com/solid-css/)\n- [One Module or Two](http://snook.ca/archives/html_and_css/one-module-or-two)\n- [Our (CSS) Best Practices Are Killing US](http://www.stubbornella.org/content/2011/04/28/our-best-practices-are-killing-us/)\n- [Keep your CSS selectors short](http://csswizardry.com/2012/05/keep-your-css-selectors-short/)\n- [The single responsibility principle applied to CSS](http://csswizardry.com/2012/04/the-single-responsibility-principle-applied-to-css/)\n- [Principles for writing good CSS](http://blog.kaelig.fr/post/38377421139/principles-for-writing-good-css)\n- [DOM Hooks—Smarter ways to target elements in the DOM](http://presentation.chris-pearce.me/DOM-hooks/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchris-pearce%2Fcss-guidelines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchris-pearce%2Fcss-guidelines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchris-pearce%2Fcss-guidelines/lists"}