At Kanopi, we value content and the experience users will have reading it. We write CSS with this in mind and don’t sacrifice our clients’ most important assets over the latest, shiniest, half-supported CSS features just for the sake of using them. CSS should help enhance content, not bury it under “cool” distractions.
Our websites are built mobile first, using performant CSS. Well-structured CSS yields maintainability and better collaboration which ultimately yields better client experiences.
Animation
Not every animation brings pleasure to the end user. In some cases motion can trigger harmful reactions from users with vestibular disorders, epilepsy or even migraines.
The prefer-reduced-motion CSS media feature does not currently have the widest support, but is active in
Let’s be honest, CSS “speed” and performance is not as important as PHP or JavaScript performance. However, this doesn’t mean we should ignore it. A sum of small improvements equals better experience for the user.
Performance best practices are not only for the browser experience, but for code maintenance as well.
We build our websites mobile first. We do not rely on JavaScript libraries such as respond.js as it does not work well in certain environments. Instead, we leverage a natural, mobile-first build process and allow sites gracefully degrade.
Min-width media queries
A responsive website should be built with min-width media queries. This approach means that our media queries are consistent, readable and minimize selector overrides.
For most selectors, properties will be added at later breakpoints. This way we can reduce the usage of overrides and resets.
It targets the least capable browsers first which is philosophically in line with mobile first — a concept we often embrace for our sites
When media queries consistently “point” in the same direction, it makes it easier to understand and maintain stylesheets.
Avoid mixing min-width and max-width media queries.
Breakpoints
Working with build tools that utilize Sass or PostCSS processing, we can take advantages of reusability and avoid having an unmaintainable number of breakpoints. Using variables and reusable code blocks we can lighten the CSS load and ease maintainability.
Media queries placement
In your stylesheet files, nest the media query within the component it modifies. Do not create size-based partials (e.g. _1024px.(s)css, _480px.(s)css): it will be frustrating to hunt for a specific selector through all the files when we have to maintain the project. Putting the media query inside the component will allow developers to immediately see all the different styles applied to an element.
Avoid:
@media only screen and (min-width: 1024px) {
@import "responsive/1024up";
}
.some-class {
color: red;
}
.some-other-class {
color: orange;
}
@media only screen and (min-width: 1024px) {
.some-class {
color: blue;
}
}
Prefer:
.some-class {
color: red;
@media only screen and (min-width: 1024px) {
color: blue;
}
}
.some-other-class {
color: orange;
}
IE8 and older browser support
We prefer showing a fixed-width non-responsive desktop version to older IE users rather than showing a mobile version.
Use a feature detection to target older browsers.
Load a different stylesheet for older browsers.
Syntax and formatting are keys to a maintainable project. By keeping our code style consistent, we not only help ourselves debug faster but we’re also lessening the burden on those who will have to maintain our code (maybe ourselves too!).
CSS Syntax
CSS syntax is not strict and will accept a lot of variations, but for the sake of legibility and fast debugging, we follow basic code styles:
Write one selector per line
Write one declaration per line
Closing braces should be on a new line
Avoid:
.class-1, .class-2,
.class-3 {
width: 10px; height: 20px;
color: red; background-color: blue; }
Prefer:
.class-1,
.class-2,
.class-3 {
width: 10px;
height: 20px;
color: red;
background-color: blue;
}
Include one space before the opening brace
Include one space before the value
Include one space after each comma-separated values
Avoid:
.class-1,.class-2{
width:10px;
box-shadow:0 1px 5px #000,1px 2px 5px #ccc;
}
Prefer:
.class-1,
.class-2 {
width: 10px;
box-shadow: 0 1px 5px #000, 1px 2px 5px #ccc;
}
Try to use lowercase for all values, except for font names
Zero values don’t need units
End all declarations with a semi-colon, even the last one, to avoid errors
Use double quotes instead of single quotes
Avoid:
section {
background-color: #FFFFFF;
font-family: 'Times New Roman', serif;
margin: 0px
}
Prefer:
section {
background-color: #fff;
font-family: "Times New Roman", serif;
margin: 0;
}
If you don’t need to set all the values, don’t use shorthand notation.
Avoid:
.header-background {
background: blue;
margin: 0 0 0 10px;
}
Prefer:
.header-background {
background-color: blue;
margin-left: 10px;
}
Declaration ordering
Declarations should be ordered alphabetically or by type (Positioning, Box model, Typography, Visual). Whichever order is chosen, it should be consistent across all files in the project.
@include (to visually separate mixins and placeholders) and media queries
Nested selectors
Nesting
Nesting has changed the lives of many, but like everything in life, abusing good things will ultimately be bad. Nesting makes the code more difficult to read and can create confusion. Too much nesting also adds unnecessary specificity, forcing us to add the same or greater specificity in overrides. We want to avoid selector nesting and over-specificity as much as possible.
If you’re using PostCSS or Sass nesting is required in the following cases, because it will make the code easier to read:
pseudo-classes
pseudo-elements
component states
media queries
Selector Naming
Selectors should be lowercase, and words should be separated with hyphens. Please avoid camelcase, but underscores are acceptable if they’re being used for
or another syntax pattern that requires them. The naming of selectors should be consistent and describe the functional purpose of the styles they’re applying.
Avoid:
.btnRed {
background-color: red;
}
Prefer:
.btn-warning {
background-color: red;
}
For components that could possibly conflict with plugins or third-party libraries, use vendor prefixes. Don’t use names that can be blocked by adblockers (e.g. “advertisement”). When in doubt, you can check a class name against
Code documentation serves two purposes: it makes maintenance easier and it makes us stop and think about our code. If the explanation is too complex, maybe the code is overly complex too. Documenting helps keep our code simple and maintainable.
Commenting
We follow WordPress official commenting standards. Do not hesitate to be very verbose with your comments, especially when documenting a tricky part of your CSS. Use comment blocks to separate the different sections of a partial, and/or to describe what styles the partial covers: