Hello friends and learners, great job making it to week 2 of Bad Website Club’s free web dev bootcamp!
We’ve seen a handful of different CSS selectors in our lessons so far. It can be tricky to remember what all of them do and why you would want to use them, so let’s review!
Reminder: the CSS selector is what we call the part that comes before the curly braces { }
in a CSS rule. The selector determines which HTML elements the rule will apply to.
Basic selectors
Type selector (type
)
p {text-align: center;}
div {background-color: green;}
This is simplest selector we have! All you write is the name of the tag that you want to style, and then the rule will apply to every element of that type. Use this if you want to set the font size for all of your h2
elements at the same time, for example.
ID selector (#id
)
/* CSS file */
#title {font-size: 3rem;}
#red-marker {background-color: red;}
/* HTML file */
<h1 id="title">Bad Website Club!</h1>
<div id="red-marker"></div>
On the other hand, maybe you want to give unique styles to just one single element. In that case, you can use the ID selector. Make sure to assign some value to the element’s id
attribute in your HTML file. Then, you can write the selector by putting a hashtag/number sign #
directly before the value of id
.
This is most useful for styles that you know you will only want to apply one time, styles that are uniquely related to one single element. It’s especially useful when you have several elements of the same type but want each one of them to have a different style.
In the “colored markers” freeCodeCamp lesson, we gave each marker its own class and used that class to set the different colors for each marker. But since we knew there would only be one marker of each color, another option would have been to give each marker an id
and assign the color to that ID, instead of using classes.
Class selector (.class
)
/* CSS file */
.large-text {font-size: 1.5em;}
.blue {color: blue;}
.canvas {width: 500px;}
/* HTML file */
<p class="large-text blue">I'm a big blue paragraph!</p>
<div class="canvas"></div>
This might be the selector we use the most often. It targets all of the elements on your page that have a certain class
attribute. Write this selector by typing a period .
right before the name of the class.
This is very versatile because you can manually pick and choose which elements will be part of your class. It’s especially useful when you have a group of similar elements that you want to share a style, but don’t want to give that style to all elements of the same time. Note the blue
and large-text
classes in the example above. We might set up our classes this way if we wanted paragraphs with a certain type of information to use larger text, or wanted only a subset of heading elements to be blue. We don’t want to apply those styles to every paragraph or heading, just to the ones we chose by giving them the right class attribute.
Remember that the class selector won’t actually do anything until you assign the class to some elements! Make sure to go to your HTML file and write class="whatever-your-class-is-called"
inside the opening tag of every element that you want to apply this set of styles to.
Universal selector (*
)
* {box-sizing: border-box;
margin: 0;
padding: 0;}
The universal selector is typed as just the asterisk symbol *
by itself. It selects every single element on the page.
It’s often used to do what people call a “CSS reset” or “normalizing the CSS”. This means setting certain properties (often including box-sizing
, margin
, or padding
) to be the same on every element in order to override the default values set by the web browser.
Attribute selector ([attr]
)
/* CSS file */
input[type="number"] {width: 50%;}
input[required] {background-color: yellow;}
[id*="blue"] {background-color: blue;}
/* HTML file */
<input type="number" id="input-number-blue">
<input type="text" required>
<div id="blue-marker"></div>
Attribute selectors can be a little more complex than the others we’ve seen so far. There are a few different ways to use them, but the basic idea is that you’re choosing which elements to apply your rule to based on what HTML attributes they have. (Remember, attributes are those extra words inside the opening tag.)
Attribute selectors are written with square brackets [ ]
around the attribute name (and value, if there is one). If you want to select anything that has the attribute set at all, regardless of its value, then type only the attribute name inside the brackets. On the other hand, if you want to select elements based on the value of an attribute, then copy and paste the entire attribute-value pair (both sides of the equals sign =
) from the HTML tag into the brackets of the CSS selector.
If you want to target elements of any type that have a certain attribute, then the whole selector will be wrapped in square brackets. However, when we’re trying to target elements by an attribute, there’s often only a single type that we want to include. In that case, we can narrow down the selection by writing a type name directly before the opening bracket.
Let’s walk through the examples above.
-
input[type="number"]
selects any element that a) is a tag of the typeinput
, and also b) has atype
attribute assigned with the value ofnumber
. It will select only the first input in this example. -
input[required]
selects any element that a) is of the typeinput
, and b) has therequired
attribute included somewhere in its opening tag. It will select the second input element in the example HTML. This is a case where you don’t need to use the = sign to specify a value. (But it’s not just because therequired
attribute never has a value attached!input[type]
would be an equally valid selector, and would select all input elements that have any value oftype
assigned. I just couldn’t think of any other attribute that you realistically would have a reason to select without a certain value!) -
[id*="blue"]
is a little weirder! It selects any element of any type that has anid
attribute with the wordblue
somewhere in its value. In the example HTML, it would select both the first input (with IDinput-number-blue
) and the div with IDblue-marker
. The reason it selects elements of all types is because we didn’t include a type name before the brackets. Also, notice how it’s not just an equals sign, it’s*=
(asterisk equals). This symbol is what makes it search for IDs that contain the letters “blue” anywhere in them, whereas writing justid=blue
would search for IDs that exactly equal “blue”.
There are several different kinds of syntax available to search for sub-strings (partial matches) of the value. You can read more about all the options on MDN’s “Attribute selectors” page.
I used inputs as an example here because this is a common situation where you might want to style elements differently depending on one of their attributes. Otherwise, attributes usually don’t have a close relation to CSS properties.
Combining selectors
We can also write more complex CSS selectors that combine two or more of the selectors described above. The special characters that we put in between the two different selectors are called combinators. Using combinators to construct more complex selectors gives us more control to target elements that fall into very specific regions of the page.
Descendant selector (A B
)
/* CSS file */
nav a {text-decoration: none;}
div div {width: 500px;}
section .blue {color: blue;}
/* HTML file */
<nav>
<ul>
<li>
<a>home</a>
</li>
<li>
<a>about</a>
</li>
<li>
<a>gallery</a>
</li>
</ul>
</nav>
<main>
<p class="blue">paragraph 1</p>
<section>
<h1 class="blue">heading 1</h1>
<p class="blue">paragraph 2</p>
<div>
<p class="blue">paragraph 3</p>
<p class="green">paragraph 4</p>
</div>
</section>
</main>
The descendant selector has the simplest syntax: there’s no special symbol to type, just put a space between the two parts of the selector. This will target elements of the second type that are descendants of an element of the first type—which means they’re nested anywhere inside.
- The selector
nav a
will target links that are found anywhere within anav
element—they could be direct children ofnav
, or they could be nested several levels deep, like the ones in the HTML above. This example is very commonly used: we often want links in the site’s navigation bar to look different than links found within the main body of text. It does not targetnav
itself. - You can even repeat the same selector twice!
div div
will target anydiv
element that is found within another div. So if you had many nested divs, it would target all of them except the outer-most one. - They don’t have to be made up of just type selectors—any of the basic selectors we saw in the previous section of this post should work as parts of a descendant selector. So
section .blue
will select any element that a) has the classblue
, and b) is found inside of asection
element. Looking at the HTML above, this selector would target heading 1, paragraph 2, and paragraph 3, but would not target paragraph 1 (because it’s not inside asection
) or paragraph 4 (because it doesn’t have the classblue
).
Direct child selector (A > B
)
/* CSS file */
nav > ul {list-style-type: none;}
/* HTML file */
<nav>
<ul>
<li>
<a>home</a>
</li>
<li>
<a>about</a>
</li>
<li>
<a>gallery</a>
<ul>
<li><a>cat gallery</a></li>
<li><a>dog gallery</a></li>
</ul>
</li>
</ul>
</nav>
The direct child selector is similar to the descendant selector, but narrower: it only targets children whose immediate parent is the one named first. The combinator is the right angle bracket >
symbol, so it’s written like selector1 > selector2
.
In this example, nav > ul
will target the first list that contains the “home”, “about”, and “gallery” list items, but it will not target the second ul
that says “cat gallery” and “dog gallery”.
Adjacent sibling selector (A + B
)
/* CSS file */
#home-button + li {margin-top: 2rem;}
/* HTML file */
<nav>
<ul>
<li id="home-button">
<a>home</a>
</li>
<li id="about-button">
<a>about</a>
</li>
<li id="gallery-button">
<a>gallery</a>
</li>
</ul>
</nav>
Instead of selecting elements based on their parent, the adjacent sibling selector targets elements based on another element that comes before them at the same level of nesting. The combinator is the plus sign +
.
This selector only ever targets one single element: #home-button + li
only targets the first list item that comes after #home-button
, and only if they share the same parent. There can’t be any other element between them. Note that we’re talking about what order the HTML tags are written in, not how things are visually laid out on the page.
We already said that the ID selector is what you should use if you’re trying to target just one single element, right, so why use this combinator instead? The advantage is that you can change around the HTML without needing to update the CSS when the order of the elements changes. In this example, we might be trying to give the home button some extra space by using the adjacent sibling selector to apply a bigger margin to whatever comes after it. Using the adjacent sibling selector means we don’t have to change the CSS at all if we decide to swap the places of the Gallery and About buttons. (This is not a great example because it would be more straightforward to just set the extra margin-bottom
on #home-button
rather than margin-top
on the thing next to it, but if for some reason you wanted to make the button next to home be a different color or something, that would also use this selector.)
General sibling selector (A ~ B
)
#home-button ~ li {color: green;}
This one is similar to the adjacent sibling selector, but more flexible. It can target an adjacent sibling and any other siblings (elements sharing the same parent) that come further down in the HTML after it. The combinator is the tilde symbol ~
.
Compare this example with the one from the adjacent sibling selector. The only difference in these two selectors is which combinator they use. Given the same HTML, this CSS rule would select both the About list item and the Gallery list item.
We could use this if we wanted every link in the nav aside from the first one to be green, for instance.
See this blog post from LogRocket for more examples of reasons you might use the two different sibling selectors. (Warning: It’s on a website that’s trying to sell you stuff.)
Grouping (A, B
)
h2, h3, h4 {color: purple;}
section a, article a {color: green;}
If you want to apply the same style rule to various different kinds of elements, and there’s no one selector that applies to all of them, then you can just list different selectors separated by commas! It works with selectors that include combinators too.
More resources
- Here’s a really fun way to both recap the selectors we already know, and also learn some new ones: an interactive game called CSS Diner! This is totally how I started to understand selectors.
- MDN guide to selectors and combinators
- Selectors Explained translates a CSS selector into a plain English description.
Top comments (0)