├── .version ├── CHANGELOG.md └── README.md /.version: -------------------------------------------------------------------------------- 1 | 2.0.0 -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # HEAD 2 | 3 | ## 2.0.0 (September 11, 2016) 4 | 5 | * General typo and code example fixes. 6 | * Removed all smart quotes. 7 | * Remove all references to the [Scally CSS Framework](https://github.com/chris-pearce/scally) as I want these guidelines to not be tied to any particular framework/library. 8 | * Changed the empty line rule that comes _after_: **Commenting -> Partial Heading** to be one (1) empty line not two (2). 9 | * Removed the non-mandatory sections: `@author` and `@created` from: **Commenting -> Partial Heading** as I don't see any value in this convention anymore. It's better to use source control e.g. [Git](https://git-scm.com/) for this information. 10 | * Removed the **Commenting -> BEM Modifier Markers** section as I don't see any value in this convention anymore. It's obvious a selector is a BEM modifier from the two (2) hyphens in its name e.g. `.c-card--compact`—certainly if a BEM modifier isn't obvious from the code alone then go ahead and add some comments but no need to use the "Modifier" marker convention. 11 | * Removed the **Naming Conventions -> Mixins And Functions** section as it was mostly referring to the [Scally CSS Framework](https://github.com/chris-pearce/scally). 12 | * Removed the **Naming Conventions -> Spelling** section so it's scalable to any team worldwide, basically this should be decided upon by the team. 13 | * A few updates to the **Tooling** section. 14 | * PR's addressed: 15 | * https://github.com/chris-pearce/css-guidelines/pull/17 16 | 17 | ## 1.0.0 (January 7, 2015) 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS Guidelines 2 | 3 | 4 | 5 | 6 | ## Contents 7 | 8 | - [Terminology And Conventions Used In These Guidelines](#terminology-and-conventions-used-in-these-guidelines) 9 | - [General Principles](#general-principles) 10 | - [Acknowledgements And Credit](#acknowledgements-and-credit) 11 | - [Syntax And Formatting](#syntax-and-formatting) 12 | - [CSS Ruleset](#css-ruleset) 13 | - [Sass Specifics](#sass-specifics) 14 | - [Declaration Order](#declaration-order) 15 | - [More On Ordering](#more-on-ordering) 16 | - [80 Characters Wide](#80-characters-wide) 17 | - [Meaningful Whitespace](#meaningful-whitespace) 18 | - [Commenting](#commenting) 19 | - [DocBlock-*esque*](#docblock-esque) 20 | - [Partial Heading](#partial-heading) 21 | - [Partial Intro](#partial-intro) 22 | - [Inline Comments](#inline-comments) 23 | - [Number Labelling](#number-labelling) 24 | - [Component-extension Pointers](#component-extension-pointers) 25 | - [Section Comment](#section-comment) 26 | - [Naming Conventions](#naming-conventions) 27 | - [BEM-like Naming](#bem-like-naming) 28 | - [Hyphen-delimited](#hyphen-delimited) 29 | - [Namespace](#namespace) 30 | - [What We Namespace](#what-we-namespace) 31 | - [The Namespaces](#the-namespaces) 32 | - [JS Hooks](#js-hooks) 33 | - [State Hooks](#state-hooks) 34 | - [Server-side Hooks](#server-side-hooks) 35 | - [QA Hooks](#qa-hooks) 36 | - [Tracking Hooks](#tracking-hooks) 37 | - [Settings](#settings) 38 | - [Global Settings](#global-settings) 39 | - [Local Settings](#local-settings) 40 | - [Sizes And Sides](#sizes-and-sides) 41 | - [Tooling](#tooling) 42 | - [Text Editor Configuration](#text-editor-configuration) 43 | - [Sublime Text](#sublime-text) 44 | - [Linting](#linting) 45 | - [EditorConfig](#editorconfig) 46 | - [Writing And Architecturing CSS](#writing-and-architecturing-css) 47 | - [Further Reading](#further-reading) 48 | 49 | 50 | 51 | 52 | ## Terminology And Conventions Used In These Guidelines 53 | 54 | - Sass variable = setting 55 | - An ellipsis (`…`) = a placeholder for code used in a code example block 56 | - Written for a team 57 | 58 | 59 | 60 | 61 | ## General Principles 62 | 63 | > "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/) 64 | 65 | In 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— 66 | 67 | - keep stylesheets maintainable; 68 | - keep code transparent, sane, consistent, and readable; 69 | - keep stylesheets scalable. 70 | 71 | No matter the document, we must always try and keep a common formatting. This 72 | means: 73 | 74 | - [consistent syntax](#syntax-and-formatting); 75 | - [consistent and meaningful commenting](#commenting); 76 | - and [consistent naming](#naming-conventions). 77 | 78 | All 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. 79 | 80 | ### Acknowledgements And Credit 81 | 82 | We'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: 83 | 84 | - [Sass Guidelines](http://sass-guidelin.es/) 85 | - [Idiomatic CSS](https://github.com/necolas/idiomatic-css) 86 | 87 | 88 | 89 | 90 | ## Syntax And Formatting 91 | 92 | Starting right at the top, we want 93 | 94 | - four (4) space indents, no tabs; 95 | - [80 character wide](#80-characters-wide) columns; 96 | - multi-line CSS; 97 | - [meaningful use of whitespace](#meaningful-whitespace). 98 | 99 | **N.B.** our [Tooling](#tooling) will automate and enforce most of our syntax and formatting rules. 100 | 101 | ### CSS Ruleset 102 | 103 | For your reference here is an anatomy of a CSS ruleset: 104 | 105 | ``` 106 | [selector] { 107 | [property]: [value]; 108 | [<- Declaration ->] 109 | } 110 | ``` 111 | 112 | Our chosen format for how CSS rulesets should be written 113 | 114 | - each selector on its own new line; 115 | - a space before the opening brace (`{`); 116 | - the opening brace (`{`) on the same line as the last selector; 117 | - a space after the colon (`:`); 118 | - each declaration on its own new line; 119 | - each declaration indented by four (4) spaces; 120 | - a trailing semi-colon (`;`) at the end of all declarations; 121 | - the closing brace (`}`) on its own new line; 122 | - 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; 123 | 124 | ###### :heavy_multiplication_x: NOT GOOD 125 | 126 | ```scss 127 | // Not having each selector on its own line 128 | .selector-1, .selector-2 129 | // Not having the opening brace (`{`) on the same line as the last selector 130 | { 131 | // Not having each declaration on its own line 132 | background-color: $color-brand; background-image: linear-gradient($color-white, $color-grey-mercury), linear-gradient($color-black, $color-grey-alabaster); 133 | // Not using new lines for the comma-separated property values and not 134 | // indenting all the values at the same level as the first 135 | box-shadow: 1px 1px 1px $color-black, 2px 2px 1px 1px $color-grey-mercury inset; 136 | // Not using a space after the colon (`:`) 137 | color:$color-text-base; 138 | // Not indenting a declaration with four (4) spaces 139 | display: block; 140 | // Not using a trailing semi-colon (`;`) at the end of the declaration 141 | // and not having the closing brace (`}`) on its own new line 142 | padding: rem($spacing-base) } 143 | ``` 144 | 145 | ###### :heavy_check_mark: GOOD 146 | 147 | ```scss 148 | .selector-1, 149 | .selector-2 { 150 | background-color: $color-brand; 151 | background-image: linear-gradient($color-white, $color-grey-mercury), 152 | linear-gradient($color-black, $color-grey-alabaster); 153 | box-shadow: 1px 1px 1px $color-black, 154 | 2px 2px 1px 1px $color-grey-mercury inset; 155 | color: $color-text-base; 156 | display: block; 157 | padding: rem($spacing-base); 158 | } 159 | ``` 160 | 161 | Adding to the above, we also want to pay attention to 162 | 163 | - use lowercase and preferably the shorthand version for all hexadecimal units—if you wish to use the longhand version then this is fine; 164 | - 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; 165 | - use single quotes for strings, `url()` values, etc; 166 | - wrap attribute selector values in double quotes; 167 | - include a space after each comma in comma-separated values; 168 | - parentheses should not be padded with spaces; 169 | - when a decimal mark is needed always include the zero; 170 | - use double colons (`::`) for pseudo elements; 171 | - 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; 172 | - use the `px` unit for fixed-sized things—this is rare nowadays as we're building responsive layouts—and for the following CSS properties: 173 | - `border-radius` 174 | - `border` 175 | - `box-shadow` 176 | - `text-shadow` 177 | 178 | ###### :heavy_multiplication_x: NOT GOOD 179 | 180 | ```scss 181 | .selector { 182 | // Not using single quotes around the `url()` value 183 | background-image: url(/path/to/image); 184 | // Not using lowercase for the hexidecimal unit 185 | color: #EEEEEE; 186 | // Not using spaces after each comma in the `rgba` value and padding the 187 | // parentheses with spaces 188 | color: rgba( 0,0,0,0.8 ); 189 | // Not including a zero before the decimal mark 190 | font-size: .98rem; 191 | // Not using shorthand for the property value 192 | padding: rem(12) rem(12) rem(12) rem(12); 193 | // Declaring zero-values due to shorthand property being used and not 194 | // removing the unit from a zero-value 195 | margin: 0rem rem(6); 196 | 197 | // Not using the double colon format 198 | &:before { 199 | // Not using shorthand for the property (should be `background-color`) 200 | background: $color-black; 201 | // Not using single quotes around the `content` string 202 | content: "✌"; 203 | } 204 | 205 | // Not using double quotes around the attribute selector value 206 | &[type=text] { 207 | … 208 | } 209 | } 210 | ``` 211 | 212 | ###### :heavy_check_mark: GOOD 213 | 214 | ```scss 215 | .selector-1 { 216 | background-image: url('/path/to/image'); 217 | color: #eee; 218 | color: rgba(0, 0, 0, 0.8); 219 | font-size: 0.98rem; 220 | padding: rem(12); 221 | margin-left: rem(6); 222 | margin-right: rem(6); 223 | 224 | &::before { 225 | background-color: $color-black; 226 | content: '✌'; 227 | } 228 | 229 | &[type="text"] { 230 | … 231 | } 232 | } 233 | ``` 234 | 235 | To 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. 236 | 237 | A 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: 238 | 239 | ```scss 240 | background-image: initial; 241 | background-position-x: initial; 242 | background-position-y: initial; 243 | background-size: initial; 244 | background-repeat-x: initial; 245 | background-repeat-y: initial; 246 | background-attachment: initial; 247 | background-origin: initial; 248 | background-clip: initial; 249 | background-color: transparent; 250 | ``` 251 | 252 | *Phew!* 253 | 254 | ### Sass Specifics 255 | 256 | Syntax and formatting rules specifically for Sass code 257 | 258 | - only use the parent selector reference (`&`) for these use cases 259 | - appending it to pseudo classes; 260 | - appending it to pseudo elements; 261 | - appending it to [State hooks](#state-hooks) in order to chain it to the selector it's referencing; 262 | - referencing itself when combined with any of the above to avoid duplicating CSS properties; 263 | - only use silent placeholder selectors with the `@extend` directive, however, we'd rather avoid `@extend` as much as possible; 264 | - avoid selector nesting, if you have to nest then limit it to one level deep; 265 | - when adding a unit to a number stored in a setting, you have to multiply the number by 1 unit; 266 | - 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; 267 | - always use colour settings for `rgb` values; 268 | - avoid writing parentheses for argument-less mixins; 269 | - all Sass functions and mixins to use the [SassDoc](http://sassdoc.com/) documentation guidelines; 270 | - for conditional statements: 271 | - no parentheses unless they are necessary; 272 | - always an empty new line before `@if`; 273 | - `@else` statements on the same line as previous closing brace (`}`); 274 | - always an empty new line after the last closing brace (`}`) unless the next line is a closing brace (`}`); 275 | 276 | ###### :heavy_multiplication_x: NOT GOOD 277 | 278 | ```scss 279 | .selector { 280 | // Extending a class selector 281 | @extend .selector; 282 | // Including parentheses for an argument-less mixin 283 | @include h-text-truncate(); 284 | // Not using colour settings 285 | background-color: rgba(0, 0, 0, 0.5); 286 | color: #eee; 287 | // Not multiplying the unit to a number stored in a setting 288 | padding: $padding-setting + rem; 289 | 290 | // Using the parent selector (`&`) to chain to the selector it's 291 | // referencing when it is not a State hook 292 | &.selector--modifier { 293 | … 294 | } 295 | 296 | // Using the parent selector (`&`) to target a class that is applied at a 297 | // higher level in the DOM 298 | .parent-selector & { 299 | … 300 | } 301 | 302 | // Nesting selectors more than one level deep 303 | .nested__selector .nested__selector { 304 | … 305 | } 306 | } 307 | 308 | // An incorrectly formatted conditional statement 309 | @if ($support-legacy == true) { 310 | … 311 | } 312 | @else { 313 | … 314 | } 315 | 316 | // Not using SassDoc documentation guidelines 317 | @function strip-unit($number) { 318 | @if type-of($number) == "number" and not unitless($number) { 319 | @return $number / ($number * 0 + 1); 320 | } 321 | @return $number; 322 | } 323 | ``` 324 | 325 | ###### :heavy_check_mark: GOOD 326 | 327 | ```scss 328 | .selector { 329 | @extend %selector; 330 | @include h-text-truncate; 331 | background-color: rgba($color-black, 0.5); 332 | color: $color-text-base; 333 | padding: $padding-setting * 1rem; 334 | } 335 | 336 | .selector--modifier { 337 | … 338 | } 339 | 340 | .parent-selector .selector { 341 | … 342 | } 343 | 344 | .nested__selector { 345 | … 346 | } 347 | 348 | @if $support-legacy { 349 | … 350 | } @else { 351 | … 352 | } 353 | 354 | /// Remove a unit from a number. 355 | /// 356 | /// @author Chris Pearce 357 | /// 358 | /// @access private 359 | /// 360 | /// @param {Number [unit]} $number — Number to remove unit from 361 | /// 362 | /// @returns {Number} 363 | /// 364 | /// @todo Add @exception rules, see: https://gist.github.com/terkel/4373420 365 | /// 366 | /// @example scss - Usage 367 | /// strip-unit(24px) 368 | /// strip-unit(2.3em) 369 | 370 | @function strip-unit($number) { 371 | @if type-of($number) == "number" and not unitless($number) { 372 | @return $number / ($number * 0 + 1); 373 | } 374 | @return $number; 375 | } 376 | 377 | // Correct use of the parent selector reference (`&`) 378 | .selector { 379 | … 380 | 381 | &, 382 | &:hover, 383 | &:focus { 384 | color: $color-text-base; 385 | } 386 | 387 | &:hover, 388 | &:focus { 389 | … 390 | } 391 | 392 | &::before { 393 | … 394 | } 395 | 396 | &.is-active { 397 | … 398 | } 399 | } 400 | ``` 401 | 402 | ### Declaration Order 403 | 404 | Properties should be ordered alphabetically, that's it. 405 | 406 | ###### :heavy_multiplication_x: NOT GOOD 407 | 408 | ```scss 409 | .selector { 410 | display: inline-block; 411 | padding-right: rem(10); 412 | padding-left: rem(10); 413 | position: absolute; 414 | top: 0; 415 | bottom: 0; 416 | left: 0; 417 | right: 0; 418 | z-index: 10; 419 | } 420 | ``` 421 | 422 | ###### :heavy_check_mark: GOOD 423 | 424 | ```scss 425 | .selector { 426 | bottom: 0; 427 | display: inline-block; 428 | left: 0; 429 | padding-left: rem(10); 430 | padding-right: rem(10); 431 | position: absolute; 432 | right: 0; 433 | top: 0; 434 | z-index: 10; 435 | } 436 | ``` 437 | 438 | ### More On Ordering 439 | 440 | Because 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 441 | 442 | 1. extend calls (`@extend`); 443 | 2. mixin calls (`@include`) *with no* `@content`; 444 | 3. declarations; 445 | 4. pseudo classes—combining [State hooks](#state-hooks) here is fine; 446 | 5. pseudo elements; 447 | 5. mixin calls (`@include`) *with* `@content`—mainly being media queries; 448 | 6. nested selectors, limit to one level deep or best to avoid in most cases; 449 | 450 | ###### :heavy_multiplication_x: NOT GOOD 451 | 452 | ```scss 453 | .selector { 454 | // Declarations should not come first and should all be grouped together 455 | bottom: 0; 456 | display: inline-block; 457 | left: 0; 458 | position: absolute; 459 | right: 0; 460 | // Mixin calls should come after extend calls and not mixed in with 461 | // declarations 462 | @include hidpi-bg-img('path/to/image/image.png', 32px); 463 | top: 0; 464 | z-index: 10; 465 | // Extend calls should come first 466 | @extend %some-silent-placeholder-selector; 467 | 468 | // Pseudo elements should not come before pseudo classes 469 | &::before { 470 | … 471 | } 472 | 473 | &:hover, 474 | &:focus, 475 | &.is-active { 476 | … 477 | } 478 | 479 | // Nested selector should come last 480 | .nested-selector { 481 | … 482 | } 483 | 484 | @media (min-width: bp(lap)) { 485 | … 486 | } 487 | } 488 | ``` 489 | 490 | ###### :heavy_check_mark: GOOD 491 | 492 | ```scss 493 | .selector { 494 | @extend %some-silent-placeholder-selector; 495 | @include hidpi-bg-img('path/to/image/image.png', 32px); 496 | bottom: 0; 497 | display: inline-block; 498 | left: 0; 499 | position: absolute; 500 | right: 0; 501 | top: 0; 502 | z-index: 10; 503 | 504 | &:hover, 505 | &:focus, 506 | &.is-active { 507 | … 508 | } 509 | 510 | &::before { 511 | … 512 | } 513 | 514 | @media (min-width: bp(lap)) { 515 | … 516 | } 517 | 518 | .nested-selector { 519 | … 520 | } 521 | } 522 | ``` 523 | 524 | ### 80 Characters Wide 525 | 526 | Where possible, limit CSS files' width to 80 characters. Reasons for this include 527 | 528 | - the ability to have multiple files open side by side; 529 | - viewing CSS on sites like GitHub, or in terminal windows; 530 | - providing a comfortable line length for comments. 531 | 532 | There will be unavoidable exceptions to this rule—such as URLs, or gradient syntax—which shouldn't be worried about. 533 | 534 | ### Meaningful Whitespace 535 | 536 | Whitespace is free, use it liberally and judiciously as it greatly improves the readability of our CSS. 537 | 538 | We 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. 539 | 540 | Four (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. 541 | 542 | ###### :heavy_multiplication_x: NOT GOOD 543 | 544 | ```scss 545 | /* ============================================================================ 546 | COMPONENTS -> SEARCH INPUT 547 | ========================================================================= */ 548 | /** 549 | * A component for the most common type of search input which has deep rounded 550 | * corners, shadows, and a background image of a magnifying glass icon 551 | * positioned to the left or right side. Visit: /subscribers/ to see an 552 | * example. 553 | * @markup 554 |
555 | 556 | 557 | 558 |
559 | */ 560 | 561 | /** 562 | * Settings. 563 | */ 564 | 565 | $c-search-input-padding-top: 5; 566 | $c-search-input-padding-bottom: $c-search-input-padding-top + 1; 567 | 568 | .c-search-input { 569 | position: relative; 570 | } 571 | 572 | 573 | 574 | 575 | /** 576 | * The input. 577 | */ 578 | .c-search-input__input { 579 | border: 1px solid $color-grey-alto-4; 580 | box-shadow: $input-box-shadow; 581 | color: $color-grey-tundora; 582 | padding: rem($c-search-input-padding-top); 583 | padding-bottom: rem($c-search-input-padding-bottom); 584 | transition: $input-transition; 585 | &:focus { 586 | border-color: $color-blue-pigeon-post; 587 | box-shadow: $input-box-shadow-focus; 588 | // Can remove this as we're providing a good custom outline 589 | outline: none; 590 | } 591 | } 592 | /** 593 | * The magnify icon. 594 | */ 595 | 596 | .c-search-input__icon { 597 | background: url('/img/icons/icon-small/search.png') no-repeat; 598 | height: $c-search-input-icon-size; 599 | left: $c-search-input-icon-position-left; 600 | width: $c-search-input-icon-size; 601 | } 602 | /** 603 | * Modifier: when icon is positioned on the right side. 604 | */ 605 | .c-search-input--icon-right .c-search-input__icon { 606 | left: auto; 607 | right: $c-search-input-icon-position-left; 608 | } 609 | ``` 610 | 611 | ###### :heavy_check_mark: GOOD 612 | 613 | ```scss 614 | /* ============================================================================ 615 | COMPONENTS -> SEARCH INPUT 616 | ========================================================================= */ 617 | 618 | /** 619 | * A component for the most common type of search input which has deep rounded 620 | * corners, shadows, and a background image of a magnifying glass icon 621 | * positioned to the left or right side. Visit: /subscribers/ to see an 622 | * example. 623 | * 624 | * @markup 625 |
626 | 627 | 628 | 629 |
630 | */ 631 | 632 | 633 | /** 634 | * Settings. 635 | */ 636 | 637 | $c-search-input-padding-top: 5; 638 | 639 | $c-search-input-padding-bottom: $c-search-input-padding-top + 1; 640 | 641 | 642 | .c-search-input { 643 | position: relative; 644 | } 645 | 646 | 647 | /** 648 | * The input. 649 | */ 650 | 651 | .c-search-input__input { 652 | border: 1px solid $color-grey-alto-4; 653 | box-shadow: $input-box-shadow; 654 | color: $color-grey-tundora; 655 | padding: rem($c-search-input-padding-top); 656 | padding-bottom: rem($c-search-input-padding-bottom); 657 | transition: $input-transition; 658 | 659 | &:focus { 660 | border-color: $color-blue-pigeon-post; 661 | box-shadow: $input-box-shadow-focus; 662 | // Can remove this as we're providing a good custom outline 663 | outline: none; 664 | } 665 | } 666 | 667 | 668 | /** 669 | * The magnify icon. 670 | */ 671 | 672 | .c-search-input__icon { 673 | background: url('/img/icons/icon-small/search.png') no-repeat; 674 | height: $c-search-input-icon-size; 675 | left: $c-search-input-icon-position-left; 676 | width: $c-search-input-icon-size; 677 | } 678 | 679 | 680 | /** 681 | * Modifier: when icon is positioned on the right side. 682 | */ 683 | 684 | .c-search-input--icon-right .c-search-input__icon { 685 | left: auto; 686 | right: $c-search-input-icon-position-left; 687 | } 688 | ``` 689 | 690 | 691 | 692 | 693 | ## Commenting 694 | 695 | Well 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. 696 | 697 | We want to be using a comment style that is simple and consistent. 698 | 699 | Starting right at the top, we want 700 | 701 | - to place comments on a new line above their subject; 702 | - to keep line-length to a sensible maximum: [80 columns](#80-characters-wide); 703 | - to make liberal use of comments to break CSS code into discrete sections; 704 | - to use 'sentence case' comments and consistent text indentation. 705 | 706 | ### DocBlock-*esque* 707 | 708 | The 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. 709 | 710 | ###### :heavy_check_mark: GOOD 711 | 712 | ```scss 713 | /** 714 | * A component for the most common type of search input which has deep rounded 715 | * corners, shadows, and a background image of a magnifying glass icon 716 | * positioned to the left or right side. Visit: /subscribers/ to see an 717 | * example. 718 | * 719 | * @markup 720 |
721 | 722 | 723 | 724 |
725 | */ 726 | ``` 727 | 728 | We 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. 729 | 730 | ###### :heavy_check_mark: GOOD 731 | 732 | ```scss 733 | /** 734 | * The underlay which is the wrapper of the modal dialog which uses Flexbox 735 | * to position the modal dialog smack in the middle of the viewport, 736 | * includes a fall-back for non-supporting Flexbox browsers. 737 | */ 738 | 739 | .c-modal-dialog-underlay { 740 | … 741 | } 742 | 743 | /** 744 | * Fall-back for non-supporting Flexbox browsers, using the Modernizr 745 | * feature detection technique via the `:not` CSS selector to get around 746 | * any lag of the Modernizr JS loading. 747 | */ 748 | 749 | html:not(.flexbox) .c-modal-dialog-underlay { 750 | … 751 | } 752 | ``` 753 | 754 | ### Partial Heading 755 | 756 | Every partial needs a partial heading type comment at the very top of the file. 757 | 758 | ###### :heavy_check_mark: GOOD 759 | 760 | ```scss 761 | /* ============================================================================ 762 | CORE -> MIXINS -> CONVERT PX TO EM/REM 763 | ========================================================================= */ 764 | // [empty line] 765 | ``` 766 | 767 | Breaking this down we have 768 | 769 | - uppercase for text; 770 | - a breadcrumb pattern showing where the partial belongs in the CSS architecture, the last part being the same name as the partial filename; 771 | - one (1) empty line to come after. 772 | 773 | ### Partial Intro 774 | 775 | A partial intro type comment follows a [Partial Heading](#partial-heading) type comment, think of this like a books Prologue/Preface/Introduction. 776 | 777 | It should be structured like this 778 | 779 | - a description—be as detailed as you can here; 780 | - any attention grabbing comments prefix with **N.B.**; 781 | - mandatory sections prefixed with `@` 782 | - `@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; 783 | - `@demo`: if applicable any URL(s) to demonstration(s); 784 | - `@credit`: if applicable any URL(s) to credit where any ideas came from; 785 | - non-mandatory sections prefixed with `@` 786 | - `@todo`: any outstanding tasks; 787 | - `@consideration`: any things to consider; 788 | - One (1) empty line between each of the above sections and two (2) empty lines coming after the intro. 789 | 790 | ###### :heavy_check_mark: GOOD 791 | 792 | ```scss 793 | /** 794 | * A generic drop down helper powered by some JavaScript which toggles a 795 | * class e.g. `is-visible` on the drop down trigger (the button that makes the 796 | * drop down visible and invisible) and the target (the actual drop down). 797 | * This class will be used to make the drop down target visible when the 798 | * trigger is selected. There is also a version for showing the drop down via 799 | * the `:hover` pseudo class which is turned off for touch devices. 800 | * 801 | * N.B. this helper is dependent on the "Align" helper. 802 | * 803 | * @credit 804 | * http://www.stubbornella.org/content/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code 805 | * 806 | * @markup 807 |
808 | 809 | 810 | 811 |
[child elements]
812 |
813 | */ 814 | // [empty line] 815 | // [empty line] 816 | ``` 817 | 818 | In 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. 819 | 820 | ### Inline Comments 821 | 822 | Sass allows us to use less verbose CSS comments prefixed with two forward slashes. 823 | 824 | This 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. 825 | 826 | These comments should always be above their subject with a space coming after the two forward slashes. 827 | 828 | ###### :heavy_check_mark: GOOD 829 | 830 | ```scss 831 | /** 832 | * Settings. 833 | */ 834 | 835 | // Colours 836 | $c-pagination-background-color: #000; 837 | 838 | $c-pagination-foreground-color: #333; 839 | 840 | // Padding 841 | $c-pagination-padding-left: $spacing-base; 842 | 843 | $c-pagination-padding-right: $spacing-half; 844 | 845 | 846 | h1 { 847 | font-size: rem($font-size-heading-1); 848 | // This is needed to turn off the top margin set in normalize.css 849 | margin-top: 0; 850 | // This is needed to fix a stupid bug in IE 9 ಠ╭╮ಠ 851 | width: 100%; 852 | } 853 | ``` 854 | 855 | ### Number Labelling 856 | 857 | A number labelling type comment is used when [Inline Comments](#inline-comments) would need to be repeated. 858 | 859 | **N.B.** this is the only time when comments—the numbers—don't need to be on a new line above their subject. 860 | 861 | ###### :heavy_multiplication_x: NOT GOOD 862 | 863 | ```scss 864 | img { 865 | // Make responsive 866 | max-width: 100%; 867 | // Make responsive 868 | height: auto; 869 | // So that `alt` text is visually offset if images don't load 870 | font-style: italic; 871 | } 872 | ``` 873 | 874 | ###### :heavy_check_mark: GOOD 875 | 876 | ```scss 877 | /** 878 | * Images. 879 | * 880 | * 1. Make responsive. 881 | * 2. So that `alt` text is visually offset if images don't load. 882 | */ 883 | 884 | img { 885 | max-width: 100%; // [1] 886 | height: auto; // [1] 887 | font-style: italic; // [2] 888 | } 889 | ``` 890 | 891 | ### Component-extension Pointers 892 | 893 | Sometimes 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. 894 | 895 | *Make sure that this type of treatment is needed and that its not just a [BEM](#bem-like-naming) Modifier of your component.* 896 | 897 | When 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. 898 | 899 | ###### :heavy_check_mark: GOOD 900 | 901 | ```scss 902 | /** 903 | * Extend `.c-button` in Components -> Button. 904 | */ 905 | 906 | .c-search .c-button { 907 | … 908 | } 909 | ``` 910 | 911 | ### Section Comment 912 | 913 | When we have really long stylesheets we need a comment that stands out more than a [DocBlock*-esque*](#docblock-esque) type comment. 914 | 915 | This 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. 916 | 917 | ###### :heavy_check_mark: GOOD 918 | 919 | ```scss 920 | /* Some section 921 | ========================================================================= */ 922 | 923 | … 924 | // [empty line] 925 | // [empty line] 926 | // [empty line] 927 | // [empty line] 928 | /* Some section 929 | ========================================================================= */ 930 | ``` 931 | 932 | 933 | 934 | 935 | ## Naming Conventions 936 | 937 | We 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. 938 | 939 | Starting right at the top, we use 940 | 941 | - lowercase; 942 | - [BEM-like naming](#bem-like-naming) for most classes; 943 | - [hyphen-delimited](#hyphen-delimited) for everything else; 944 | - [namespaces](#namespace) for almost everything. 945 | 946 | We don't want 947 | 948 | - CamelCase; 949 | - underscores with the exception of being used in BEM *Element* selectors; 950 | - `id`s, **never**. 951 | 952 | ### BEM-like Naming 953 | 954 | We 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. 955 | 956 | So rather than rehashing everything about BEM please read the above resources. 957 | 958 | ### Hyphen-delimited 959 | 960 | We use hyphen-delimited for: 961 | 962 | - Settings 963 | - Mixins 964 | - Functions 965 | - Animation names 966 | - Filenames 967 | - [State hooks](#state-hooks) 968 | - [JS hooks](#js-hooks) 969 | - [Server-side hooks](#server-side-hooks) 970 | - [QA hooks](#qa-hooks) 971 | - [Tracking hooks](#tracking-hooks) 972 | 973 | ### Namespace 974 | 975 | Mostly everything in our CSS is namespaced so that our CSS is as transparent and self-documenting as possible. 976 | 977 | #### What We Namespace 978 | 979 | - Classes 980 | - Settings 981 | - Mixins 982 | - Functions 983 | - Filenames 984 | 985 | They are all prefixed with a letter followed by a hyphen. 986 | 987 | #### The Namespaces 988 | 989 | - `l-`: **Layout Modules** ([read more here](https://github.com/chris-pearce/scally/blob/master/layout/README.md)) 990 | 991 | *Examples:* 992 | - `.l-grid` 993 | - `$l-grid-gutter` 994 | - `_l-grid.scss` 995 | 996 | - `c-`: **Components** ([read more here](https://github.com/chris-pearce/scally/blob/master/components/README.md)) 997 | 998 | *Examples:* 999 | - `.c-button` 1000 | - `$c-button-foreground-color` 1001 | - `_c-button.scss` 1002 | 1003 | Taken 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*: 1004 | 1005 | - `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**. 1006 | 1007 | *Examples:* 1008 | - `.h-text-small` 1009 | - `$h-text-small-size` 1010 | - `_h-text-sizes.scss` 1011 | 1012 | - `t-`: [Themes](http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/#theme-namespaces-t-) 1013 | 1014 | *Examples:* 1015 | - `.t-dark` 1016 | - `$t-dark-background-color` 1017 | - `_t-dark.scss` 1018 | 1019 | - `s-`: [Scoped](http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/#scope-namespaces-s-) 1020 | 1021 | *Examples:* 1022 | - `.s-subtext-alignment` 1023 | - `$s-subtext-alignment-bottom-spacing` 1024 | - `_s-subtext-alignment.scss` 1025 | 1026 | And the rest: 1027 | 1028 | - `js-`: [JS hooks](#js-hooks) 1029 | - `is-`/`has-`: [State hooks](#state-hooks) 1030 | - `ss-`: [Server-side hooks](#server-side-hooks) 1031 | - `qa-`: [QA hooks](#qa-hooks) 1032 | - `track-`: [Tracking hooks](#tracking-hooks) 1033 | 1034 | ##### JS Hooks 1035 | 1036 | Rather 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/). 1037 | 1038 | JS 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. 1039 | 1040 | ###### :heavy_multiplication_x: NOT GOOD 1041 | 1042 | - `js-trigger` 1043 | - `js-target` 1044 | - `js-list` 1045 | - `js-close-button` 1046 | 1047 | ###### :heavy_check_mark: GOOD 1048 | 1049 | - `js-drop-down-menu-trigger` 1050 | - `js-drop-down-menu-target` 1051 | - `js-drop-down-menu-list` 1052 | - `js-drop-down-menu-close-button` 1053 | 1054 | ##### State Hooks 1055 | 1056 | Certain styles are *state* based, for example 1057 | 1058 | - a navigation link may be in an active state; 1059 | - an accordion section may be in an expanded state; 1060 | - a drop down menu may be in a visible state; 1061 | - a third party widget may be in a state where it has finished loading. 1062 | 1063 | Styles 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: 1064 | 1065 | - `is-active` 1066 | - `is-expanded` 1067 | - `is-visible` 1068 | - `has-loaded` 1069 | 1070 | JavaScript 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 `` element. 1071 | 1072 | To 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: 1073 | 1074 | - `is-active` 1075 | - `has-loaded` 1076 | - `is-loading` 1077 | - `is-visible` 1078 | - `is-disabled` 1079 | - `is-expanded` 1080 | - `is-collapsed` 1081 | 1082 | We 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. 1083 | 1084 | We achieve this by chaining the state hook to the selector it needs to be applied too, for example: 1085 | 1086 | ```scss 1087 | .nav-main__link { 1088 | color: red; 1089 | 1090 | &.is-active { 1091 | color: blue; 1092 | } 1093 | } 1094 | ``` 1095 | 1096 | Which compiles too: 1097 | 1098 | ```css 1099 | .nav-main__link { 1100 | color: red; 1101 | } 1102 | 1103 | .nav-main__link.is-active { 1104 | color: blue; 1105 | } 1106 | ``` 1107 | 1108 | ##### Server-side Hooks 1109 | 1110 | Server-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#. 1111 | 1112 | You the front end developer will typically not be applying these hooks. 1113 | 1114 | ##### QA Hooks 1115 | 1116 | QA hooks are classes namespaced with `qa-` that are used to hook into the DOM for the purpose of applying automated UI tests. 1117 | 1118 | You the front end developer will typically not be applying these hooks. 1119 | 1120 | ##### Tracking Hooks 1121 | 1122 | Tracking hooks are classes namespaced with `track-` that are used to hook into the DOM for the purpose of collecting data for analytics. 1123 | 1124 | You the front end developer will typically not be applying these hooks. 1125 | 1126 | #### Settings 1127 | 1128 | ##### Global Settings 1129 | 1130 | Global 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. 1131 | 1132 | ###### :heavy_multiplication_x: NOT GOOD 1133 | 1134 | ```scss 1135 | $color-error: #dc322f; 1136 | 1137 | $color-success: #859900; 1138 | 1139 | $color-warning: #b58900; 1140 | 1141 | $color-information: #268bd2; 1142 | ``` 1143 | 1144 | ###### :heavy_check_mark: GOOD 1145 | 1146 | ```scss 1147 | $g-color-state-error: #dc322f; 1148 | 1149 | $g-color-state-success: #859900; 1150 | 1151 | $g-color-state-warning: #b58900; 1152 | 1153 | $g-color-state-information: #268bd2; 1154 | ``` 1155 | 1156 | ##### Local Settings 1157 | 1158 | Local 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. 1159 | 1160 | ###### :heavy_multiplication_x: NOT GOOD 1161 | 1162 | ```scss 1163 | /** 1164 | * Settings. 1165 | */ 1166 | 1167 | // Colours 1168 | $c-drop-down-menu-background: $g-color-white; 1169 | 1170 | $c-drop-down-menu-color-outline: rgba($g-color-black, 0.19); 1171 | 1172 | $c-link-color: $g-color-grey-rolling-stone; 1173 | 1174 | // Widths and heights 1175 | $c-drop-down-width: 194px; 1176 | 1177 | $drop-down-menu-width-narrow: 170px; 1178 | 1179 | $arrow-width: 13; 1180 | 1181 | $arrow-height: 7; 1182 | 1183 | // Padding 1184 | $c-drop-down-menu-padding-all: 7; 1185 | 1186 | $c-drop-down-menu-link-padding-left-padding-right: 15px; 1187 | 1188 | $c-drop-down-menu-link-padding-top-padding-bottom: 8px; 1189 | ``` 1190 | 1191 | ###### :heavy_check_mark: GOOD 1192 | 1193 | ```scss 1194 | /** 1195 | * Settings. 1196 | */ 1197 | 1198 | // Colours 1199 | $c-drop-down-menu-background-color: $g-color-white; 1200 | 1201 | $c-drop-down-menu-outline-color: rgba($g-color-black, 0.19); 1202 | 1203 | $c-drop-down-menu-link-color: $g-color-grey-rolling-stone; 1204 | 1205 | // Widths and heights 1206 | $c-drop-down-menu-width: 194px; 1207 | 1208 | $c-drop-down-menu-width-narrow: 170px; 1209 | 1210 | $c-drop-down-menu-arrow-width: 13; 1211 | 1212 | $c-drop-down-menu-arrow-height: 7; 1213 | 1214 | // Padding 1215 | $c-drop-down-menu-padding: 7; 1216 | 1217 | $c-drop-down-menu-link-padding-sides: 15px; 1218 | 1219 | $c-drop-down-menu-link-padding-ends: 8px; 1220 | ``` 1221 | 1222 | ### Sizes And Sides 1223 | 1224 | We 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. 1225 | 1226 | The main naming convention for sizes: 1227 | 1228 | - Tiny 1229 | - Small 1230 | - Large 1231 | - Huge 1232 | 1233 | And occasionally for something really small or big we use: 1234 | 1235 | - Micro 1236 | - Mega 1237 | 1238 | The base size is simply *Base*. 1239 | 1240 | ###### :heavy_check_mark: GOOD 1241 | 1242 | ```scss 1243 | .c-pagination--tiny { 1244 | padding: rem($c-pagination-padding-tiny); 1245 | } 1246 | 1247 | .c-pagination--small { 1248 | padding: rem($c-pagination-padding-small); 1249 | } 1250 | 1251 | .c-pagination--large { 1252 | padding: rem($c-pagination-padding-large); 1253 | } 1254 | 1255 | .c-pagination--huge { 1256 | padding: rem($c-pagination-padding-huge); 1257 | } 1258 | ``` 1259 | 1260 | A secondary naming convention for sizes is the `x` pattern where `x` is short for "extra". 1261 | 1262 | ###### :heavy_check_mark: GOOD 1263 | 1264 | ```scss 1265 | .c-pagination--small { 1266 | padding: rem($c-pagination-padding-small); 1267 | } 1268 | 1269 | .c-pagination--x-small { 1270 | padding: rem($c-pagination-padding-x-small); 1271 | } 1272 | 1273 | .c-pagination--xx-small { 1274 | padding: rem($c-pagination-padding-xx-small); 1275 | } 1276 | 1277 | .c-pagination--xxx-small { 1278 | padding: rem($c-pagination-padding-xxx-small); 1279 | } 1280 | ``` 1281 | 1282 | The `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. 1283 | 1284 | Another 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). 1285 | 1286 | ###### :heavy_check_mark: GOOD 1287 | 1288 | ```scss 1289 | .c-pagination--padding-only-ends { 1290 | padding-bottom: rem($c-pagination-padding); 1291 | padding-top: rem($c-pagination-padding); 1292 | } 1293 | 1294 | .c-pagination--padding-only-sides { 1295 | padding-left: rem($c-pagination-padding); 1296 | padding-right: rem($c-pagination-padding); 1297 | } 1298 | ``` 1299 | 1300 | ### Containers 1301 | 1302 | The names we give to classes that act as containers should be *container* e.g. `.l-container`, we shouldn't use *wrap*. 1303 | 1304 | And for inner containers we should simply use *inner* e.g. `.c-card__inner`. 1305 | 1306 | 1307 | 1308 | 1309 | ## Tooling 1310 | 1311 | Making it easier to apply our guidelines and to prevent wasting time picking apart nonconforming code in code review (PR's). 1312 | 1313 | ### Linting 1314 | 1315 | We recommend using the excellent [stylelint](http://stylelint.io/) CSS linter. 1316 | 1317 | You'll be able to create a configuration file that enforces pretty much all of these guidelines. Stand by for such a file. 1318 | 1319 | ### EditorConfig 1320 | 1321 | We use an [EditorConfig](http://editorconfig.org) file which enforces our indenting rules. 1322 | 1323 | The contents of the `.editorconfig` file should look something like this: 1324 | 1325 | ``` 1326 | root = true 1327 | 1328 | [*] 1329 | charset = utf-8 1330 | end_of_line = lf 1331 | indent_style = space 1332 | indent_size = 4 1333 | trim_trailing_whitespace = true 1334 | insert_final_newline = true 1335 | ``` 1336 | 1337 | ### Text Editor Configuration 1338 | 1339 | You should configure your text editor to adhere to as much of these guidelines as possible. 1340 | 1341 | At the bare minimum configure your editor to *show invisibles* or to automatically remove end-of-line whitespace. 1342 | 1343 | #### Sublime Text 1344 | 1345 | If 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 -> Preferences -> Settings — User`: 1346 | 1347 | ```json 1348 | "tab_size": 4, 1349 | "translate_tabs_to_spaces": true, 1350 | "trim_automatic_white_space": true, 1351 | "trim_trailing_white_space_on_save": true, 1352 | "word_wrap": true, 1353 | "wrap_width": 80 1354 | ``` 1355 | 1356 | Also install [this package](https://sublime.wbond.net/packages/DocBlockr) to make writing DocBlock style comments super easy. 1357 | 1358 | 1359 | 1360 | 1361 | ## Writing And Architecturing CSS 1362 | 1363 | All of the above is about how we structure and form our CSS; they are very quantifiable rules. 1364 | 1365 | For 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. 1366 | 1367 | In the interim we can link to relevant parts of [Harry Roberts](http://csswizardry.com/) excellent [CSS Guidelines](http://cssguidelin.es/): 1368 | 1369 | - [CSS Selectors](http://cssguidelin.es/#css-selectors) 1370 | - [Specificity](http://cssguidelin.es/#specificity) 1371 | - [Architectural Principles](http://cssguidelin.es/#architectural-principles) 1372 | 1373 | ### Further Reading 1374 | 1375 | - [SOLID CSS](http://blog.millermedeiros.com/solid-css/) 1376 | - [One Module or Two](http://snook.ca/archives/html_and_css/one-module-or-two) 1377 | - [Our (CSS) Best Practices Are Killing US](http://www.stubbornella.org/content/2011/04/28/our-best-practices-are-killing-us/) 1378 | - [Keep your CSS selectors short](http://csswizardry.com/2012/05/keep-your-css-selectors-short/) 1379 | - [The single responsibility principle applied to CSS](http://csswizardry.com/2012/04/the-single-responsibility-principle-applied-to-css/) 1380 | - [Principles for writing good CSS](http://blog.kaelig.fr/post/38377421139/principles-for-writing-good-css) 1381 | - [DOM Hooks—Smarter ways to target elements in the DOM](http://presentation.chris-pearce.me/DOM-hooks/) 1382 | --------------------------------------------------------------------------------