We at Extra Nerds believe that it is important to support folks like us, with similar philosophies, in the industry and, to that end, here’s our first guest blog post by Toptal Developers.
CSS Best Practices and Tips
This resource contains a collection of best CSS practices and CSS tips provided by our Toptal network members. As such, this page will be updated on a regular basis to include additional information and cover emerging CSS techniques. This is a community driven project, so you are encouraged to contribute as well, and we are counting on your feedback.
Cascading Style Sheets (CSS) can be described as a style sheet language written in a markup language. It is used for defining the look and formatting elements of Web documents such as the layout, colors, and fonts. The CSS specifications are maintained by the World Wide Web Consortium (W3C). Even though every browser supports CSS, there are many inconsistencies in the supported specification version. Some browsers even have their own implementation of the specification and have proprietary (vendor) prefixes. Supporting all modern browsers is a daunting task, not to mention when developers need to support old and legacy browsers. All these problems cause a lot of trouble for developers, and it is hard for them to write CSS code that will render consistently across all browsers. That’s why we want our top CSS developers and engineers to share their knowledge and offer their best tips to achieve those tasks more easily.
How to Improve CSS Performance
There is a lot you can do to ensure good CSS performance and reduce page loading times. Here are some tips and techniques you can start implementing today.
A browser needs to go through every single DOM element to find what it is looking for. Take this example:
.home-page .header-main .nav-main ul
The browser will begin by looking for every ul element, then every .nav-main inside of a ul, then every .header-main inside of that, and then every .home-page inside of that. Only when the search is done are styles applied. We can be far more efficient than that and write a specific selector, like this:
.nav-list
Now the browser simply needs to find the .nav-list element and apply the styles to it. We have kept specificity low and avoided unnecessary nesting. Simple, yet efficient.
Naming classes can be tough, but you can use some of the well known tricks for that. For instance, in our .nav-list element, you can use the .component-descendant-descendant naming:
.nav-list-item
The .nav-list-item would be the list item in the navigation. Alternatively, you can use the BEM naming methodology, already covered in our CSS tips.
Another piece of advice for keeping low specificity is to avoid IDs and use classes. The big benefit of using classes is that you can reuse your styles and help keep your style sheets DRY (Don’t Repeat Yourself), which will also reduce the file size.
How to Write Modular CSS Code
Code duplication is one of the most important issues that originate from coding in plain CSS. In order to contest that, preprocessors come with very strong function, mixin or extend implementations. In this tip we are going to introduce @include and @extend, and discuss how they can be used efficiently in SCSS.
Creating Mixins with @include and @mixin
By utilizing the @include implementation, you can create mixin functions with parameters. For example, a display block centered container with max-width could be implemented as follows:
// Create a max-width container
@mixin maxWidthContainer($width : 1024px) {
display: block;
max-width: $width;
margin: 0 auto;
}
The mixin declared above can be called with the following command: @include maxWidthContainer();. Since the default value for a $width parameter is set to 1024px, generated CSS will look like this:
display: block;
max-width: 1024px;
margin: 0 auto;
Extending Classes with @extend
The @extend can be used to share CSS properties from one class to another. For example, the following button style declarations in SCSS:
.button {
color: black;
background: white;
border: 1px solid gray;
}
.button--warning {
@extend .button;
color: red;
background: orange;
}
.button--disabled {
@extend .button;
color: white;
background: gray;
}
Will result in the following CSS:
.button, .button--warning, .button--disabled {
color: black;
background: white;
border: 1px solid gray;
}
.button--warning {
color: red;
background: orange;
}
.button--disabled {
color: white;
background: gray;
}
Please notice how the button modifiers (.button--warning and .button--disabled) are stacked in the initial declaration of .button.
Efficient Usage of @include and @extend
Mixin declaration is the most useful function that preprocessors have to offer. @include can be used for anything from adding animations to responsive breakpoints. Any piece of code that is repeated multiple times should be applied into a mixin which will effectively make your code more readable and easily maintainable.
On the other hand, @extend has to be used very carefully and sparsely. While initially it seems to pose plenty of advantages, in its use there are a few disadvantages:
- You can not extend from within a media query
- It does not accept any parameters
Both @include and @extend are very strong directives which can make CSS development with the aid of preprocessors way more productive as well as fun.
In addition to these CSS topics, the rest of the blog series includes discussions on Using Stylus to Easily Decouple Semantic Markup from CSS Stylesheets; How CSS Namespacing Can Aid Front-End Development; How to Write Maintainable CSS Declarations; How to Customize an HTML File Input; What is a Block, Element, Modifier Approach; and How to Write Consistent CSS.