Styleguide Navigation

Hinderling Volkart Frontend Coding Guidelines

Version 1.4 ( 2015-09-18 / sk )

Version 1.5 ( 2016-04-21 / dme ): Adds Best-Practices, updates CSS Formatting rules

Formatting

1. General

  • Encoding: UTF-8
  • Indentation: Tabs
  • We like Spaces and Readability
.i_am_a_selector + p {
                  color: #fff;
                  transform: scale(1);
              }
              
              function doSomeFancyStuff( param1, param2 ) {
                  // fancy stuff
                  if ( param1 < param2 ) {
                      return false;
                  }
                  return true;
              }
              

is better than

.i_am_a_selector+p{
                  color:#fff;
                  transform: scale(1);
              }
              
              function cmpF(p1,p2){
                  if (p1<p2) return false;
                  return true;
              }
              

2. HTML

  • Attributes wrapped with double quotes
  • Filenames with underscores (e.g. myfancymodule.html.haml)
  • the HTML is W3C Valid
  • We use semantics where semantics make sense
  • Try to avoid too many structural elements like sections, articles, headings
  • We'll use level headings (no matter the structural elements):
    • h1 for page title
    • h2 for main sections
    • etc.

2a. HAML / RUBY

  • Use single quotes for static string: part 'components/mymodule' – double quotes are only needed for strings with variables: error :id => "#{input_id}_error"
  • Do not use randomized strings! Randomizing output makes it extremely difficult to compare with diffs. We have two extensions to satisfy these needs:
    • uid returns a unique id as string, uid(:int) returns a unique id as integer
    • the constant lorem extension gives you the power of lorem with "constant random": just use it like lorem. Also note the lorem.rand function that should be used whenever you think you'd like to use rand.
  • We have a part helper that replaces the usual partial and partial_wrap:
    • partial 'a', :locals => {:id => uid} is replaced by part 'a', :id => uid
    • partial_wrap 'a', :locals => {:id => uid} do is replaced by part 'a', :id => uid do
  • We always work with locals in partials. Define default parameters at the top of your partial:
- id ||= uid
              - title ||= 'Default Title'
              

3. SASS (CSS)

  • Use SCSS
  • We avoid selecting tag names (to separate styling from semantics)
  • We avoid multi level selectors: just select .mega_list--item instead of .mega_list .mega_list--item (after all we have expressive class names, right?)
  • CSS States are an alternative to Variants. They must be prefixed with is- or has- or no-. E.g. is-open, has-menu. States are often set by Javascript. Only style states in combination with a unique class name! (so never do .is-open .mega_list--item but .mega_list.is-open .mega_list--item!!)
  • Please consider prefixing all components with a project wide abbreviation: This helps avoiding future collision with third party selectors (e.g. edelweiss: ew-*)
  • Avoid using Frameworks
  • Don't use CSS Hacks (use Modernizr if necessary)
  • Extend with care: only @extend %placeholder_selectors!! We considere it good practice to avoid extending at all in most cases.
  • Don't do this: [class*="some_class-"] Better go with .some-class, .some-class-a, .some-class-b

3.1 Formatting

  • Properties indented with tabs
  • Selectors in lowercase
  • Class names with underscore: .mega_list
  • A descendent of a class is denoted with two dashes: .mega_list--item
  • A Different variant or version of a class is denoted with one dash: .mega_list-ultra
  • SASS: Variables and function names in camelCase
  • Put a space before the opening brace { in rule declarations
  • In properties, put a space after, but not before, the : character.
  • Put closing braces } of rule declarations on a new line

Bad

.bad{
                  border:2px solid white; }
              .no, .not_good, .bad {
                  // ...
              }
              

Good

.avatar {
                  border: 2px solid white;
              }
              .one,
              .selector,
              .per-line {
                  // ...
              }
              

4. JS

  • There is no JS that is included without Require.js (beside of Modernizr and IE8 Shims)
  • Modernizr must be customized.
  • We only do feature detection.
  • Variables and function names in camelCase
  • Constructors, Singletons and class names in PascalCase
  • Constants in UPPERCASE (e.g. ANIMATIONDURATION)
  • References to jQuery objects start with $ (e.g. $container)
  • Use jshint and JSCS (JavaScript Code Style) with the provided default configs (.jshintrc and .jscsrc) to lint the code and programatically enforce our style guide.
  • We avoid selecting css class names that are not 'js' prefixed. So basically select .js-list--item within .js-list, not li within ul.list
  • The only exception from this rules are states: you may set, unset and (if really necessary) select states, like is-open, is-active or has-menu
  • Comments (because we use YUI compressor):
/\*!
               \* Not stripped when compressed
               \*/
              
              /\*
               \* Stripped when compressed
               \*/
              

5. Units

  • We generally use PX and %
  • REM/EM's are only used for Font-Sizes and styles that depend on text.

6. Images

  • Optimize all included images (with ImageOptim for example) (unless its included in the middleman build)
  • Icons and layout specific images are usually included in standard and retina resolution.
  • The naming for retina is "{name}-2x.{ext}", e.g. logo-2x.png – sprites are within folder "{name}2x", e.g. "icons2x".
  • Generated sprites are by default optimized with pngquant (if installed)

7. General Best-Practices

  • Avoid setting custom classes on base/layout components (like .l-grid), if not really necessary (especially within a component):

Bad

.l-grid
                  .l-col.l-1of1.not-good
              

Good

.l-grid
                  .l-col.l-1of1
                       .better