CSS Basics - Advanced Selectors

Shawn Werber
4 min readMay 20, 2022


Last time, we went through the basic selectors and how to implement them in a stylesheet to apply our styles. Selectors have a lot of sneaky extra ways they can be used though, including the following 4 categories. Let’s get into it.

Photo by Ferenc Almasi on Unsplash


The first of the four advanced categories, following are the four types of combinators, as well as their symbol, and they do exactly what it sounds like they do - combine selectors.

Descendant (space)

Styles all matching tags within the specified element. For example,

div p {}

styles all paragraph tags inside div elements. This works with classes and IDs as well, styling the descendent tag inside the respective class or ID.

Child (>)

Like the descendant selector, but more specific.

div > p {}

would only style the paragraph tags that are directly under the corresponding div, not just any that are in it anywhere.

Adjacent Sibling (+)

Styles a tag that have the same parent and are directly after their sibling.

div + p {}

would only apply to a paragraph tag that is the first sibling element after a div, like this -

<div></div><p>This paragraph gets styled.</p><p>This one doesn’t.</p>

General Sibling (~)

Like the adjacent sibling, but more lenient.

div ~ p {}

would style all paragraph elements following divs, but don’t need to be directly underneath, or ‘adjacent’. Simply have to be on the same level.

Pseudo Classes

These are used to specifically style an element in a certain state. They can be applied to elements, classes, or IDs. One popular one looks like this -

element:hover {}

This would apply the contained styles to the target element on the condition that the user is hovering over it.

Another common application of these types of selectors specifies the iteration of the element. For example -

.container:nth-child(4) p {}

would style the paragraphs that are descendants of the fourth ‘container’ class element. The ‘p’ selector I snuck in there was to keep you on your toes and is a mixture of this type of pseudo class selector, and the descendant combinator selector discussed above. Not necessary, just possible!

Some HTML elements have different applicable pseudo classes, so get more familiar with what is possible here.

Pseudo Elements

Used to select certain parts of an element, rather than the entire element. They apply like pseudo classes, but with two :: rather than one. Pseudo Elements have very specific use cases and many are limited in what styles they can apply. You’ll see what I mean below…

::selection - styles the elements selected by the user. Limited to color, background, cursor, and outline styles.

::before - inserts content before the respective tag.

::after - like ::before, but after…

::marker - styles the bullets of list item elements - <li>

::first-letter and ::first-line - styles the first letter or line of the applicable text. Limited to certain styles like ::selection (though with many more available styles) and only apply to text. For a complete list of applicable styles, read more here.


The neglected sibling to Classes and IDs, Attributes act much the same. Though attributes give us much more customizability, they can be selected in a similar way. The major difference here comes in how attributes are implemented in HTML.

The following div has a class, id, and attribute -

<div class=”container” id=”controller” target=”blank”>

Notice how the attribute doesn’t have to be declared as an attribute unlike class and id. In this case, the attribute is named ‘target’ and it has its own value. In CSS, we can select this by its attribute in the following ways -

[attribute] - selects all element(s) with the attribute.

[attribute=”value”] - selects elements with the related attribute and value.

[attribute~=”value”] - selects elements with an attribute containing the value as a whole. If the target attribute had the values ‘blank’ and ‘top’, then a selector value of ‘top’ would still apply, even if ‘blank’ wasn’t included.

[attribute|=”value”] - selects all elements with attribute values exactly the same the value, or with a hyphen - if the value was ‘top’ then elements with the value ‘top-text’ would still be selected.

[attribute^=”value”] - selects all elements with attribute values beginning with the value.

[attribute$=”value”] - selects all elements with attribute values ending with the value.

[attribute*=”value”] - selects all elements with attribute values containing the value, even partially. If the value was ‘b’ then elements with the attribute value ‘blank’ would be styled.

Bonus Section -

Remember how form inputs have that [type] thing that determines which version of the input it is? This is an attribute! And it can be styled like one too!