CSS/SASS philosophy


Frameworks

While we have used frameworks such as Bootstrap and Foundation for many of our projects, we ideally would try to avoid them moving forward. This is especially true with Drupal 8 theme development, since drupal core already provides many good default element styles, and adding an additional framework creates unnecessary complexity, conflicts, and confusion. 

Now that CSS Grid and Flexbox have near-universal support, we should use those instead of adding a grid framework.

We have been using the Foundation breakpoint mixin, but we really should find a better alternative, since it contains a bunch of cruft: https://github.com/zurb/foundation-apps/blob/master/scss/helpers/_breakpoints.scss

Non-semantic classes

Using extend and placeholder selectors, we can apply commonly used sets of rules to different elements without the need for non-semantic classes, such as the ones like col-6 used by bootstrap and other frameworks for grid layout.

Your markup should be focused on describing the content semantically, and all layout and styles should be handled in sass.

BEM

Use BEM to organize your class names into the format .block__element–modifier, such as .header__menu--blue.

When using modifiers, you usually should also include the non-modifier block/element class in the element, ie <div class='header__menu header__menu–-blue'>, especially when working with Drupal, since that is how it tends to handle classes. The alternative would be to have the header__menu–-blue class extend the header__menu class in sass, which is a perfectly fine approach, but a project should not mix the two methods or things will get confusing and hard to maintain.

One advantage to BEM and SASS is that you can use the ampersand parent selector to clearly organize your blocks into a hierarchy: 

.nav {
  background: white;

  // element .nav__link
  &__link {
    font-size: 1.2em;
    color: red;
    padding: 0.2em 0.5em;

    // modifier .nav__link--twitter
    &--twitter {
      color: blue;
    }
  }
}


Example from: https://jonsuh.com/blog/sass-bem-selector-and-trailing-ampersand/

Additional resources:
https://css-tricks.com/bem-101/
https://www.smashingmagazine.com/2013/08/other-interface-atomic-design-sass/

Placeholder (fugly) selectors

Don't generate output unless used in a project…

We really like to use these, the following articles explain them succinctly and hopefully, you too, will see their value.
http://thesassway.com/intermediate/understanding-placeholder-selectors
https://www.sitepoint.com/sass-extend-nobody-told-you/
https://www.previousnext.com.au/blog/decouple-design-styleguide-driven-drupal-development

%button {
  border: 4px #0af solid;
  color: #fff;
  background-color: #ff0000;
}

%button--blue {
  background-color: #0000ff;
}

.sidebar > .donate-callout .donate-link {
  @extend %button;
  @extend %button--blue;
}

You can theoretically chain these extends together, so that the %button--blue placeholder extends the %button placeholder, but that is not advisable when doing drupal projects, since its markup tends to contain both the modified and non modified classes, such as <div class='nav nav--primary'>. You don't want the nav--primary class extending the nav class in sass, since it is already getting those styles from having the plain nav class on the element. Even though placeholder classes are obviously not being directly added to elements, we should stick with the same philosophy of modifier classes not extending their element class in sass.

Units

By necessity, any stylesheets will include a combination of different units when specifying sizes of things. However, it is important to use the proper units for the proper uses:

px

  • border width (and radius?)

rem

  • breakpoints
  • maximum container widths
  • font sizes
  • margins and padding
em
  • margins and padding for text blocks where space should scale with the font size
1.x
  • Unitless ratios are used for line-heights.
%
  • layouts (flex and grid)
  • images size within containers
  • setting the base font size (though you should usually leave it at 100% of the user's browser default for accessibility)
vw/vh
  • when elements need to be sized in relation to the window/device height

The most common misuse of units is to specify things in px sizes, when really the element should be sized in proportion to something else. Font sizes especially shouldn't be in px, since you want all of the text to scale up together if the base font size is changed.

For padding and margins the use of rems is highly encouraged, not necessarily because they behave differently than px, but because it encourages everyone on the team standardize on sizes using multiples and divisions of 16px.

Try to avoid using a rem-calc() mixin to convert px values to rem or em (unless you are dealing designer who positively insists on specifying the entire design in px). If you are delivered the specifications for an element in px sizes (especially frequent for font sizes) try to just do the calculation manually and put in the resulting rem value.

Box sizing

Specifying the widths and heights of things is often a pain in the ass, since you are never sure if the padding and borders are being included as part of those sizes. Therefore, at the beginning of a project, you should specify a box-sizing setting for all of the elements on the page.

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

A good explination on why you should use this exact syntax: https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/

Breakpoints

We have not really settled on standard breakpoints to try to use across our projects. However, these might be good values to start with:

Screen sizeStarting sizeNote
small0
medium40rem (640px)
large60rem (960px)Will often be the size that the header and menus switch from mobile to desktop.
xlarge80rem (1280px)Should probably be the same size as your content container.
xxlarge10rem (1600px)Not often used, but that may happen more frequently as 4k desktop monitors become more prevalent.

You should avoid using maximum sizes in your media queries. Considering browser window sizes are no longer in 1px increments, it is almost impossible to ensure that media queries that are bounded on both sides don't overlap or create gaps between them.

Some examples from our projects

EECS http://github.com/kalamuna/eecs

(Perhaps) overly complicated nav organism:
https://github.com/kalamuna/eecs/blob/sprint/sites/all/themes/eecs/kalastatic/src/components/organisms/eecs_nav/_eecs_nav.scss

Much more recently Josh is killin' it on GBZ-FE3
https://github.com/kalamuna/greenbiz.com/blob/fe/sites/all/themes/gbz_fe/kalastatic/src/components/organisms/featured_sessions/_featured_sessions.scss