Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed CSS Best Practices!
You have completed CSS Best Practices!
Preview
There’s more to writing good CSS than simply knowing all the latest and greatest features and techniques. In this workshop, we'll cover best practices for making our CSS more efficient, maintainable, and scalable.
CSS Architecture
CSS Resets
Formatting CSS
Vendor Prefixes
Helpful Tools
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
[CSS Best Practices with Guil Hernandez]
0:00
[Guil Hernandez] Hi everyone, I'm Guil, one of the front end
0:04
design teachers here at Treehouse.
0:06
In this workshop we'll be covering CSS best practices.
0:09
These are methods we can use to make our CSS
0:13
more efficient, maintainable, and scaleable.
0:15
As we will soon find out, there is a lot more to writing good CSS
0:19
than simply knowing all the latest and greatest features and techniques.
0:23
Today's web sites and applications are larger than ever
0:28
and a lot hinges on the CSS architecture,
0:31
so CSS that is poorly thought out can be a strain on development in the long run.
0:34
In this workshop we will be covering topics such as
0:42
CSS architecture, classes versus IDs.
0:45
We'll also get into specificity in selectors,
0:50
and we'll then cover some CSS reset methods
0:54
along with ways to format our CSS and using vendor prefix.
0:58
Finally, we will get into some helpful tools
1:04
to help us write CSS with these best practices in mind.
1:07
When writing CSS our main goal should be that our CSS is
1:12
predictable, reuseable, maintainable, and scaleable.
1:18
So let's review these in detail.
1:24
CSS rules that are predictable should behave as we expect them to.
1:28
If we need to update or add any new CSS rules
1:34
they shouldn't affect other parts of our site.
1:38
Reuseable CSS should be decoupled from the html.
1:41
So if we need to add any new components or features
1:46
we shouldn't need to recode any patterns or solve any problems
1:49
that we've already solved with existing CSS.
1:54
Now one of the most important ones is making our CSS maintainable.
1:58
This means that we should not have to refactor any of the CSS
2:03
if we need to add updates or new features and components.
2:07
The added features or updates we make should not break
2:12
any of those other components in the site.
2:16
Now at some point our site or application will need to scale, which will then require
2:19
more developers working on and maintaining our site and our code,
2:26
so we need to write our CSS so that it can be easily managed
2:31
by other developers who are looking at our code for the very first time,
2:36
and there should not be a learning curve for them.
2:41
This is when a lot of these best practices come in to help us with a lot of these goals.
2:44
For example, keeping our CSS "DRY."
2:51
DRY, or "Do Not Repeat Yourself," is a common best practice
2:55
in web development where the main idea is to avoid
3:01
repeating these same chunks of code or patterns.
3:06
If we have bits of code that are repeated multiple times throughout the site
3:10
it's a good idea to refactor the CSS set
3:15
so that there's only one instance of that code—or one occurrence of that code.
3:18
This way each property and value pair is only defined once in our style sheet.
3:23
The idea with DRY is to group these repeated CSS properties together
3:29
into one rule then add selectors to those groups if they share the same property.
3:35
That way our CSS is more maintainable and we would only have to change
3:42
one line of CSS, which results into a cleaner html file,
3:45
and we only rely on those specific selector groups in the CSS.
3:51
For example, we might have a CSS file with 3 rules.
3:57
Each of these share the same padding and border radius properties.
4:02
The button and field rules share the same display property,
4:08
and the float property is only declared in this common rule here.
4:13
To make this CSS a bit dryer we can simply separate those shared properties
4:19
into 1 rule that groups the selectors using those properties.
4:25
So now the button field and column selectors
4:29
share the padding and border radius declarations,
4:33
and below that the button and field selectors share the display property,
4:36
and the column rule now only has that float property declared.
4:40
Now this was a very simple example of grouping selectors together
4:45
that share the same properties, but what if we have to deal with hundreds of lines
4:49
of CSS or large scale sites that have tens or hundreds of pages?
4:54
Well, object-oriented CSS, or OOCSS, can be really useful for this.
5:01
OOCSS was introduced by Nicole Sullivan in 2009,
5:09
and the base principles are a lot like our previous example with DRY.
5:16
The object in OOCSS is a repeating visual pattern.
5:21
That visual pattern then gets abstracted into
5:27
these independent blocks of CSS or modules.
5:31
Those modules can then be reused anywhere in our site.
5:35
So with OOCSS we will need to think more in terms of style patterns
5:39
instead of just styling these individual elements.
5:44
We'll also need to think of our web site or app as these code-independent
5:47
components that can be rearranged without affecting surrounding components.
5:52
OOCSS has 2 main concepts.
5:58
The first one is the separation of structure from appearance
6:02
and the separation of containers and content.
6:07
When we separate the structure from appearance it means that
6:11
once we spot these repeating patterns in our CSS we'll need to abstract them
6:15
into these separate skins that are reuseable.
6:21
We'll then need to name those skins logically,
6:24
and, finally, we'll add those skin classes to our html elements that require those styles.
6:28
For example, here in our CSS we again have 3 separate rules.
6:35
Now they all share the border, border radius,
6:40
padding, and box shadow values as we can see here.
6:43
Using OOCSS we can actually abstract those into a separate rule or object
6:48
and make that our base skin style, which can be reused anywhere in our project.
6:54
Then the html can still have those classes for container, box, and button,
7:01
but we can then append those skin classes
7:06
in the class attribute to bring in those space styles.
7:09
Now if skin needs to be changed we only need to change it once in the CSS.
7:13
When we separate containers and content
7:19
the style components we create should be code or location independent.
7:22
So the elements should be reuseable no matter where they are on the page,
7:28
and the CSS should not be specifically tied to the html or a location in the document.
7:33
The module should actually be able to adapt
7:41
to different containers and be easily themed.
7:44
When we separate containers and content all elements with those given classes
7:48
will also look the same on the page no matter what.
7:53
For example, we might have a page with a header and footer
7:58
that span the full width of our browser, but then we would probably like to have
8:02
these inner containers that need to be centered on the page, as we can see here.
8:08
So our html might look something like this
8:14
where we have the main header, main content, and main footer elements
8:17
with these header inner and footer inner divs nested inside.
8:22
These will need to share the same structural styles like width, margin, and padding.
8:28
Our CSS could look something like this with these 3 selectors
8:36
grouped into 1 rule that shares those properties.
8:40
With the separate containers and content principle in mind, we can abstract
8:44
those structural styles into their own reuseable class called global width.
8:49
Then in our html we'll just need to add that global width class to the class attribute.
8:56
Some of the benefits to using OOCSS is that it results in smaller style sheets
9:04
that are easier to maintain and scale.
9:11
It also makes our CSS predictable, which is one of our main goals when writing CSS,
9:15
and we could very well build an entirely new html page
9:21
without having to touch the CSS at all.
9:24
Once we've defined all these modules in the style sheet
9:27
we can sort of plug them in where needed.
9:31
For more info on OOCSS you can check out github.com/stubbornella/oocss
9:34
or check out the link I added to the workshop notes.
9:42
A similar method called Scaleable and Modular Architecture for CSS
9:46
was created by Jonathan Snook as a style guide that helps organize our CSS.
9:52
SMACSS is very similar to object oriented CSS
9:58
in that it helps structure our code for projects on any scale.
10:03
It also combines repeating CSS patterns into these reuseable components
10:09
we can use anywhere in our sites.
10:14
The difference is that SMACSS separates our components
10:16
into 5 general categories and those categories are
10:20
the base rules, the layout rules, the module rules,
10:25
the state rules, and the theme rules.
10:30
Our base rules in SMACSS define all the default styles
10:34
and how they should look no matter where they are on the page.
10:39
Base rules are directly applied to element selectors, not classes or IDs.
10:43
Base rules can be used as a CSS reset. It's very good for that.
10:51
For example, here we have base rules with our box sizing for all elements,
10:57
one that removes margins and padding from the body,
11:02
sets the body font styles and so forth.
11:05
The SMACSS layout rules are what divide the page into the major components.
11:10
For example, the main header, the sidebar, the footer,
11:17
and these components can then contain 1 or more modules.
11:21
For example, here we have some layout rules for our main wrap container,
11:26
the main headers and footers, and some of the layout columns of the page.
11:30
Our module rules are the reuseable modular components or the minor components.
11:37
Each module we create should exist as a stand-alone component
11:44
so it can be easily moved throughout the layout without breaking anything.
11:49
When we write module rules we should avoid using IDs and element selectors.
11:54
We should stick with those class names since they're reuseable.
11:59
For example, here we have examples of the main nav component,
12:04
callout module, along with maybe a login or search-box component,
12:09
and these should all be reuseable throughout our project.
12:13
We should just be able to plug them in wherever
12:17
we need to without affecting anything else.
12:19
Now we can also subclass these module rules if we need to change the look
12:21
because we want to place it in other parts of our site.
12:28
To do that it's best to use a subclass
12:31
instead of creating a new conditional style based on the new location.
12:34
Here are some examples of the subclassed module.
12:40
We might have these mod and searchbox components
12:43
that maybe need to be modified to use in the footer or the sidebar sections.
12:47
Instead of creating descendant selectors for mod and searchbox
12:53
we can create those subclasses that contain those modified styles.
12:57
Then in our html we can, for example, keep those searchbox and mod classes and, to
13:02
bring in the modified styles, we simply append those subclasses in the class attribute.
13:09
In SMACSS the state rules are what define
13:17
how the modules look when in a particular state.
13:21
These are the collapsed or expanded states,
13:25
maybe a success or error state, or a hover inactive state in a link.
13:28
State rules augment or override other styles,
13:34
and we can apply them to layout and module styles.
13:38
State rules can also be used with pseudo-classes, media queries, or JavaScript.
13:43
Examples of state rules are, as we can see here,
13:49
the hover rule for mod, maybe an active state or a transparent state.
13:52
We also have these hidden states and maybe a JavaScript specific state
13:58
for expanding or collapsing elements.
14:03
Finally, the theme rules are what define the color scheme or the typography.
14:07
Theme rules are similar to state rules in that they define how the layout might look.
14:13
So they are what separate the themes into their own set of styles,
14:19
so that they are easier to modifry.
14:24
Theme rules are optional because we may not have a need for themes in our project.
14:26
So, as Jonathan Snook states, "We'll need to think about our interface
14:33
as not only modularly, but as a representation of those modules
14:37
in various states because it will make it easier to separate styles appropriately
14:43
and build sites that are easier to maintain."
14:48
There has been a lot of discussion lately about using classes versus IDs.
14:53
So let's talk a little bit about when it's best to use a class or an ID in a selector.
14:59
It's best to use IDs as JavaScript hooks or as fragment identifiers in our page.
15:04
For example, here we have 3 anchor elements that target sections of the page
15:13
if their IDs match the # in our URL or in the href attribute.
15:18
Here we have IDs being used as fragment identifiers,
15:25
but we can then bring those in as JavaScript hooks,
15:29
for example in our search field and the submit button functionalities.
15:32
IDs are very heavy on specificity and they cannot be reused.
15:38
That is why it's best to use classes because they are more flexible for styling,
15:44
and they can always be reused.
15:49
So then back in our html file we can add those to the elements for the presentation.
15:52
Now there are a few more things to consider, for example,
15:59
we should avoid using the same class or ID for styling and JavaScript.
16:01
Doing that will make our architecture a lot more fragile
16:09
because we're setting up a lot of dependencies
16:13
between the CSS, JavaScript, and the fragment identifier.
16:15
If we need to create JavaScript specific classes
16:20
it's best to prefix them with something like JS.
16:23
This way they're easily identifiable as JavaScript hooks
16:27
and it decouples the presentational classes from the functional classes
16:31
and, most importantly, it reduces the chances of affecting JavaScript behavior
16:36
when we need to make those thematic or structural changes in the CSS.
16:42
For example, here we have some JavaScript specific classes
16:48
for maybe collapsing an element, hiding it, fading it,
16:51
or sliding it on the page.
16:56
This leads usa into how specificity is calculated in a selector.
17:00
Specificity is what determines which CSS styles are applied by the browser.
17:05
Selectors with the most specificity always take precedence over others.
17:11
Let's talk a little bit about the calculations a browser will make
17:17
in order to determine that specificity in a selector.
17:22
It's important to understand this conceptbecause knowing how the browser
17:26
will interpret your code can come in really handy when debugging CSS,
17:31
and it will also save you a lot of time.
17:36
The browser uses 4 categories to define the specificity in a selector.
17:39
One of those is inline styles, which use that style attribute and elements.
17:45
The others are IDs, next.
17:51
It uses classes, attributes, selectors, and pseudo-classes, and, finally, elements.
17:54
The browser then assigns a specificity value to each one of these categories,
18:00
and we can sort of think of them as points.
18:06
Each zero here represents each of the categories, respectively.
18:09
So no selectors are zero points across the board,
18:14
and if the selector consists of any of these four categories
18:18
one point is added to its respective category.
18:23
For example, 1 point will be added for every inline element,
18:28
1 point for every ID, 1 for every class, and 1 for every element selector.
18:32
Let's take a look at an example of a selector here.
18:38
Here we have a selector that has 1 class.
18:42
The browser then adds 1 class point, which gives us a specificity value of 1,0 or 10.
18:45
Next, if the selector has 1 ID and a class in the selector
18:54
the browser will then add 1 class point and 1 ID point
19:00
which then gives us a specifricity value of 1, 1, 0 or 110.
19:04
In another example, if we qualify that class by adding the list item element selector
19:11
the browser will then add 1 point for the element and our specificity value is 1, 1, 1.
19:17
If we then add an unordered list element selector to that nav ID
19:27
the browser will then add 1 more element point, which gives us that value of 1, 1, 2,
19:32
and, finally, inline styles are very heavy on specificity.
19:39
As we can see, it gives inline the value of 1, which results in a specificity value of 1000.
19:44
So other things to keep in mind with specificity
19:52
is that we should not rely on parent or descendant selectors
19:55
because they lower the specificity of child elements.
20:01
A better approach is using name spaces as modifiers.
20:05
That way they are self-contained and modular.
20:10
The modifiers can then be used anywhere and they're
20:13
not entirely location based.
20:16
For example, we can prefix moidified selectors with the base class name.
20:19
So here we have an element with the class title in the second rule
20:25
that we might want a modifier for the sidebar.
20:29
Well, instead of relying on that sidebar descendant selector,
20:33
we can extend it by creating a new modifier class named sidebar title.
20:37
Here's another example where we might want to adjust something for the sidebar
20:45
when it's inside the main footer.
20:50
For that we can create the modifier class using the main footer
20:53
name space right in front of sidebar.
20:57
It's very similar to subclassing module rules
21:00
with that SMACSS approach we covered earlier.
21:04
It's also important that we do not rely on tag selectors
21:07
because tag selectors are not reuseable and they can be easily overridden,
21:12
which then makes our CSS architecture more fragile.
21:17
Finally, we'll need to avoid those important declarations in our CSS values.
21:22
We should not use important unless absolutely necessary
21:30
because it breaks the natural order of the CSS cascade.
21:34
It overrides all specificity, even ones in inline style.
21:39
It has also been referred to as the "Jedi mind trick" of CSS.
21:44
So, as you can see, it's a very powerful declaration that we need to be careful with.
21:48
So, as you can see, it's a very powerful declaration that we need to be careful with.
21:48
To sum up CSS specificity, inline styles will win over external style sheets,
21:53
IDs win over classes, and important wins over all.
21:59
Next up, it's always good to use some form of CSS reset in our architecture.
22:06
Most CSS resets provide a baseline for styling our pages.
22:13
By completely removing certain browser style inconsistencies
22:20
like margins, padding, line height, and some of the heading font sizes
22:24
we're making sure that our page looks pretty consistent on all browsers
22:29
before we begin writing our main styles, but it's also okay
22:34
to leave in some of those browser default styles as we'll find out shortly.
22:39
The method we should avoid for CSS resets is using the universal selector.
22:45
When using that universal selector we have no control
22:52
because we lose inheritance in CSS values from parent to child elements.
22:56
It trumps any form of inherited style.
23:02
Because of that we'll need to write a lot of extra CSS to define a property
23:06
for both the parent and the child element.
23:12
It also affects the browser—the page load time—because the browser
23:15
has to run througth every page element to apply the reset properties.
23:20
A common CSS reset method is Eric Meyer's reset CSS.
23:26
Reset CSS provides a really good starting point.
23:33
We can then edit or extend as we need.
23:36
It also includes all the necessary and new html5 tags
23:39
like header, footer, aside, section, and so forth.
23:44
The good thing with this method is that we shouldn't need to include the entire reset,
23:48
just those attributes that we're using and restyling.
23:53
One of the most common methods these days is normalize.css.
23:58
Some advantages to using Normalize over other CSS reset methods
24:03
is that Normalize preserves those useful default styles,
24:08
so we don't need to redeclare styles for some of those common typographioc elements
24:13
like headers, paragraphs—they all preserve those consistently across the browsers.
24:18
Also, the form elements are cross-browser consistent.
24:24
Different browsers do have different styles for form elements
24:29
so Normalize keeps those consistent right from the start.
24:32
We can then remove entire sections of the normalize.css file
24:35
because the file size is very small and modular with detailed documentation
24:40
and, most importantly, it has great browser support.
24:47
Now it's important to keep in mind that we should not
24:51
have to write new CSS to reset previous styles.
24:53
If you find yourself doing that often,
24:59
you'll need to stop, reassess, then refactor your CSS.
25:01
Next we'll talk about the best order for formatting CSS rules.
25:06
One of those methods is the single line method,
25:12
which is the most space and size efficient,
25:16
and it requires the least vertical and horizontal scrolling in your style sheet
25:20
for writing and editing CSS,
25:24
but it is difficult to browse through and immediately target
25:27
the specific parts of the CSS as we can see here.
25:31
CSS rules can get complex so because of that most developers like
25:35
to use that multi-line method, where each property
25:40
and value declaration is on a separate line.
25:44
We can take the multi-line method one step further
25:49
with the multi-line indent format where indented blocks indicate
25:53
that we're targeting child elements of the selector above.
25:57
For example, here we have main-nav indented beneath main-header,
26:03
the column rule is indented beneath the main-content rule and so forth.
26:06
We should be minifying and compressing our CSS files in production anyways,
26:12
so we should use a method that allows us to navigate CSS quickly
26:17
so it will need to maximize readability
26:22
even if it means writing each property on a separate line.
26:24
Next, what about the property and value declarations?
26:29
The best way is to arrange them functionally in our CSS
26:34
where the properties are divided into these groups
26:38
and aranged in the most logical order.
26:41
Doing that improves maintenance and readability.
26:44
As we can see here, this rule has the positioning properties; width, height,
26:49
border styles, and the background colors all defined in separate groups,
26:53
which then improves maintenance efficiency, as we just learned,
27:00
and there are a lot of tools that can actually help us with the declaration order,
27:04
one of them being CSS Comb, which is a free tool
27:10
for sorting CSS properties into specific orders.
27:14
It helps us sort and categorize our CSS to improve maintenance
27:18
It actually has an algorithm that sorts CSS in the order that is as close as possible
27:24
to the decisions web developers would make when writing CSS.
27:30
If we were to do something like this manually it would involve
27:35
copying and pasting a lot of lines of CSS,
27:38
and CSS Comb will do it with just one click.
27:41
A tool like CSS Comb will come in handy when working with a team of developers
27:45
because it helps maintain our coding style across the team,
27:50
which then helps us understand the CSS better
27:53
and it helps us find properties much faster, which prevents errors in the CSS.
27:56
The cool thing is that code editors like Sublime Text 2 and Coda
28:02
all have these CSS Comb plugins we can use right in the text editor.
28:05
Next, what about vendor prefix?
28:11
It's important to follow up on browser support for many of the latest CSS3 features
28:15
so we'll know which vendor prefixes we need to include in our style sheet.
28:22
A good resource for that is caniuse.com,
28:26
which gives us a comprehensive compatability table
28:30
for browser support of all the latest CSS3 features.
28:33
Another one is the Mozilla Developer Network,
28:38
which is a valuable reference that describes
28:41
pretty much every CSS property and the latest browser support.
28:44
When writing vendor prefixes it's important to always include
28:49
the unprefixed properties last in the rule,
28:53
as we can see here with the transition and the linear gradient properties.
29:00
There are tools that can help us write these vendor specific properties.
29:06
My favorite is Prefixr at prefixr.com,
29:10
because we only need to write the properties once.
29:14
It then converts our CSS to cross-browser compatible CSS,
29:18
and it does that by filtering through CSS3 properties
29:23
then dynamically updating them with the necessary prefixes.
29:27
Code editors like Sublime Text and Coda
29:31
also have prefixer plugins you can use right in the code editor.
29:34
Next, if it's necessary, we'll need to provide a fallback method
29:42
for some of these CSS3 features,
29:46
because first we'll need to always develop with progressive enhancement in mind.
29:49
With progressive enhancement we start from a basic working example as our
29:56
foundation so it's an experience that all browsers will be able to provide to our users.
30:01
We then add those enhancement layers one by one.
30:08
With progressive enhancement it's important that we start with
30:12
semantic, well-strutured markup, then add that CSS layer
30:15
followed by the JavaScript layer.
30:20
This minimizes dependencies on a lot of CSS3 features
30:23
because we don't sacrifice the accessability for convenience.
30:28
We can also use feature detection as a last resort.
30:33
Now a really useful tool for feature detection is Modernizr.
30:38
Modernizr is a powerful JavaScript-based library
30:43
that detects support for html5 and CSS3 features.
30:48
It then allows us to provide a fallback
30:52
for those browsers that do not support certain features.
30:55
Modernizr tests for over 40 features in a matter of milliseconds, so it's really fast,
31:00
but we shouldn't need to include the entire library.
31:06
We can actually create a custom build only for those features we need.
31:10
Finally, there are tools that can help us write CSS using a lot of these best practices.
31:16
One of those tools is CSS frameworks.
31:24
With CSS Frameworks all these best practices are already baked in.
31:28
A good one to use is Foundation by ZURB.
31:34
There's also Twitter Bootstrap and others.
31:37
It's important that we do not use a framework just because
31:42
you don't understand CSS best practices.
31:46
We should use a framework to speed up our work flow,
31:50
so to make us faster, not necessarily better at CSS.
31:53
Next, another helpful tool is CSS preprocessors.
31:58
Preprocessors save us a lot of time writing CSS,
32:02
and they make our CSS modular and easily scaleable.
32:06
A lot of the useful features in CSS preprocessors are
32:11
being able to create variables, nest selectors,
32:15
create mix ins, and do math functions, along with a lot more features.
32:19
Some of the most popular CSS preprocessors are Sass, Less, and Stylus.
32:24
Preprocessors do require a bit of a learning curve,
32:30
but just remember that it's CSS after all,
32:34
and they're not a new language, just a new syntax.
32:38
Okay, so that will do it for our workshop on CSS best practices.
32:41
As we've learned, it's important we continue using
32:46
those best practices throughout our development process.
32:49
To learn more about CSS check out our learning adventure
32:52
on becoming a web designer or developer and our Deep Dives on html and CSS.
32:55
I'm Guil Hernandez, thanks everyone.
33:01
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up