the short answer
A CSS selector is the part of a rule before the curly brackets. It tells the browser which elements the rule styles. p picks every paragraph, .note picks elements with the class note, and #top picks the one element with the id top. You can combine them to target exactly what you want.
A CSS selector is the part of a rule that comes before the curly brackets. It tells the browser which elements the rule applies to:
p {
color: navy;
}Here the selector is p, so every paragraph on the page turns navy. Change the selector and you change which elements get styled. That is the whole job of a selector, and getting it right is most of what makes CSS feel easy or hard.
This guide covers the selectors you will use every day, how to combine them, what happens when two rules disagree, and the small mistakes that cause most “my CSS isn’t working” moments. Every example here was checked in a real browser.
The parts of a CSS rule
.note {
color: green;
font-weight: bold;
}- Selector:
.note, which elements to style. - Declaration block: everything between the curly brackets.
- Declaration: one line like
color: green;, made of a property (color) and a value (green).
The page used in this guide
The examples below style this small page:
<nav>
<a href="/">Home</a>
<a href="/shop">Shop</a>
</nav>
<main>
<h1 id="top">Pet shop</h1>
<p class="note">Open every day.</p>
<ul>
<li class="pet">Cat</li>
<li class="pet">Dog</li>
<li class="pet sold">Fish</li>
</ul>
<input type="email" placeholder="Your email">
</main>The four basic selectors
Type selectors
A tag name on its own picks every element of that type. li { color: purple; } turns Cat, Dog and Fish purple.
Class selectors
A dot followed by a class name picks every element with that class. .pet { color: green; } turns all three pets green. An element can have several classes, separated by spaces in the HTML: Fish has both pet and sold.
Id selectors
A hash followed by an id picks the one element with that id. #top { color: red; } turns the Pet shop heading red. Each id should appear only once per page.
The universal selector
A star, *, picks every element. You will mostly see it in a line at the top of a stylesheet that resets something for the whole page, like * { box-sizing: border-box; }.
Styling several things at once
Separate selectors with commas to give them the same rule:
h1, .note {
font-family: Georgia, serif;
}The heading and the note both get the new font. This is called a selector list, and it saves you writing the same declarations twice.
Combining selectors
Inside: a space
A space between two selectors means “inside”. This one picks links anywhere inside the <nav>, and ignores links elsewhere on the page:
nav a {
text-decoration: none;
}Directly inside: >
> means “a direct child of”. main > p picks paragraphs whose parent is <main> itself, but not paragraphs tucked deeper inside another element.
Both at once: no space
Write two selectors with no space and the element must match both. li.sold picks an li that has the class sold. Only Fish matches. .pet.sold works the same way and also picks just Fish.
Attribute selectors
Square brackets pick elements by their attributes:
input[type="email"]picks email boxes only.a[href^="https"]picks links whose address starts withhttps.img[alt]picks pictures that have analtattribute at all.
They are handy for forms, where many inputs share the same tag but do very different jobs.
Pseudo-classes: elements in a certain state or place
A pseudo-class starts with a colon and picks elements by their state or position:
a:hoverpicks a link while the pointer is over it.input:focus-visiblepicks a box that has keyboard focus, so people can see where they are.li:first-childpicks anlithat is the first child of its parent. In our list that is Cat.li:last-childpicks the last one. That is Fish.li:nth-child(odd)picks the 1st, 3rd, 5th and so on. Great for striped tables..pet:not(.sold)picks pets without the classsold: Cat and Dog.
Pseudo-elements
Two colons pick part of an element, or add a decoration that is not in the HTML at all. ::before and ::after add content before or after an element, and ::first-line styles just the first line of a paragraph. You will meet these once the basics feel comfortable.
Which rule wins when two disagree
Say all three of these rules are in the same stylesheet, and the page has <p id="intro" class="note">Hello</p>:
#intro { color: red; }
.note { color: green; }
p { color: black; }All three match the paragraph, and the text comes out red. The browser picks the rule with the most specific selector, which is called specificity:
- Id selectors are the strongest.
- Class, attribute and pseudo-class selectors come next.
- Type selectors are the weakest.
Order in the file does not matter here, because the selectors have different strengths. Order only decides things when two selectors are equally strong: then the one written last wins. Gwecode’s CSS Level 1 has a lesson on each of these rules.
Two shortcuts that win almost every time
A style attribute written straight on an element beats anything in a stylesheet. Adding !important to a declaration beats even that. Both make later changes painful, so treat them as a last resort.
The same selectors in JavaScript
Selectors are not only for CSS. JavaScript’s document.querySelector() takes exactly the same selectors to find elements on a page, so everything here carries straight over. Our guide to selecting DOM elements shows how.
Common mistakes
A space where there should not be one
li.sold and li .sold look almost the same but mean different things. The first is an li with the class sold. The second is an element with the class sold somewhere inside an li. In our page, the second matches nothing.
Forgetting the dot or the hash
pet { color: green; } looks for a tag called pet, which does not exist, so nothing happens and nothing warns you. Classes need a dot and ids need a hash.
A space instead of a comma
h1 .note means a note inside a heading. h1, .note means headings and notes. One small comma changes everything.
Capital letters that do not match
Class names and ids care about capitals. .Note will not style class="note".
Ids everywhere
Styling with id selectors works, but because they are so strong, every later change needs an even stronger selector to beat them. Classes keep your CSS easy to change.
Expecting hover on a phone
Touch screens have no pointer hovering over things, so do not hide anything important behind :hover.
How to see which rules apply
Right-click any element and choose Inspect. The developer tools show every rule that matches it, in order of strength, with the losing declarations crossed out. When a style does not appear, this tells you straight away whether your selector matched at all, or matched and lost.
A short exercise
Using the page from earlier, write one selector for each of these:
- Every link inside the
<nav>. - The first pet in the list.
- The email box.
- Every pet that is not sold.
One possible answer
nav a { }
li:first-child { }
input[type="email"] { }
.pet:not(.sold) { }For the first pet, .pet:first-child works too. For the email box, main input would also work on this page, but the attribute selector keeps working if you add more boxes later.
Related reading
- HTML document structure explained, for the page that your selectors find their way around.
- Selecting DOM elements in JavaScript, which uses these same selectors from code.
Your next step
Selectors are the part of CSS you use in every single rule, so they repay a little practice. Gwecode’s CSS Level 1 teaches them one at a time with a live page beside your code, alongside colour, fonts, boxes and layout, and its level check has you style a profile card. Level 2 picks up the combinators and pseudo-classes from this guide. Every lesson is free. Create a free account to keep your progress, and try the class lesson below.
practise this · css · lessonSelect by classstart the lessonquestions
What is the difference between a class and an id selector?
A class, written with a dot like .note, can be used on as many elements as you like. An id, written with a hash like #top, should be used on one element per page. Id selectors also win over class selectors when the two disagree.
What does the space between two selectors mean?
It means “inside”. nav a picks every link anywhere inside a nav. Without the space, li.sold means an li that itself has the class sold.
Why is my CSS not working when the selector looks right?
Usually another rule with a stronger selector, or a later rule of equal strength, is winning. Your browser’s developer tools show every rule that applies to an element and cross out the ones that lost.
Should I use !important?
Rarely. It makes a declaration beat almost everything, which fixes one problem and causes the next. Writing a more specific selector, or reordering rules, is nearly always better.
Are CSS selectors used anywhere else?
Yes. JavaScript’s querySelector() and querySelectorAll() take the very same selectors to find elements on a page.
