12 CSS tips and best practices

Technology
Roberto Ibarra

Roberto Ibarra

CSS, the language that defines a website’s presentation, is easy enough to learn at first.

However, writing it well is another skill entirely, and one that’s essential in professional web development.

Several ways exist to accomplish things in CSS*, and some are better than others. In a software project, multiple team members will access and change CSS files. If everyone doesn’t follow the same standards, the code can break and need to be rewritten. Therefore it’s necessary for developers to stay current with best practices, or at least be on the same page as their teammates.

*CSS (Cascading Style Sheets)

Our team’s tips and best practices for writing CSS

1. Make it readable

Write using multiple lines, giving a line to each property. While there are a few cases in which single-line CSS may be more readable, the fact is most people prefer multi-line CSS.

The theory behind multi-line CSS is that it’s easier to find specific properties, as in the example below: 

Single line:
.class {color: #fff; text-align: center;}
Multi line:

.class { 
  color: #fff; 
  text-align: center;
}

2. Use a reset

To deal with browser inconsistencies and avoid unpleasant surprises, use a reset.

A reset can be anything from a few lines of code at the top of your stylesheet to a full library of styles like sanitize.css. The overall goal is to make styling consistent across all browsers.

Note: With a CSS framework it’s not necessary to use a reset.

The strategy of a reset varies. The main types are summarized in the table below:

3. Follow an organizational pattern

Stylesheets should be organized in a consistent way that makes it easy for everyone on a project to find sections of code.

We use the following index:

  • Reset
  • Font-face (when needed)
  • Layout styles
  • Global styles
  • Page sections, in the order in which they appear (header, nav, home, internal pages, footer)
  • Media queries
4. Use shorthand properties

Save time and make your CSS more readable by using shorthand properties. These allow you to condense multiple properties into one convenient property.

It’s important to know how shorthand properties work before using them. You can unwittingly override previously defined styles, as values not defined in the shorthand property will be set to their default.

For example, in the following code:


body  {
  background-color: #f4f4f4;
  background:
no-repeat
url("img_cat.gif")
fixed center; }

The resulting background color will be transparent, the default value.


Mozilla’s web docs are a useful reference for shorthand properties.
https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties

5. Go easy on specificity

In the spirit of keeping code as clean as possible, try to use the minimum amount of selectors needed to apply a property. Whenever possible, don’t get more specific than .class.

Of course, it may be necessary to use more than .class, particularly when applying IDs. In the specificity hierarchy (ID > Class > Element), IDs trump classes. Yet a selector like div.class is more specific than an ID.

For example, in the following code font-size: 12px takes precedence, no matter the order in which it appears. 


#real{
  font-size: 12px;
}
.fake{
  font-size: 14px;
}
div{
  font-size: 18px;
}

But in the following, font-size: 14 wins because div.fake is more specific.


#real{
  font-size: 12px;
}
div.fake{
  font-size: 14px;
}
div{
  font-size: 18px;
}

6. Format classes correctly

Use the – separator when writing classes, not camelCase or _.

Correct: first-section

Incorrect: firstSection, first_section 

7. Space out multiple selectors and long properties

Use line spaces to make reading stylesheets easier.

Correct: 


h1,
h2,
h3,
h5{
  background: 
    url('a long URL') 
    no-repeat 
    left bottom
    other-property: ....;
}
8. Respect the awesome power of !important

This property should be used only as a last resort when specificity doesn’t work. Usually this happens with inline styles or styles injected with Javascript. 

9. Use Calc()

This property is your friend. It allows you to use operators for any type of property that employs units of measure, such as height, width, font size, border, etc.

The correct way to write this is property:(x + x). Any type of operator can be used, as well as different units of measure in the same operation.

For example:


div{
   height: calc(100% - 80px);
}
10. Know your units of measure

Fonts can use a variety of measurement types, generally: em, px, pt, rem, or %. The ones most commonly used are px and em.

Em: A scalable unit equivalent to the font size of the parent document. If a <div> has font-size: 16px, then 1em = 16px and 2em is 32px and so forth, within that div and its child elements.
Rem: Also a scalable unit, but relative to the root HTML element. By default this is 16px in most browsers.
Px: Screen pixels, or the smallest division the resolution allows.
Pt: Equivalent to 1/72 of an inch. This measurement is not commonly used.
%: Percentage of the parent element’s font size.

The advantage of em is that it’s scalable, which is especially useful for media queries. All fonts declared in em will vary along with the main one. Px by contrast maintains a set size.

Em and rem can also be used for margins, padding, etc. with the same logic.

1em = the font-size of the parent element.

1rem = the font-size of the root element, <html>. By default 100% = 16px.

In other words, if a <div> has font-size: 18px, the value of 1em for its children would be 18px but the value of 1rem would be 16px (if not modified).

To make things even more interesting, we can also use vh and vw.

1vh = 1% height of the viewport

1vw = 1% width of the viewport

These are especially useful when we need an element to be relative to the screen size. It might be tempting to use height: 100%, but an element doesn’t know what 100% of its height is if not previously determined. Vh comes to the rescue in this case because it’s always using the viewport as a reference.

11. Set box-sizing

In order to determine width, CSS by default adds together element values, excluding margins.
So for example:


div{
  width: 100px;
  padding: 20px;
  border: 1px solid black;
  margin: 20px;
}

Default CSS

box-sizing: border-box

The result is a box 42px tall and 142px wide, with 20px margins on all sides.

But wait–height isn’t defined. Where is the 42px coming from?

This is because the CSS adds all the values that are inside the element. So while the default height is 0px, 20px of padding top and bottom plus a 1px of border on each side = 42px.

The same applies for the width: 100px + 20px padding-left + 20px padding-right + 1px border on each side = 142px.

To make sizing easier to manage, use box-sizing: border-box. This way the width of the element can be directly declared (in this case 100px) and the other values will be placed inside the box. If we add box-sizing: border-box to the case above, the result will be a box of 100 px with the border and padding contained within that measurement.

12. Nth your children and types

:Nth-child() and :nth-of-type() are pseudo classes that permit us to target the children or types of certain elements, within a group of siblings.

For example, in a <ul> we can give styles to some of the <li> elements and not others. And if we have a <div> encompassing different elements, we can set X element in X position to a different style.


/* Selects every fourth 
element among a group of
siblings. */ :nth-child(4n) { color: lime; } /* Selects every fourth among a group of siblings */ p:nth-of-type(4n) { color: lime; }

Both cases permit operations. For example,:nth-child(2n+1)is going to select the first, third and fifth and so forth successively because it multiplies 2 and any value, starting with zero, adding 1.

Also it’s possible to “attack” only pairs or non-pairs:
:nth-of-type(odd) or :nth-child(even)

Or only the first or last element:
:first-child or :last-of-type.

You can even count back and forth when the content is dynamic and you want to style the next to last element, third to last, etc. With an operation of type (xn + y) this would be quite complicated, so :nth-last-of-type()and :nth-last-child() exist to make this easier.

Example:


:nth-last-child(7)
/* Represents the 7th element,
   counting from the last 
   element. */

:nth-last-child(2n)
/* Goes from 2 by 2 starting 
   from the last element. This 
   would be the same as using 
   “even”.*/

:nth-last-child(3n + 1)
/* Starts from the last 
   element (3x0 = 0 +1 = 1)
   and goes to the 4th. */

The right framework for your business: Angular, React and Vue.js compared

The business risks of overlooking software documentation

The innovative launch techniques of Superhuman

Share This