CSS Standards

The Spike CSS Standard stack can be accessed through a single plugin bundle for simple configuration. This is what you will find in spike's default template when you create a new project. It includes a wide range of plugins that make life easier and polyfill for upcoming standards. A full list can be seen here:

https://github.com/static-dev/spike-css-standards#usage

All these plugins run on top of postcss, our foundation-level css transformation platform. The rationale behind each of these decisions is explained below. This is a living document and any and every part of it is subject to change in the future. We try to align as closely as possible with future CSS standards when considering our default stack and best practices.

🚧

Note

Many in the spike community choose to use sugarss as the default parser, which eliminates semicolons and brackets. All examples here apply the same if you are using sugarss, just leave out the brackets and semis and make sure your indentation is accurate.

Nesting

Support for nested css selectors is an absolute essential in the spike standards for CSS. Without nested selectors, you end up repeating yourself over and over. This feature is so important to so many people that it has an official css spec.

#index {
  color: red;
  
  & .introduction {
    font-size: 14px;
  }
}

This also applies for media queries. You can avoid specificity issues and having your code too spread out by keeping an element's media query styles right alongside its standard styles. For more details on the rationale for this check out the "style" section below.

#index {
  color: red;
  
  & .introduction {
    font-size: 14px;
		
   	@media (min-width: 500px) {
      font-size: 12px;
    }
  }
}

Variables

So let's say that you have a couple of primary brand colors for a page you're working on. You will probably need to use those colors in a few places. Perhaps you need the same striking red for the call to action button as for the primary headline. Here we have already run into a situation that is not DRY. Better in programming to abstract that color to a variable so that it can be controlled from a single location.

For that reason, using variables is an important thing to have in your CSS. There is also an official CSS spec for variables, which we follow in our recommended implementation:

:root {
  --brandColor: #f00;
}
 
h1 {
  color: var(--brandColor);
}

While this is not the smoothest syntax that has ever been proposed for variables, it is the one in the official css spec, so we're rolling with it.

No Vendor Prefixes

Vendor prefixes are a huge pain and everyone knows it. Fortunately, we now have autoprefixer, so we don't need to worry about vendor prefixes anymore :tada:

Calc

Sometimes you need to do some math. Like making one border double the width of the other border. When the relationship between the two values is mathematical, you don't want to just calculate it yourself and paste the result, because when one value changes, you need to recalculate any other times that it is used. For this situation, it's better to be able to say "this should be value X times two", which requires the calc function. Example:

:root {
  --fontSize: 1rem;
}

h1 {
  font-size: calc(var(--fontSize) * 2);
}

Mixins & Custom Functions

There is currently no web standard in development to implement mixins, although CSSWG members have indicated that this is eventually something they would like to have. As such, if you need more complex functionality that would typically require a mixin, we recommend using postcss for this directly. There are a lot of postcss plugins that provide specific functionality through functions, and if you can't find one that fits your needs, you can just write a little custom postcss plugin to contain your functions.

Eventually, we intend to build or bring in a library that implements mixins with css standard variables, but as of the time of writing nothing like this exists.

Pixels, Ems, Percentages

There are three units of measurement that you can use in your stylesheets, and this can be confusing. Each one of them has an ideal use case, which will be explored below.

Pixels are an absolute unit of measurement and are great for any granular measurement. If you need a measurement to be exact, and not change unless you specifically change it, pixels are the way to go. For many pure-layout-based things, you will find that pixels are the best choice.

That being said, all websites must be responsive by today's standard, which makes using percentages very relevant. If you are using any type of grid, it likely uses percentages. For high level layout functionality, this is typically the best choice. For example, if you have two columns that are aligned horizontally and each take up half the width of the page, you would use 50% as the value for this, rather than calculating the number of pixels needed for the screen you are on. Essentially, if you have used pixels and find yourself needing to constantly adjust the measurement using media queries to be properly responsive, it's probably worth considering using percentages instead.

The em is a little more confusing of a measurement. According to the w3c, it is defined as:

Equal to the computed value of the 'font-size' property of the element on which it is used. The exception is when 'em' occurs in the value of the 'font-size' property itself, in which case it refers to the font size of the parent element.

One thing that's quite clear by the definition is that the em is a font-size-based measurement. This means at face value, ems should be used if you are working with fonts or elements that must change in parallel with the font-size. For example, margins or padding around text. Essentially, if the text size changes, ems will change. So as long as you can change the base font size in the element you are working with or its parent element and it behaves the way that you would want it to, ems are the right measurement. If not, you should probably be using pixels or percentages. It's worth also mentioning rems, a newer form of measurement. These are basically the same as ems, except they are tied directly to the root font size on the <html> element. So you could change the font size in the element containing text, and it would not change an em measurement. Only if the root font size changed would the value of rems adjust

Code Style

We use the stylelint standard to lint css. Much like our javascript style linting, it's a basic set of preferences that are easy to agree on in order to help keep css style consistent across projects and so that everything is as easy to understand as possible for all developers.

Unlike standardjs, stylelint is configurable through the .stylelintrc file. However, we strongly suggest not modifying the configuration to fit your own style, as this kind of destroys the purpose of setting this standard in the first place, unless a particular rule has a bug that cannot be avoided while keeping your stylesheet functional.

CSS Architecture

There are many opinions on the "right" way to write and structure your CSS, and for good reason. Structuring CSS well is vastly important, especially when dealing with large websites, and if it is done wrong it can mean absolute disaster for your project.

Spike's CSS standard recommends using a CSS organization system called GPS. This system is designed to be as clean and simple as possible while also completely preventing any scope leaks or global css conflicts. It does not require any additional compilation, it's simply a methodology for writing CSS.

The one thing this does bank on is being able to add a unique ID to each page of your site for scoping purposes. This feature is included with spike's base template through the pageId local, but entirely customizable as well.