Demystifying the Power of CSS Selectors

Demystifying the Power of CSS Selectors

A Comprehensive Guide to CSS Selectors for Web Developers

Often underestimated by beginners, knowing how CSS selectors work and how to use them to your advantage is crucial.

In this article, we will be going through the different CSS selectors and their use cases.

Sit down and grab a snack or something, as this is one of my longer articles.

What is a Selector?

I mean...it's in the name (-_-)

CSS selectors are used to "find" (or select) the HTML elements you want to style.

-W3Schools

Simple as that.

Say you want to change the style of all paragraphs on a page. A selector is what allows you to pick out all headings and apply those styles to them. Of course, CSS selectors can be much more dynamic than this.

Depending on what you want to achieve, CSS selectors can be divided into several categories.

Simple Selectors

Element Selector

The element selector selects all instances of the specified HTML element.

Taking the above example I gave with paragraphs, the following will select every paragraph on a page, change their color to orange, and make them bold.

/* select all paragraphs on the page */
p {
  color: orange;
  font-weight: bold;
}

Class Selector (.)

The class selector selects all elements with the specified class attribute.

Elements with a specific class are selected by writing a period (.) followed by the name of the class.

Take this for example:

<button class="cta-button">Buy now</button>
/* select all elements with a class of "cta-button" */
.cta-button {
  background-color: purple;
  color: white;
  padding: 1rem 2rem;
  border-radius: 0.5rem;
}

The code above selects any element with class="cta-button".

ID Selector (#)

While the class selector selects elements based on their class, the ID selector is used to define styles that affect only elements with the corresponding ID.

To use an ID selector, write a hash (#), followed by the ID of the element.

<section id="features">...</section>
/* select the element with an ID of "features" */
#features {
  width: 90%;
  margin: 5rem auto;
  background-color: black;
  color: white;
}

Universal Selector (*)

The universal CSS selector is used to select every element on a page.

You most probably have used or seen it used when performing a CSS reset.

/* select every element on the page */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

Grouping Selector (,)

Imagine this scenario:

You want to have a different font on headings from paragraphs on a page. However, there are different levels of headings. You could do this:

h1 {
  font-size: "Open Sans", sans-serif;
}
h2 {
  font-size: "Open Sans", sans-serif;
}
h3 {
  font-size: "Open Sans", sans-serif;
}
h4 {
  font-size: "Open Sans", sans-serif;
}
h5 {
  font-size: "Open Sans", sans-serif;
}
h6 {
  font-size: "Open Sans", sans-serif;
}

Or, you could code like a pro and use the grouping selector :)

/* group all heading levels and give them the same font */
h1, h2, h3, h4, h5, h6 {
  font-size: "Open Sans", sans-serif;
}

In essence, when two or more selectors have the same styles, the grouping selector is used to declare those styles for the different elements that use them.

You can also group different types of selectors, such as grouping elements, classes, and IDs as needed, e.g.

/* select all paragraphs on the page,
all elements with a class of "copy", and
the element with an ID of "jacques" */
p, .copy, #jacques {
  font-size: 1.25rem;
}

Combinators

A combinator is something that explains the relationship between the selectors.

-W3Schools

You can use combinators to select an element based on its relationship with another element.

Combinators also work with all simple selectors.

Descendant Selector (space)

Say you want to select element A which is a descendant of element B, such as paragraphs inside a div.

<div>
  <p>Lorem ipsum...</p>
  <p>Lorem ipsum...</p>
  <p>Lorem ipsum...</p>
</div>

Separating the two selectors by a space activates the descendant selector, as seen below.

/* select all paragraphs that are descendants of a div */
div p {
  color: green;
}

You can also go several levels deep with descendant selectors.

/* select all paragraphs
that are descendants of divs
that are descendants of the header element */
header div p {
  font-size: 2rem;
}
<header>
  <div>
    <p>Lorem ipsum...</p> <!-- selected -->
    <p>Lorem ipsum...</p> <!-- selected -->
  </div>
  <div>
    <p>Lorem ipsum...</p> <!-- selected -->
  </div>
</header>

Child Selector (>)

We have established that the descendant selector selects every descendant of an element, not withstanding how deeply nested it is.

The child selector does not have such freedom. You can only select direct children of an element using the child selector. Take this HTML structure for example:

<section>
  <p>Lorem ipsum...</p> <!-- 1 -->
  <p>Lorem ipsum...</p> <!-- 2 -->
  <div>
    <p>Lorem ipsum...</p> <!-- 3 -->
  </div>
  <p>Lorem ipsum...</p> <!-- 4 -->
<section/>

There are four paragraphs in the section. We know that the descendant selector will select ALL paragraphs that are inside the section.

/* select all paragraphs in this section */
section p {
  font-weight: bold;
}

The child selector, though, will only select direct children of the section.

/* select all paragraphs that are direct children of this section */
section > p {
  font-weight: bold;
}

Since paragraph 3 is nested within a div, it will not be selected, and thus, will not inherit the bold style.

Once again, it is possible to go multiple levels deep with child selectors.

Adjacent Sibling Selector (+)

The adjacent sibling selector selects an element that appears after another on the page.

So, if we have an HTML structure such as this,

<header>...</header>
<section>...</section> <!-- section 1 -->
<section>...</section> <!-- section 2 -->
<footer>...</footer>

The code below will select only section 1.

/* select the section that appears directly after a header */
header + section {
  margin-top: -10rem;
}

General Sibling Selector (~)

So, a sibling selector selects an element that comes DIRECTLY AFTER another.

Cool.

What's a general sibling selector?

A general sibling selector removes the restriction of a sibling selector to a direct sibling only, by allowing you select ALL siblings of a particular type of an element.

Back to this:

<header>...</header>
<section>...</section> <!-- section 1 -->
<section>...</section> <!-- section 2 -->
<footer>...</footer>

The general sibling selector will select both section 1 and section 2.

/* select all sections that are on the same level as a header */
header ~ section {
  margin-top: -10rem;
}

Pseudo-classes

You're doing great!

Now let's talk about pseudo-class selectors.

They're used to select elements to give them styles when they are in certain states. These could be when they are hovered, clicked, in focus, checked, empty, and so on.

A pseudo-class selector is defined by writing a colon (:), followed by the pseudo-class.

There are A LOT of pseudo-class selectors, more than even I expected while researching for this article.

Common examples are :link, :hover, :active, :visited, :required, :first-child, :last-child, and so on.

For the sake of the brevity of this post, I have simply linked to an article on pseudo-classes from W3Schools.

Pseudo Elements

The pseudo-element selectors include ::before, ::after, ::first-letter, ::first-line, ::marker, and ::selection.

The most popular are the :before and :after element.

Little secret: I hadn't ever heard of any of those other pseudo-elements I mentioned, till today. Shh (-_-)

They are defined by writing double colons (::), then the name of the pseudo-element.

Once again, for the sake of brevity, I have also linked an article on pseudo-elements.

Attribute Selectors

You can also select an element based on its attributes, as well as the nature of the attributes' values.

A common use case is selecting all inputs of a certain type.

input[type="text"] {
  color: black;
}

I will also not be writing extensively on attribute values in this article, but you can learn all about them here.

Parting Words

If you've made it to the end, paste your aza. I'll pray over it for you.

Seriously though, you deserve a pat in the back.

Hopefully, you can use this article as a reference in the future as well, so make sure to bookmark it.

Also, leave a like, comment, and follow me for more web dev content like this one. You can also go through my other posts on this blog. You're sure to get a ton of value :)

Till next time, have a good one :)