DEV Community

vance
vance

Posted on

BWC Bootcamp Recap: CSS Selectors

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;}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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;}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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 type input, and also b) has a type attribute assigned with the value of number. It will select only the first input in this example.
  • input[required] selects any element that a) is of the type input, and b) has the required 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 the required attribute never has a value attached! input[type] would be an equally valid selector, and would select all input elements that have any value of type 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 an id attribute with the word blue somewhere in its value. In the example HTML, it would select both the first input (with ID input-number-blue) and the div with ID blue-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 just id=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>
Enter fullscreen mode Exit fullscreen mode

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 a nav element—they could be direct children of nav, 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 target nav itself.
  • You can even repeat the same selector twice! div div will target any div 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 class blue, and b) is found inside of a section 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 a section) or paragraph 4 (because it doesn’t have the class blue).

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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;}
Enter fullscreen mode Exit fullscreen mode

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;}
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)