Learning Principles for Improving Your CSS

This article will cover some basic principles and tips on how to learn and become better at CSS, based on personal experience.

In today’s article I will mostly talk about my own experience, and what I have learned about CSS after almost one year and a half of heavy practicing.

First, let me remind you that CSS is an extremely simple language. It can be summed up in 3 words: selector, property, value. Nothing more, really. This is why some people don’t like CSS at all: because they feel like children playing with LEGOs.

Yup. Explain the basics of CSS to a 9 years old child and he or she will be able to create a website. Not a complex one I agree, but maybe a few pages with headers, links, content, images, and such.

But the fact that CSS is an easy language doesn’t mean everyone is on the same level. Some people use CSS like a chimp uses a fork, some people are okay to good with it, and some people can do magic with it.

From what I can tell, I’ve been playing around with CSS for almost two years now and on what I would call a heavy level for something like 7 months. I’m still far from perfect, and there are still some tricks I don’t know or understand.

Anyway, there are a few things I understood over the months and I’d like to share them with you. One more time, it’s not code snippets or useful tricks, it’s more like general principles and good practices. Here is what I will cover:

1. Don’t rush your code & keep it simple

Don’t rush your code

This is more like a general advice, it’s not specific to CSS. When you’re about to develop something, start by thinking about it. Ask yourself a few questions:

How would I do this?

Is there another way?

How can I optimize it (to be maintainable, clean, cool, etc.)?

Rushing into the code may lead to time loss. What if you spent one hour creating something to realize you can’t do it this way and have to start all over again? This shouldn’t happen.

Spending hours on a CSS slideshow to end up with SlidesJS or Adaptor is a shame. Not because you didn’t succeed, but because it was a complete waste of time. On a tight deadline, you may suffer from such a mistake.

Keep it simple

CSS is a simple language but things can easily become complex. Especially if you want them to be. In most cases, the simplest idea is the better idea. When you want to achieve something, always ask yourself if there is not a simpler way to do it. You’d be surprise how often the answer is ‘yes’.

As an example, if you want a really simple horizontal navigation with only links, you have multiple ways to do this:

Float the list elements

Set the list elements to inline

Set the list elements to inline-block

Pick the simplest and set the list elements to inline. No need of a clearfix hack. No need of an inline-space fix. It only needs a regular padding, nothing more. End of story.

2. Know the basics and learn the tricks

To be good at CSS, or to be good at anything in life, you have to know the basics. You can’t become a maestro if you’re not comfortable with the most common things in the discipline.

The basics of CSS

What are the basics in CSS? Everybody will tell you a different story; it’s more like a feeling thing here, but if you want my opinion, there are two things to understand above all to really get into CSS:

The box-model. Every single element in CSS is a box (block or inline), with a width, a height, and eventual padding, margins and borders. Most important thing ever. Read more about it here.

The “stacking context” trick

Every single front-end developer in the world struggled at least once with stacking context issues. Basically, it means you can’t apply z-index to a child of an element (or a pseudo-element) which has already a stacking context (triggered by either z-index or opacity or a transform); there is no workaround. Once you know it, you don’t forget it, trust me.

The “I forgot to clear the floats” trick

Your layout is going crazy. Blocks are flying everywhere. You’re crying because you don’t understand what you did wrong. Then check your floats! In most cases, you just forgot to clear them.

Note: if a parent only contains floated elements, it will collapse on itself unless you clear the floats, or set its height / overflow.

I could go on and on with this stuff, but it’s not the goal of the article. My point is that CSS has a lot of special and peculiar cases and people discover new ones everyday. You’ll have to get stuck on some of them to know they exist and how to deal with them next time.

3. DRY

DRY stands for Don’t Repeat Yourself, and once again it’s not specific to CSS. It’s more like a common practice when you’re coding, whatever the language you’re dealing with.

So the main idea is to avoid repeating the same chunks of code X times when you can do it only once. In some languages, it can mean using functions but in CSS, it often means using reusable classes instead of targeting a specific element (more on that in the next section about OOCSS). However, sometimes it’s something really simple like refactoring. Let me explain myself.

If you happen to spot a snippet of code multiple times in your style sheet, it could be a good idea to refactor it in order to end up with only one occurrence. Have a look at the following:

See? You may wonder what the point of this is since the result is clearly the same. There are two things to consider: performance and maintainability.

About performance: less lines means faster parsing for the browser’s CSS parser. To put it simple, the parser will apply the color to both rules at once instead of doing it twice.

About maintainability, I think it speaks for itself. By doing this, you only have to change one line instead of two if you have to edit the color. Okay, no big deal when it’s only 2 lines to edit. But what about 50? Or 300?

Further readings on DRY CSS

4. OOCSS

What is this thing?

OOCSS stands for object-oriented CSS. You’ve probably all heard about object-oriented programming languages. Basically, it means using “objects”, usually instances of classes (which consist of attributes and methods). So you may ask, what the relation with CSS could be?

First of all, let’s say it’s more like a concept or best practices than a real thing. CSS can’t really be object-oriented since it’s not a programming language: there are no namespaces, no functions, no methods, no programming classes, no conditional statements, etc. This is why some people will laugh when you talk about OOCSS.

Even if I have to agree with this, we can still optimize the way we do CSS to ease the process, make websites faster and improve maintainability.

How do we do that?

To put it very simple, it means using classes. A lot of classes. Think of your website with “modules” or “components” if you want. Try to spot repeated patterns and make them “objects” (classes) in order to reuse them.

To be a little more precise, it would mean essentially two things:

Separate structure and appearance

Separate containers and content

Separate structure and appearance

Separate structure and appearance can be important since graphical stuff can be used in multiple places on the website and in various types of elements, right? Take the following chunk of code, it can fit to a button, to a box, to a picture, whatever:

This results in a much more comprehensible and maintainable style sheet and faster parsing.

Separate container and content

I think this is one of the most important rules of OOCSS: code independent components, not stuff for a specific place in your current design. Things should be reusable whatever their place on your site is without coding them again. Let’s take the following example:

Okay. Now what if I want the exact same styles on a level-2 heading in the footer? Or, to style a level-3 heading in the exact same way (for whatever reason)? The right way to go would be to create a class and give those styles to this class, not to the elements itself.

What about the “never use IDs” thing?

When Nicole Sullivan came up with the concept of object-oriented CSS, this one was one of the hottest topics. Indeed CSSLint, a CSS code quality tool by Nicholas C. Zakas and Nicole Sullivan, recommends against the use of ID selectors.

To understand Nicole’s point of view, it’s important to understand that IDs can involve some specificity issues since they have the highest specificity score. Take the following code as an example (from CSSWizardry – source here):

[…] I have decided that a blanket ban is sensible. Save yourself many potential headaches and never use IDs in your CSS files.

But of course, IDs can in principle still be used and are perfectly valid.

What’s my feeling about OOCSS?

As far as I’m concerned, I’m not entirely familiar with it. Mostly because I’ve never worked on a huge website involving multiple front-end developers. Let’s face it, this is probably very useful for larger architectures, but not for the little one-page website you do for your baker.

However, even if I don’t use OOCSS in my projects, I try to focus on important things like reusability of components, maintainability of the style sheet, performance and such. Those are the things OOCSS focuses on, so in some way, I’m not so far from it.

Further resources on OOCSS and the ID question

5. CSS3: learn what you can do and what you can use

Okay, enough with concepts. Let’s talk about real stuff. Let’s talk about CSS3. Although there is not really one thing called CSS3:

Unlike CSS 2, which is a large single specification defining various features, CSS 3 is divided into several separate documents called “modules”. Each module adds new capabilities or extends features defined in CSS 2, over preserving backward compatibility. […] Due to the modularization, different modules have different stability and statuses.

But let’s agree that we are talking about the new features that modern browsers understand.

Nowadays, CSS3 is everywhere: from border-radius to gradients, from transparency to shadows and pseudo-elements.

Learn what you can do

In my opinion, you can utilize CSS3 is to reduce the number of HTTP requests (images), the size of the markup and JavaScript resources. Let’s have a closer look:

Border radius: 1 line of CSS instead of 4 containers + 4 images

Opacity and alpha channels in color: 1 line of CSS instead of a semi-transparent PNG

Advanced selectors: no need for JavaScript

Flexbox: a few lines of CSS instead of a whole JavaScript library

Gradients: a few lines of CSS instead of a repeated background image

Multiple backgrounds: no need for multiple containers

Pseudo-elements: no more extra markup for decorative elements

And I could go on and on but I think you got it. My point is: learn what you can do with CSS3. You have to create a table of contents? You should know you can do it with pure CSS thanks to CSS counters. You need to set a fancy custom border for this client site? You should know there is a border-image property to do this.

You can do a million things with CSS, and it’s even more true when it comes to CSS3. It’s important to know what you can do, and what you can’t. Sadly, there is no magic potion for this, you have to read the documentation and explore. From there, you’ll learn that you can make calculations with the calc() property but you can’t achieve 6 perfect equal heights columns layout without to struggle like hell.

Learn what you can use

The biggest problem with CSS is the fact that not all browsers support the same properties. Worst, they don’t even handle some properties in the same way when it comes to CSS3. This will be your biggest curse when experimenting with CSS3.

As an example, take the simplest CSS3 and well-known property ever: border-radius. Well, there are still browsers being used that don’t understand rounded corners (IE8 and below and Opera Mini). Actually, even Firefox and Chrome don’t render border-radius the same way (or haven’t always done).

What does this mean for you as a front-end developer? It meant that if you have to display rounded corners in ALL browsers, you’ll can do it the old fashion way: multiple backgrounds + multiple images or do it both ways and serve the right one to each.

Not bad, but not perfect. IE8 and below and Opera Mini don’t support CSS gradients.

Is it an enhancement or a vital feature ?

It’s more like a graphical improvement, no big deal. I’ll add a plain color as a fallback.

It’s a compulsory graphical element: I have to make it work for unsupported browsers.

How am I going to make it work on unsupported browsers ?

I’ll have to use a background image.

Thanks to this little step-by-step process you know how to do something with CSS (if it can be done), if you can use it concerning browser support and how to create fallbacks.

Note: always remember the target audience of your website or application. If you’re creating web content for an iPad app or a flexbox explorer, you will be able to use a lot of CSS3 features without worrying about fallbacks. However if you’re building a website for a bank, remember a lot of people still use IE8 and below.

Providing fallbacks

Depending on the situation, providing a fallback for unsupported browsers can be either ridiculously simple or super annoying. Indeed, there are different cases. Let’s see.

No fallback or simple fallback

When it’s some kind of user experience improvement with no consequences when unsupported, you’re not even forced to provide a fallback. This is cool.

There are also some properties which are easy to deal with when it comes to fallbacks. Generally, you only have to write two versions of this property: first, the fallback, then the cool version for browsers that support it.

In this case, browsers not supporting rgba and hsl won’t read the lines 3 and 5, so you provide alternative versions on line 2 and 4. For supported browsers, they will first apply the alternative version then override it with the cool one.

Modernizr

Nowadays, we can hardly talk about CSS3 without mentioning Modernizr. It’s a JavaScript library that tests support for HTML5 and CSS3 features on page load. This may sound heavy, but it’s well optimized and quite fast.

Anyway, sometimes you have to know exactly if the browser is supporting one specific feature. For, let’s say, providing an alternative version requiring other CSS properties.

To provide such a fallback, you have to rely on classes added by Modernizr (.no-opacity and .no-pointerevents). You can’t have both versions simultaneously.

Whatsoever, please always remember to draw fallback, this is really important. Vital features have to be supported on all browsers old as well as new, and if in any case they are not, you have to warn your user.

So either you start with a simple basis and improve it for recent browsers, or your start with a modern basis and you decline for older ones. More on that in the next section.

Further resources on CSS3:

6. Progressive enhancement and graceful degradation

Those are two terms you’ve probably already heard about, especially graceful degradation, however there is a subtle difference between both.

Progressive enhancement

Progressive enhancement is when you establish a baseline of usable functionalities and features and then improve the user experience according to browser support.

Using the HTML5 required attribute to warn the user that a field is missing before submitting can be considered a progressive enhancement. It’s improved user-experience speaking thanks to the native browser engine.

Graceful degradation

You got graceful degradation when you provide an alternative or lower version of your features in case they are not supported. Basically, it’s going from top to bottom.

A very simple example would be the warning you put between the <canvas> tags to inform users with browsers that don’t support it that there is something they can’t see.

<canvas>
This page uses HTML5 Canvas. Please use a recent browser to see this content. To get another browser, go to <a href="http://browsehappy.com/">BrowseHappy</a>
</canvas>

What’s the difference?

In the end, there is none. You have features for advanced browsers and features or fallbacks for legacy ones. It’s more a process thing: either you code for the cool browsers, giving fallbacks for the old ones, or you do it the other way. It’s up to you.

Anyway, my point is: user experience doesn’t have to be the same in all browsers. Actually, it’s not even possible since browser engines are different. Whatsoever, you have to provide basic features for everyone, but please improve your website or application for modern browsers. They are good, they provide native features: use them.

Further readings on progressive enhancement and graceful degradation

7. CSS preprocessors

Aaaah, preprocessors… The hot question at the moment. Are they useful? What for? Should I use one? Which one? I think this is one of the most debated topics about CSS at the moment.

I’ll try to be as objective as possible for this section. Let me start with this: if you don’t want to use a preprocessors, then don’t. This will never be an issue. This will not make you a bad front-end developer. This will not make you unable to do some kind of things. But you should give it a try to make your own opinion about it.

Okay, enough with the disclaimer. What is a preprocessor, generally speaking? A preprocessor is a kind of tool that compiles a given syntax into an actual language used by another program (in this case: the browser). There are preprocessors for many languages: there is Markdown or Jade for HTML. There is LESS, Sass and Stylus for CSS. There is CoffeeScript for JavaScript. There is CakePHP for PHP and so on.

Basically the preprocessor will translate this into the regular CSS version. It will be exactly the same, except for the calculation. It will run the operation itself and display the according result without any need of the calc() function.

So you end up with a more comprehensible (nesting and variables) and maintainable (variables and functions) style sheet. It was a very dummy example, but in a real project, you will feel the difference.

How to choose one?

There are a few CSS preprocessors out there, each one with its own advantages and particularities. Anyway, all of them do more or less the same stuff, so the one you choose is really up to you. Here are the main options when it comes to CSS preprocessors:

The best way is to get to know them and experiment and see what fulfills your and your project’s needs best. There are many factors that play a role; listing them all would be out of the scope of this article but you can find some relevant resources below.

What’s my feeling about CSS preprocessors?

I’m not an expert when it comes to CSS preprocessing, but I like it. It provides very useful features missing in CSS like variables, nesting and conditional statements.

I’ve played a little with LESS, and it did pretty much what I wanted. At least until I started things a little bit more complicated as you may have read in my last article about CSS Loading Animations (for loop + vendor prefixing + keyframes).

I also gave a quick shot to Sass and Compass. To my surprise, it was incredibly easy to install and run through Ruby. I was scared but it’s very very intuitive, trust me. So in the end, Sass + Compass looks amazing, seriously. You can also read more about why I switched from LESS to Sass in this article on my blog.

Anyway, I’m still completely able to write regular CSS without a preprocessor, and most of the time this is what I do. But in the end, I think we will all use one, whichever it is. CSS really lacks some useful things, and CSS preprocessors are here to fix this.

Further readings on CSS preprocessors

8. Keep an eye on the future

Languages are evolving. It’s very true with CSS. CSS specifications are never finished, and browsers are not waiting for them to add new features to their engine.

Regarding this, my best tip would be to stay alarmed about what’s coming. I know you may not be able to use it right on launch, but knowing which feature is now in Chrome Canary, soon in Chrome stable and Safari, then Opera, then Firefox and so on, is important in order to gain perspective of what the CSS problems and possible solution are.

9. Read other people’s code

One of the best ways to learn how to code is to read code. Thankfully, CSS is client side, so you can read it on every single website on the web with a web inspector like WebKit Inspector, Dragonfly, Firebug, etc. Plus, the web industry is somewhat really focused on open-sourcing, meaning people are glad to share their sources with you.

Another great way to learn is to follow tutorials. Take an easy tutorial, and do it step-by-step. Then try to redo it from scratch. If you happen to be stuck, have a glance at the solution, then continue by yourself.

When you’re comfortable with CSS and want to get deep into it, you might want to have a look at unexplained demos and experiments. People create stuff everyday, you’ll always find something you can’t do.

Further resources to find examples of other people’s code:

10. Keep practicing

You know what’s said about learning: we learn by doing. So my best advice is to keep practicing as for anything else. The more you practice, the better you’ll be. Practicing doesn’t necessarily mean doing a website from scratch. Just pick a simple shot on Dribbble and try redoing it with pure CSS. The result may not be useful, but what you’ve learned, definitely is.

And as I said before in “Know the basics and learn the tricks”, CSS is full of special cases. Learning how to deal with them is part of the job in writing CSS. And the only way to know they exist is to practice, find one, have a look at the solution, and go on.

I’d also suggest you to share your code. It’s always helpful to get constructive feedback, so be sure to ask people to review your code once close to be finished. Simply drop them in a JSFiddle, share and ask for feedback.

Index and credits

Since this article mentioned a bunch of various links and resources, let me gather them all in the same spot:

I definitely disagree with Sullivan on the ID practice though. Aside from the CSS arguments, it would make for very poor Javascript performance. Using IDs to search the document has been benchmarked at over 100 times the speed of classes.

Great article though! You really hit on some of the more intermediate concepts that are less talked about. I’ve just switched over to SCSS and not looking back.

I don’t think “whatsoever” doesn’t mean you think it means.
Fair article though. Re: OOCSS, guidlines and such, I always like to refer back to https://github.com/csswizardry/CSS-Guidelines. You might want to look at the OOCSS section though. A better example would be, if I am not mistaken, something like the following…

.superset
.superset__subset
.superset__subset–variation

Or as taken from git
.person{}
.person–woman{}
.person__hand{}
.person__hand–left{}
.person__hand–right{}

Though, I have to admit that I don’t always follow these guidelines religiously.

1) Progressive enhancement and graceful degradation aren’t just about the regular desktop browsers, it’s also about going mobile.
When you’re going for progressive enhancement, you should start from the smallest device you’ll be supporting and work your way to the full desktop experience. You’ll of course start with less functionality and end up with all functionality.

Graceful degradation is the opposite of course, desktop to mobile and leaving out functionality.

2) You should really be careful with preprocessors. Most of the time, preprocessors shorten your coding time, however they don’t always shorten your actual rendered css code. So just think about how it will be rendered before you go either way.