CSS Diner - It's a fun game to learn and practice CSS selectors.

  • By Luke Pacholski
  • Last update: Sep 21, 2022
  • Comments: 16

Welcome to CSS Diner

It's a fun game to learn and practice CSS selectors.

To play, visit flukeout.github.io or cssdiner.com

Change Log

Aug 25,2016

  • Added Twitter, Facebook and Email share actions
    • Tracking clicks with GA Events
  • Made the level menu and editor area scroll independently
    • Using custom jQuery scroll library

Aug 18,2016

  • Started using cssdiner.com to redirect to flukeout.github.io

Aug 12,2016

  • Added checkmarks to completed levels in level menu and header

Aug 4,2016

  • Began tracking progress and correct guesses with GA Events

Filing issues and PRs

Please file issues and PRs in the css-diner repo.

Repo structure

Here's the repo structure, it's a bit confusing...

  • Currently, all of the working code (including issues, PRs and in-progress branches) is hosted in the css-diner repo
    • The lastest version of the code is on the develop branch
  • The live version is published from the flukeout.github.io repo
    • Live version lives on the master branch


This is more of a note to myself in case I forget, to deploy the latest version, I'll have to push to the master branch on the flukeout.github.io repo from the latest develop branch.

Roadmap and Status

Potential Features & Improvements

  • Lots of people have trouble with level 19, how should I address this?
  • Create levels for attribute selectors
    • Will probably add attributes like customer='bob' and place a little nametag by those dishes
    • Also some great ideas in this issue
  • Figure out how to tackle the .table element
    • Including it in the selector string makes the selectors invalid, but it shouldn't
  • Investigate the order of stacked oranges in the markup, some users think it's counter intuitive
  • Block attempts to use comma between selectors
  • Only pass each level if that level's selector is used
  • Make it easier to navigate between levels
  • Number all of the levels in the menu
  • Add UI to Tweet about finishing all of the levels
  • Add additional challenges per Selector
    • Some repetition per level would be good

Special Thanks




  • 1

    Improper Use of HTML5 Self Closing Tags

    I noticed that many examples in CSS Diner make use of self-closing tags that lead to confusion.

    Modern browsers view self-closing tags (except for <br/>) as errors and will treat the self-closing tag as a start tag. This leads to nesting of adjacent tags and changes the structure and semantics of the rendered HTML.

    For example, consider this snippet from level 17:

    <div class="table">
      <plate id="fancy">
        <apple class="small"/>
      <plate />
      <plate />
        <orange class="small"/>
        <orange />
      <plate />
      <pickle class="small"/>

    The browser actually interprets this as:

    <div class="table">
      <plate id="fancy">
        <apple class="small">
                <orange class="small">
                      <pickle class="small">

    Notice how the rendered HTML now communicates a different intent than originally desired.

    I think it's best practice to explicitly close all tags and save the self-closing short-cut for <br/>.

    For reference: http://stackoverflow.com/questions/3558119/are-self-closing-tags-valid-in-html5#3558200

  • 2

    Level 17 doesn't work?

    I have to select small apple small pickle with last-child selector When i write the selector: .table pickle,plate apple:last-child The small apple and small pickle shimmies but the level is not completed please tell me where i'm going wrong shimmy

  • 3

    I can't pass level 9

    I chose to select:

    plate pickle, bento pickle

    And I saw the shaking animation on those 3 pickles, which usually means I got it, but it just didn't let me pass. What's wrong?

  • 4

    Level 19 - Cannot find one valid selector according to the page

    I found at least 3 valid selectors that fit the criteria but none worked even though many would "shake" the intended element visual.

    Finally found that bento:nth-child(2) did work. The page was emphasizing :nth-last-child

    According to https://github.com/flukeout/restaurant/blob/master/levels.js, the intended target was: bento:nth-last-child(4) but what finally worked (as I was testing to list for this issue) was bento:nth-child(2)

    This demo is only supposed to succeed on a single, specific selector, not "valid selectors"?

    "Select the 1st bento"

    Tried: div > bento:first-of-type div > bento:nth-child(2) div > bento:nth-last-child(4) bento:nth-child(2) (finally worked)

  • 5

    level 1: hint if you don't get what game is expecting you to do?

    hi, first of all, thanks for creating this game! as a total beginner in html/css, i must admit it took me several minutes to understand what i was expected to enter. i tried 'real' types first, like


      and it took me a while to understand i should enter 'plate' , without the < > . i understand that at the moment there is no 'feedback' feature included in the game, like error messages appearing when you fail to do something. even if there is no way to do this, maybe the explanations for level 1 could be modified so it's easier to grasp the concept of the game quickly.

  • 6

    Level 30 missing closing double-quote

    In the following sentence, at the end of Swimwear: .toy[category^="Swim"] selects elements with class toy and either category="Swimwear or category="Swimming".

  • 7

    Only pass each level if that level's selector is used

    I am not in favor of this, as this gonna hinder my learning. I was happy to experiment with various solutions for a given level. You should not stop that.

  • 8

    Extended examples with Attribute Selectors

    Hi there!

    Since were playing around with fruits and plates and similar (no real-life examples), I'd come up with attributes that would further describe the freshness of the fruits, or condition of the plates (broken?) to use together with attribute selectors.

    A few Examples

    plate[condition=broken] Attribute equals exact value

    milk[condition*=spoiled] Attribute contains value somewhere

    apple[condition^=rotten] Attribute begins with value

    Never used this selector, but why not include it? bento[title$=sushi] Attribute ends with value

    There are still more. A full list can be found here: http://css-tricks.com/attribute-selectors/ Something to add: Attributes tend to be not so visible on real-life examples. Other than data- attributes, which are processed per javascript. I came up with examples which could be visible, both in the markup and also on the table. The selectors can also be used with classes and IDs of course.

    Cheers, -Martin

  • 9

    Level 18: div.table plate:nth-child(3) does not work

    When I type:

    "div.table plate:nth-child(3)"

    the appropriate plate shakes, but it does not fly off the table! But if i press the enter fast multiple times it suddenly does work :)

  • 10

    Level 13: Please mention having the same parent

    Select every pickle to the right of the bento

    I was confused. I thought A ~ B means select every element that follows A. But, it means only those elements which have the same parent as A and the elements follow A.

  • 11

    Perhaps an issue with 15

    Hey, I'm stuck on 15th question - I should select top orange. image

    Am I missing something and this should be a valid solution or what? System doesn't want to accept my answer :/

    Also I even tried div plate:first-child


  • 12

    [feature request] more CSS topics?

    this is an awesome app! I think it has the potentially to easily expand into full range css topics; let's start with critical topics such as display: flexbox; display: grid;

    let me know if I can help to contribute to this!

  • 13

    level 17

    If we have selected the last child correctly and accurately, but the program does not accept it and calculates it incorrectly, please check it, thanks.

  • 14

    Remove code that is no more necessary for validating .strobe selector cheat

    checkResults functions already prevents cheating with ".strobe" selector by comparing $(".table").html() == ruleTable.html() because ruleTable.find(rule).addClass("strobe"); will never find anything if dependent on the .strobe class because ruleTable.find(".strobe").removeClass("strobe"); already removes the class right before :)

  • 15

    Nth Child Pseudo Collector

    In Level 18, the second example reads as follows: div p:nth-child(2) selects the second p in every div

    Shouldn't it read instead as follows?: div p:nth-child(2) selects the second element that is a p, in every div

    Because in Level 19, it might lead one to think this is the solution for selecting the bento: bento:nth-last-child(2) //the second bento counting from the end whereas the correct answer is: bento:nth-last-child(3) //the third element that is a bento, counting from the end

  • 16

    Bug: on mobile table area covers css instructions on the right panel

    Hi, Thanks for the awesome content. Just to let you know, there's a bit of a ui bug when using cssdiner from mobile. Please see attached picture.image

    Os:iOS Browser:Safari Level:22