3 Things (Almost) No One Knows About CSS

Think you know CSS? If the results of a free CSS test I’ve offered online for the past six months are anything to go on, plenty of practicing developers don’t know CSS as well as they think. Out of over 3,000 people who have taken the test so far, the average score was just 55%.

But hey, an average isn’t that interesting by itself. I was more curious about which questions people were getting wrong. For this article, I’ve run the numbers, and zeroed in on three questions where people scored especially badly. I’ll talk you through each question, show you the answer that most people chose, and explain the correct answer.

It’s safe to say that if you take the test yourself after reading this, you’ll have an unfair advantage!

Question 1: How Best to Set line-height

This first question should have been easy for anyone who deals with text styles on a regular basis:

You want text on your website to be double-spaced by default. Which of the following line-height values is the best way to achieve this?

  • 200%
  • 2em
  • 2
  • double

With four answers to choose from, you’d expect 25% of people to get the right answer by luck alone, and only 31% got this one right! Take a minute and pick out an answer for yourself, then read on.

First off, double is a red herring. The only keyword value that line-height accepts is normal. I’m happy to say that only 9% of people fell for this one. The remaining three answers were all pretty popular, though.

The answer that most people selected is 2em (39% chose this). Indeed, 2em will certainly give you double-spaced text for the element it’s applied to; but so will 200%, and only 21% liked that answer! Either ems are much more in fashion than percentages, or people don’t really understand them.

The correct answer, though, is 2.

This is a lesson that was drilled into me a long time ago, when I was first learning CSS. Always specify line-height as a unitless number; that way, descendent elements that specify a different font-size will inherit that number rather than a fixed line height.

Let’s say the page has a default font-size of 12pt, but it also contains a heading with a font-size of 24pt. If you set the line-height of the body to 2em (or 200%), then you’ll get a line height of exactly 24pt (twice the body’s font-size) everwhere in the document—even in that heading. The heading will therefore be single-spaced, not double-spaced!

Setting line-height to 2 instead tells the browser to preserve the font-size/line-height ratio even when the font size changes. The line height for the body will be 24pt, but for the heading’s 24pt font, the line height will automaticlly increase to 48pt.

Question 2: How to Make Elements Overlap

This question was a bit trickier. It called for some experience of the “dirty tricks” that CSS layout often requires:

Which of the following CSS properties, used by itself, can cause HTML elements to overlap?

  • z-index
  • margin
  • overflow
  • background

Got an answer picked out? Okay, let’s dive in.

Once again, there was an easily-eliminated option: background. All but 2% of test takers steered clear of it, knowing that it controls background colors and images.

Unfortunately, most steered straight into z-index. A full 46% of people jumped on that one. I’m guessing it’s because no one really understands how z-index works. In fact, setting the z-index property by itself has no effect whatsoever; you also need to set the position property of an element for z-index to do anything. In short, z-index lets you control the stacking order of elements that do overlap, but they need to be overlapping in the first place. MDN has a really nice article called “Understanding CSS z-index” that’s worth a read for more detail.

overflow should have been easy to eliminate too, if you’ve ever used it. It controls how content that doesn’t fit inside a sized box behaves: whether it’s chopped off, whether it flows out past the edges of the box, etc. Again, this depends on the box’s size being constrained with other properties; by itself, it won’t cause overlaps. Still, 22% of people thought it might.

That leaves us with margin, which is the right answer. Only 30% of people got it. You might wonder how on earth a property that creates distance between elements can cause them to overlap. If you’ve done any real-world CSS layout, the answer should be obvious: negative margins make things overlap.

To demonstrate this, create a page with two div elements. Set the margin-top on the second div to a negative measurement, for example -100px. Bam! The second div now covers the bottom one hundred pixels of the first div.

In practice, you’d almost never overlap blocks like this on purpose, but negative margins are extremely useful for squeezing HTML elements into places they don’t normally go. I often use them to push left- or right-floated elements into the padding region of their parent box.

Schematic of a right-floated box resting against the right border of its parent

For web design history buffs, in 2005 overlapping elements with negative margins is what made possible three-column page layouts such as the so-called One True Layout (and later the Holy Grail layout).

Question 3: Pseudo-elements vs Pseudo-classes

This last question is a bit of a cheap shot, I’ll admit. But with only 23% of test takers able to answer it correctly (that’s worse than chance!), it clearly hits on a point of confusion:

Which of the following effects is best achieved using a pseudo-element?

  • Add a drop-shadow to a hyperlink when a user hovers their mouse over it.
  • Display the label of a checkbox in a different color when the checkbox is checked.
  • Give the even and odd rows of a table different background colors.
  • In a flexible page layout, display the first line of a paragraph in bold text.

Three of these choices are effects you achieve with a pseudo-class; only one involves a pseudo-element. Can you tell the difference?

A pseudo-class is a particular state in which an actual HTML element can find itself. Think of it as a virtual class that is applied to the element automatically by the browser under certain conditions.

A pseudo-element is a part of the document that CSS lets you style even though it isn’t an actual HTML element. It’s like a virtual HTML element—something you get to style even though it doesn’t have actual HTML tags around it.

With this distinction in mind, let’s run through the options:

Add a drop-shadow to a hyperlink when a user hovers their mouse over it.

A hyperlink is an actual HTML element. Applying styles to it only in a particular situation (when the mouse is over it) means we’re using a pseudo-class. The pseudo-class you’d use in this case is :hover.

22% of test takers thought this was a pseudo-element.

Display the label of a checkbox in a different color when the checkbox is checked.

Again, a label is an actual HTML element, not a virtual one. When a checkbox is checked, the browser applies the :checked pseudo-class to it. You can then use it in your selectors to style the checkbox, or even a label next to it (e.g. using an adjacent sibling selector with +).

20% of test takers thought this was a pseudo-element.

Give the even and odd rows of a table different background colors.

This is the one that really fooled people, but once again we’re talking about applying styles to actual HTML elements (tr elements, in this case). A tr being even- or odd-numbered within its parent element’s collection of children is just another circumstance that you can match with a pseudo-class.

In this case, the pseudo-class is :nth-child(even) (or :nth-child(2n)) for even elements, and :nth-child(odd) (or :nth-child(2n+1)) for odd ones.

I’m guessing it’s just because :nth-child and pseudo-elements in general both sound like really obscure CSS features, but a full 36% of test takers picked this as a pseudo-element.

In a flexible page layout, display the first line of a paragraph in bold text.

This, of course, is the right answer. And by now, hopefully, the distinction is clear. In a flexible page layout, you can’t look at the HTML code of a page and say “that element there contains just the first line of the paragraph’s text”. The browser does the word-wrapping depending on the width of the paragraph, which is something you don’t get to control in a flexible page layout.

:first-line is the pseudo-element that lets you apply styles to the first line of text in a block, no matter where that first line wraps to the second.

If you’re thinking “OK, sure, that all makes sense, but c’mon—no one knows the difference between pseudo-elements and pseudo-classes”, well the W3C agrees with you. In the CSS3 Selectors spec, in an attempt to distinguish the two, it changed the syntax so that pseudo-element selectors use two colons (::first-line), while pseudo-classes still use one (:hover). Of course, for backwards compatibility, browsers must support both versions.

So yeah, like I said: cheap shot. But hey, if you’re a CSS geek like me, I imagine you’d know your pseudo-elements from your pseudo-classes.

How’d You Do?

So that’s it: three tough questions from the test. If you answered just one of them with confidence, you’re doing okay. Got two of them? Not bad at all. If you got all three, I’d love to hear from you! Especially now that I’ve given away the answers to these, I could really use some ideas for more tricky CSS questions. Post ’em in the comments!

If you enjoyed these questions, maybe you’d like to give the rest of the test a try. Rest assured, the other questions are much easier than these … mostly!

Sponsors

No Reader comments