If you’ve ever done web development, or worked with web developers, you’ve probably heard that CSS is the bane of our existance. To the contrary, I’ve actually begun to really enjoy using CSS, it just took a lot of figuring my way around things.

Most people's experience with CSS.

This article covers some of the things that have helped me to make CSS not just tolerable, but even – dare I say it – enjoyable to use.

box-sizing: border-box

I include the following in every website I develop, and I’ve never had problems with it.

*, *:before, *:after {
  box-sizing: border-box;
}

By default, browsers use content-box, this rule sets the box-sizing mode to border-box for all elements and pseudo-elements (:before and :after) on every part of the website. With box-sizing: content-box, the dimensions of an element can grow to accomodate padding, whereas border-box retains a fixed height and width with padding being “inset” within the element.

The best way to explain how the two differ is with an image.

The difference between `content-box` and `border-box`.

If you’re using third-party plugins, scripts, etc. this may cause their layout to break, but it can be overridden on a case-by-case basis as necessary by applying box-sizing: content-box to the problematic element’s respective CSS selector.

Use a CSS pre-processor

Currently, the two largest CSS pre-processors are SCSS and LESS. Of the two, I would personally recommend SCSS, as LESS has some weird quirks like calc() not always working as expected because LESS performs the math when processing your stylesheets. So calc(100vw - 20px) in LESS is delivered as calc(80px) to the browser. Other than that, they have essentially identical feature-sets.

Why use a pre-processor? They make CSS a lot simpler, and therefore faster to both write and read.

You can take code like this:

.container {
  display: block;
  text-align: center;
}

.container li {
  display: inline-block;
  padding: 5px;
}

.container li a {
  font-weight: 500;
}

.container li a:hover {
  text-decoration: none;
}

And rewrite it like this instead:

.container {
  display: block;
  text-align: center;

  li {
    display: inline-block;
    padding: 5px;

    a {
      font-weight: 500;

      &:hover {
        text-decoration: none;
      }
    }
  }
}

With vanilla CSS, you’re not able to nest selectors. SCSS and LESS allow you to do this and a lot more, and they provide no performance hit for the user. CSS written with a pre-processor are “processed”, or compiled, down into vanilla CSS by the server, and that CSS is sent to the client for parsing.

Besides nesting, SCSS also includes variables, functions, mixins, and color modifiers.

Variables are represented by a $, and can be used anywhere in a stylesheet after being defined.

$brand-color: red;
$header-width: 100vw;

.header-text {
  color: $brand-color;
  width: $header-width;
}

For more complex websites with more than one stylesheet, you can use @include to include variables from a distinct _variables.scss file.

/* _variables.scss */
$brand-color: red;


/* header.scss */
@include 'variables.scss';

.header-text {
  color: $brand-color;
}

Also note that there’s a difference between “Sass” and “SCSS”. “Sass” doesn’t include any brackets or semicolons, it looks like this:

.container
  display: block
  text-align: center

  li 
    display: inline-block
    padding: 5px

Personally, I prefer SCSS because it’s closer to vanilla CSS, so you’ll be able to more easily follow CSS tutorials, better understand open source examples, and be able to write vanilla CSS or use other pre-processors should you ever need to. I also personally find SCSS easier to read, with an easily understood, well-defined visual hierarchy.

More information about using SCSS and its features is available in the SCSS documentation.

Avoid using float

I’m sure others will disagree with me on this, but I have tried to avoid using float in almost all my projects. Those that I have used float in have had their fair share of problems because of it. Perhaps my problems stem from ignorance, in which case I’d love to be told how to correctly use floats.

When writing stylesheets I’d prefer to write once and have it work everywhere. Of course, that isn’t usually a reasonable expectation. When using flexbox for layout, it’s at least made relatively simple, with only a handful of properties to modify if you’ve set things up correctly. When using display: flex, the float property will no longer work for elements within a flexbox container.

With flexbox, modifying a list of “cards” that fill the full width of the page on mobile to become listed horizontally and overflow into more rows as screen size increases is as easy as:

.cards {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
}

.card {
  width: 100%;
  max-width: 300px;
}

No need to change anything between platforms for this to work, it just does. If your layout requires using a lot of float, using flexbox becomes significantly more difficult.

A common reason to use float is to align content to the right side of the page. However, this brings its own complications.

Let’s say you have a list of navigation elements:

<header>
  <ul class="header-left">
    <li>Home
  </ul>

  <ul class="header-right">
    <li>Messages
    <li>Notifications
    <li>Profile
  </ul>
</header>

If you apply the following CSS, the expectation would be that Profile is the right-most element, because it’s listed last in the HTML, correct?

.header-right li {
  float: right;
}

The problem is that float actually places “Messages” as the right-most element, then “Notifications” and “Profile” are placed to the left of “Messages”. You could fix this by applying float: right to the header-right class instead of the list items themselves, but what if you wanted to add a search box to the inside of the right side, certainly it wouldn’t go inside the header-right element? It isn’t a list item like the other navigational elements. So you’d need to place it outside of the unordered list, and apply float: right to it as well. However, it would have to go after the header-right element if you wanted to place it on the inner side of the right-aligned navigation elements.

The point I’m trying to make is that the float property tends to cause unnecessary complexity and unexpected results. As with all things, there are exceptions to these rules. Float can be very useful in articles if you’re trying to get text to flow around a picture, for example. That said, I believe that – as a means of aligning items in a layout (i.e. a navigation bar, header, etc.) – there are many means of achieving this which simply work better.

Understand selector specificity

I won’t cover this myself, as others have covered it better than I can, but Shay Howe’s getting to know CSS guide is great for this. This is an incredibly important concept to understand.

Always avoid using !important

On the topic of selector specificity, !important is a common way of hacking around the specificity hierarchy for newer web designers and developers. I would advise strongly against this practice, as it can become a nightmare when misused.

The key thing to understand with regards to !important is that it breaks the delicate specificity system. It overrides all style rules regardless of their specificity. The only rules capable of overriding an !important declaration are in-line styles with !important declarations themselves.

For example:

.colored-text {
  color: red !important;
  text-align: center;
}
<div class="colored-text">This text will be red.</div>

<div class="colored-text" style="color: green !important">This text will be green.</div>
This text will be red.
This text will be green.

Except in the cases of !important and in-line styles, there will always be a way to override another selector’s properties. !important, especially when a site becomes larger, with hundreds or thousands of different CSS classes and IDs, using !important will only cause headaches down the road.

Wrapping up

I want to note that I’m not saying CSS is infallible and some great style language. It should have sensible defaults, but sometimes it doesn’t – usually for backwards compatibility reasons. Ideally it wouldn’t require experience with every CSS property to throw together a relatively simple website, but I’d challenge you to develop a stylesheet language that works in as many use-cases as CSS does, as well as it does.

If you want to learn more about web development, I’d definitely recommend checking out these links: