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!


80% on the test.

I'd like to know what I got wrong though - there doesn't seem to be a method for seeing? Some of the questions were a bit nitpicky as to asking you to explain reasoning...

Edit-Glad I didn't get any of your article questions wrong though.

Some of the questions seemed pretty basic though...I had some questions going over a CSS rule. Who doesn't know that...?


80% on a second try and I don't know what I'm getting wrong again...Please do look into developing a feature which allows you to review what you get wrong.

Great quiz though.


84% first try. I guess we just have to keep trying until we get 100%. It would spoil the test if we were given the answers, I suppose, but it would really help to learn from the quiz if we knew what we got wrong.


84% here also.

Some of the questions were a little ambiguous and I wasn't quite sure what was being asked (although I did rush through it a bit).

Fun quiz though smile

I could really use some ideas for more tricky CSS questions. Post ’em in the comments!


div {
div div {



a) The outer div will show red for 20px and the inner div will be 20px from the top and show as blue

b) The inner and outer divs will both be blue and the inner div will be 20px from the top of the outer div making the outer div 60px tall

c) The inner and outer divs will both be red and 60px tall

d) The outer div will be completely covered by the inner div so only blue will be seen. They will have a combined height of 40px.


I'd like to know what I got wrong though - there doesn't seem to be a method for seeing?

We offer the CSS Core (practice) test, which you can take as often as you like and offers you detailed results at the end of the test, and the CSS Core test, which awards you a certificate if you get 80% or better and which you can only take once a week. Did you try the “(practice)” test?

Sounds like we need to make this distinction a lot more apparent!

Both tests cover the same material, but the questions in each come at that material from slightly different angles.


Yeah I had to make a second account to take the test again since I did get that certificate.

I did not see any option to see my results though. I assume that's not offered if you get the 80% or better? Because you can go do the test yourself and see . Perhaps I missed it both times but I don't see it.


You can still resit the test even though you’ve gotten the certificate. You can only sit the “non-practice” test once a week, though. That’s why you’d have had to create a second account.

Again, it sounds like you took the “CSS Core” test and not the “CSS Core (practice)” test. Here’s a screenshot showing the link to see detailed results at the end of the practice test.


Yes I understand. I wasn't sure if the practice one was based on the real one or what the deal was so I figured I had 2-3 email addresses in use - I'd just use a 2nd one.

Yeah I did just take the core test - what a shame though.

BTW - huge fan of your work. Great to see you on these forums.


Yeah, I get fooled by some of my own trick questions when I try to take the test quickly. wink

And thanks for the tricky question! smile


blush Thanks! Fun to have written something for SitePoint again after all these years!


I can see why you got that new laughing headshot for the article. Curse you, Yank.


Didn’t do so well, Ricky? smile


Harrumph. After 88% on the HTML test, I managed only 51% on my first pass on CSS. I'll be back.


64% on Javascript, and 80% on HTML...I'll take it smile

Did have a go at the CSS practice test and got 88%. It's fun to do these quizzes actually.


I'm not reading either the article or the answers in this topic... I didn't know about this test and I haven't done it so I want to give it a try first smiley


68%?? What the? Answered every question. I took the test on my iPhone 5 before reading this article. Not mobile-friendly at all. I got the first two questions above, but the third one wasn't on my test. 68% ... Whatevs. I'll take it again!


Yep, that’s one of the shortcuts we took to build the first version of Sit the Test more quickly. We’re actively working on making the entire app responsive, but right now it’s definitely a pain to use on a phone. Sorry about that!

The test actually contains 50 questions, and you get a random sampling of 25 every time you take it. So be prepared for a few different questions the next time you try it. smile

If you haven’t already, give the “CSS Core (practice)” test a try. When you get your score, it offers to show you Detailed results, which tell you exactly which questions you got wrong (and what the right answer for each was). You can also resit this test as frequently as you like, so you can practice until you’ve mastered the material in the practice test, then take the “CSS Core” test (which covers the same material but with different questions).


Right on man. Other than that, the site looks and works great. Great job!

I passed the HTML (barely) and got a 72 on the JavaScript; that was with a few distractions, so I ended up having to hurry. I was pretty surprised by my results. I guess I don't know as much as I thought I did. smile


The best way to learn, is to learn from your own mistakes.

It would really be great, if you could give all your incorrectly answered questions that kind of "why this is the right answer" at the end of the test. I find your article really good and I feel those kinds of explanations (a.k.a. teachings) would make the test actually quite valuable to the person being tested too. smiley



I always engage in things like this with some trepidation, partly because of trust issues. I can't help asking myself if the author really knows all the ins and outs of this (even though it be Kevin Yank himself!)

It depends on context whether you need the div selector in div.class, but at the same time, the semi-colon at the end of the final declaration is optional. Hmmm. So what to choose? And then, does the author know that the quotes around multi-word font names are optional?

Anyhow, great fun. I was a bit slow, though, and panicked a bit at the end as time ran out (I hate time limits!). Got 80% on CSS the first time around, but pretty sure I know what I got wrong. smile


Did you get a chance to read the article


Actually, it is good to see you around these lands again! It's been ages but I know that you kept yourself quite busy.

I finally took the test. I'm afraid I failed (72%) but I did it under 5 min... Is that an excuse? lol

I agree that some of the questions are a bit tricky because you can't be sure what they're asking but I guess this is on purpose so you pay more attention.

@kevinyank Will you be writing more articles for SP?


I got 92% on my first try smile And I have a screenshot to prove it (though that obviously doesn't prove it's my first try!). I happen to love writing elegant CSS, and both Chris Coyier and Heydon Pickering are my heroes!

I've been designing and developing website for about 2 years now, since I graduated (Marketing), and I recently hired my first employee; a junior web developer. The interviews consisted of about 12 questions, and a mini CSS test. In that test, I had a sketched scenario of 3 boxes horizontally overlapping each other between 2 paragraphs, and asked the interviewees how they'd achieve it. Needless to say, almost none of them got the even close. It required a combination of margin, padding (optional really), negative margin, and z-index. I'd be happy to scan the diagram in and upload it if anyone's interested.

Dane, from Cape Town, South Africa


I disagree with you writing off the 'background' option in the second question.
Background controls colors and images for the background. Background thus is something that typically gets overlapped by text, images, divs and so forth. So background can cause HTML elements (itself in this case) to overlap.


Background is purely visual. It does not allow any elements to move and overlap.


How can background (by itself) overlap those elements? Answer: They can't.


Devils advocate smile Yes they can.

Try this:

<meta charset="utf-8">
<title>Untitled Document</title>
div{display:inline;background:blue;padding:25px 0}
div + div{display:block;background:red;}


The quiz said by itself. You seem to have other properties other than background Paul. Seems that isn't following the quiz thus invalid. Your example fails without the padding.


I was quoting your post not the quiz smile

Anyway all elements are display:inline by default until the UA applies its own styles so there is always more going on under the hood than you think. wink

Here's another not so straight forward question.

<meta charset="utf-8">
<title>Untitled Document</title>
table tr > td {
table td {
table td:first-child {
table > tr > td:first-child {


What colour will the td background be.


Not correctly then. I specifically say "background (by itself)". This does actually mean no other properties. I guess you can change displays since you aren't limited in the HTML you can use so I'm fine with that.

I'm aware of the displays default but I'm talking about the padding invalidating your code. It fails the quiz since the padding is needed for your example and my post, and the quiz specifically ask for what property can do the overlap by itself. Aside from default displays for elements and whatnot, background can't do it.


I was avoiding any specifics to the quiz in case any one was trying it out but I take your point.

I was only playing devils advocate and if you remove the background from my post there appears to be no overlap but adding the background shows an overlap. It's another misunderstood part of CSS and would have been good as a separate question smile


You're a sadist, O'Brien. stuck_out_tongue


In my eyes it's narrowed down to 2 results instantly (ok technically 3 but that 3rd one has obviously less specificity) which is then left to specificity to determine the winner.

Sadist indeed.


I didn't know if the green or yellow would win out. I had to try it.


says of both > and :first-child

You can use these to make selectors that are more specific.

But it doesn't say which is more specific.

I thought order might have an effect, but no.


Off the top of my head, only combinators do not have specificity. So >, +, etc.

It's not an HTML element, class, ID, pseudo class, or pseudo element. So thus it HAS no specificity smile .

You could have

table tr > td{}
table tr td{}

And the only thing that would ever allow the first rule to work is if you put it latter (ok ignore !important.)

So that means that the table tr>td{} is 0003 specificity while the table td:first-child{} is 0012 specificity. Order will not matter there.


Surprises me that the last one isn't more specific than the second last, though, even if you rule out the child selectors.

The child selectors seem to cancel out the value of the selector, which seems weird to me.


The page will automatically insert <tbody> into the page (if not present already) so no matter what table>tr is IMPOSSIBLE. Invalidating that entire option.


Ugh. Haha! That makes sense. Now I really hate that O'Brien person. stuck_out_tongue

It is a really good question, though. Great way to trip people up. smile


Yes, I found that out the hard way a long time ago smile

That's what I'm here for smile


I was one to confuse a pseudo-element with a pseudo-class (my result was 92%). Haven't done any CSS-from-scratch long time (usually using Bootstrap).


The last is the most specific and, if not for the browser inserting a THEAD element, would be selected.

Perhaps this should be a separate thread, but ...
Are there a lot of variances from one browser to another in specificity?
Specificity seems to be pretty clear


No, specificity is universal and never varies.

But it isn't inserted, thus this option cannot be considered as an option. You're correct though it WOULD be selected if not for the browsers inserting tbody. That fact alone though makes that option invalid. If the last option started with "tbody" instead of "table", then yes that would win out. But it doesn't wink .

table>tr will never select anything since in no possible universe will the browser not insert <tbody> before any rows.


3/3 of those questions in article and 100% on CSS Core on the first try. Some questions were a bit tricky smile Nice quiz overall: with careful reading and understanding there were no ambiguities.

Regarding ideas for more tricky questions: I have some, but most of them won't fit into the format with the number of predefined answers (and I'm not that good at coming up with false answers, haha). But, one of my favorite questions: “When the styles of siblings can have an impact on the position of the absolute positioned element?”


Well done smile


92% on the html one first try. Both html and css quizzes done in less than 15 minutes. Even though the answers aren't posted, there is a lot of benefit to be gained from these quizzes. Great remedy for the "Imposter Syndrome", especially if you are a full-stack free-lancer and have no way of gauging if you are keeping up with the industry on average. Plus they are a lot of fun.


I just have to say I didn't assume that :hover was a pseudo-element, I was thinking that I'd apply a pseudo-element TO the anchor on :hover to create the shadow, which seems like a perfectly valid scenario. So I think that question should be re-evaluated, or at least consider re-wording or replacing that particular answer. :^)


I’m not sure I understand. A pseudo-element is a piece of content that doesn’t correspond to an actual HTML element; I’m not sure what you mean when you say you’d apply a pseudo-element to the anchor. Do you mean you would target a pseudo-element (such as :before or :after) of the anchor?


No immediate plans, but I really enjoy it so I’ll certainly be looking for excuses. smile


I’d say that’s a poor choice of words on the author’s part. Combinators like > and + certainly do cause a selector to target a smaller subset of elements in the page than the selector would without them, and in that sense they are more ‘specific’, but they do not contribute to the Specificity (with a capital ‘S’, meaning the formal ranking of CSS selectors that determines the order in which rules are applied to the document) of a selector.


Kevin Yank himself is a perfectly fallible human being, and I do share your trust issues. Writing good multiple choice questions is really hard, because for every correct answer you have to come up with four incorrect answers (the technical term is ‘distractors’) that aren’t obviously wrong but are actually wrong.

We’re actually in the process of adding support for fill-in-the-blank questions to Sit the Test, in part because it makes writing good test questions a lot easier!

Hmm. I’d argue that the semicolon is clearly optional whereas all the other options are not. Still, I do agree it could be clearer. I’ve adjusted the wording to “Which part of this code can be removed without breaking it or changing its effect?”

Indeed, he did not! I’ve deleted this question from the test and will devise a suitable replacement. Thanks for the catch (and the awesome piece of CSS trivia!).


In the case of div.class, I vaguely remember some people even advising not to include the div part, because the class is enough of a hook. Of course, if various kinds of elements have that class and you only wanted to target the divs, then you'd need the selector. anyhow, I'm not trying to be difficult. I was just a bit thrown by the question. stuck_out_tongue

I can't take any credit. Mathias Bynens posts reams of amazing trivia like that—on CSS, JS etc. I'm rather proud that I even remembered one such piece of trivia, given my lousy memory. smile


Thanks for expanding the explanation!
And yes, browsers insert a TBODY, not a THEAD. ( I injected a bug while correcting a bug...)


Perhaps the third question above could be improved by emphasising the word "element":

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

I got this one in my test and read it too quickly to notice the subtlety so thought it was a trick question – "These are all done with pseudo!"

There were a couple of other questions that I thought could be worded better, but I can't go back to it now to check which ones. How about making a way of giving feedback on question clarity from within the test?


I must admit, I was pleased to see that first question, about line height. I, too, learned to use unitless line height a long time ago, and I was surprised to discover that its behaviour is not widely known. A couple of years ago, I had somebody on these forums ranting at me for my utter stupidity in not redeclaring my line height after I changed font size, and my explanation was met with disbelief.

(It's probably just as well he's no longer around; I can have a quiet gloat without being tempted to remind him in person. )


I had the same argument with him a few times smile


Yay, I got 96%, quite happy with that, but I have no clue where I tripped up. None whatsoever.

Incidentally the JavaScript Core test on the same site has far too many browser DOM centric questions to be branded JavaScript Core. They should probably be two separate tests.


88% first time for me. A couple were a bit confusing but don't think I did too badly! Would be nice to know where I tripped up though.


Heh, it wasn't that he didn't know about unitless line heights, but rather that he passionately disagreed with their use. Still, I wasn't convinced, and am quite a fan of them.


Any ambiguous wording in questions or options that, intended or not, fools the answerer is not testing css knowledge imho. The ambiguity/difficulty should be put in the problem itself.

I'll take the tests then, though I'm prone to error a lot when distracted.
Maybe 100% could be made by my ignorant mistakes. How would I know? smile


Css core: 88%. I was lucky I guess.
Css practice: 92%, two pretty silly mistakes.
Html Core: 84%, aborted in a hurry.

Not that ambiguous as I was afraid of after all. smile


2nd attempt 100% smile (no practice questions looked at)


Congratulations! (Show-off. )


Whoa, thanks for the screenshot, @PaulOB! That’s definitely not how it’s supposed to look. Fixing it now. smile


Not using unitless line-heights means you are signing on to specify a line-height whenever you specify a font-size. It’s doable, but hardly a sensible default position, I’d say.


I like this idea, lesley! Will change this the next time I edit the test.


Would you need to change anything if that line height were set in ems or % though? Whatever you changed the font size to would be automatically reflected in the line height, wouldn't it? (Granted, though, that it's a different story for descendent elements, as the Eric Meyer link above shows, so I still don't like the idea of setting units on line height.)

Anyhow, here's one of the discussions by said member about line height: http://www.sitepoint.com/community/t/layout-disaster-css/13746/36, in case anyone's interested in what we are referring to!


Hmm I suppose you could do something like:

* { line-height: 1.2em; }

This would cause every element in your document to calculate its own line height based on its own font size. But you can get the same effect with just

html { line-height: 1.2; }

and that only requires the browser to match one element, rather than every single element on the page.

To be clear, this:

html { line-height: 1.2em; }

will not calculate auto-adjust the line height for each element’s font-size. It calculates a fixed line height (1.2 times the html element’s font-size) and every element in the document inherits that fixed height, regardless of its own font-size.


Really liked the quiz but made a poor result above and had to wait one week to get a second shot at it. smile

The trickyness in some questions made me I feel like I knew the proper answer but had a hard time decide what was really the question. Guess I was luckier this time.


Well done Erik smile


Passed them all, but some with shameful results imho, I guess I have some catching up to do. open_mouth
Nice test though, thanks!


80% first try. Loved the test although some of the questions could have been made a bit clearer.


74% on the actual test, but got 88% on the practice.

For a harder question, I like this one that surprised me when I learnt it:

Which of these properties on its own can create a new stacking context?


The correct answer is opacity. Margin is the red herring but position and z-index need to both be specified in order to create a stacking context.


Technically isn't position all you need? Stacking context is then created based off the HTML source order.


The stacking order would be defined from the html order. A stacking context is a different thing to that. Taken from http://philipwalton.com/articles/what-no-one-told-you-about-z-index/:

Groups of elements with a common parent that move forward or backward together in the stacking order make up what is known as a stacking context.


Ah - my stacking context was the definition of stacking order. Thanks! Learned something wink .


Very nice, i had 77% thats not bad from a person who only played with css for 1 year, and never learned in school about the names: pseudo-class and element:)
Very nice i learn so much on this site:)
// Patrick clemmensen


I got 84% on first try. On that question about overlapping you should specify negativ margin, not just margin. I know there is no negative margin property but, It's common knowledge that negative margins are with minus - sign.