CSS Combinators

Chapter 6 6 mins

Learning outcomes:

  1. What are combinators
  2. Types of combinators

What are combinators?

CSS selectors come already with a whole ton of possibilities to select HTML elements - we can base the selection on ids, classes, tags, attributes with or without values, states such as :hover, :focus, :blur, :visited and the list goes on.

However the potential for element selection doesn't end here - we have something called CSS combinators giving another push to this powerful selection mechanism.

So what are combinators?

Well you have already worked with combinators without realizing it? Remember the space in the selector statement body p - that was a descendant combinator.

Anyways, let's define what a combinator is:

Combinators are delimiters that serve to combine selectors in various ways.

Delimiters, in this case, are simply characters that serve to sit in between two selectors.

The list of combinators in CSS is shown below. Try to relate the purpose of each combinator with its name; it'll be a good excercise to start with.

  1. Descendant combinator - " "
  2. Group combinator - ","
  3. Child combinator - ">"
  4. Next sibling combinator - "+"
  5. General sibling combinator - "~"

Combinators come in between two different selectors and there can be only one of them at a time. You might have had been able to deduce this on yourself, but it's always good to list out things.

Let's consider each combinator turn by turn.

The HTML

To illustrate the differences between the different combinators we'll use the following HTML. Try to skim through it and take note of the level of nesting of each element.

<body>
    <span>Span 0</span>
    <section>
        <span>Span 1</span>
        <div>
            <span>Span 2</span>
            <span>Span 3</span>
        </div>
        <span>Span 4</span>
    </section>
</body>

Although this markup is just plain, unstyled HTML, in all the examples that follow we've styled this to better differentiate the levels of nesting for each element. The final result is shown below.

Span 0
Span 1
Span 2
Span 3
Span 4
Span 5

The idea is to clarify the nesting of each element so that you are able to better understand which combinator selects which set of elements.

Group combinator

The group combinator is given by a comma - ",".

The selector A, B selects all elements A and B. As the name suggests, it simply groups the selectors into one.

Consider the following example illustrating the group combinator.

div, span {background-color: yellow}
<span>Span 0</span>
<section>
    <span>Span 1</span>
    <div>
        <span>Span 2</span>
        <span>Span 3</span>
    </div>
    <span>Span 4</span>
    <span>Span 5</span>
</section>
Span 0
Span 1
Span 2
Span 3
Span 4
Span 5

Here all the divs and spans in the HTML are selected. The group combinator simply groups different selectors together.

If a selector in a group is not recognised by the interpreter the whole group fails and thus no styles are applied as a consequence.

Descendant combinator

The descendant combinator is given by a space - " ".

In the selector A B the descendant combinator selects all the elements B that are the descendants of A. An element B is a descendant of A if and only if B is nested inside A.

Consider the example below to get a better idea of this. All the selected elements are given a highlight.

section span {background-color: yellow}
<span>Span 0</span>
<section>
    <span>Span 1</span>
    <div>
        <span>Span 2</span>
        <span>Span 3</span>
    </div>
    <span>Span 4</span>
    <span>Span 5</span>
</section>
Span 0
Span 1
Span 2
Span 3
Span 4
Span 5

As you can see here, all the span elements that come within section are selected, including the ones in div as well.

Child combinator

The child combinator is given by a greater-than angle bracket - ">".

The selector A > B selects all elements B that are the children of elements A. An element B is the child of A if and only if it is a direct descendant of B i.e directly nested inside it.

Following is an illustration:

section > span {background-color: yellow}
<span>Span 0</span>
<section>
    <span>Span 1</span>
    <div>
        <span>Span 2</span>
        <span>Span 3</span>
    </div>
    <span>Span 4</span>
    <span>Span 5</span>
</section>
Span 0
Span 1
Span 2
Span 3
Span 4
Span 5

As you can see here, only those span elements are selected that are directly nested inside the element section i.e the children of section.

A way to remember which bracket is the child combinator is to just remember that it points from the left to the right - the way an interpreter goes! The > bracket indeed does point this way whereas < doesn't. Hence the former is the child combinator.

Next sibling combinator

The next sibling combinator is given by the plus sign - "+".

The selector A + B selects all the elements B that are the next siblings of the elements A. The element B is a sibling of A if and only if it follows A and has the same parent element.

More generally this combinator is known as an adjacent combinator, but we chose this naming to help us explain how an adjacent combinator works.

div + span {background-color: yellow}
<span>Span 0</span>
<section>
    <span>Span 1</span>
    <div>
        <span>Span 2</span>
        <span>Span 3</span>
    </div>
    <span>Span 4</span>
    <span>Span 5</span>
</section>
Span 0
Span 1
Span 2
Span 3
Span 4
Span 5

As shown, only the span element that follows div is selected.

General sibling combinator

The general sibling combinator is given by the tilde symbol - "~".

The selector A ~ B selects all the elements B that are the siblings of the elements A.

Compare this combinator with the previous one and see how do the differ from each other.

div ~ span {background-color: yellow}
<span>Span 0</span>
<section>
    <span>Span 1</span>
    <div>
        <span>Span 2</span>
        <span>Span 3</span>
    </div>
    <span>Span 4</span>
    <span>Span 5</span>
</section>
Span 0
Span 1
Span 2
Span 3
Span 4
Span 5

Unlike the adjacent sibling combinator, which selected only the first sibling of div, the general sibling combinator selects all siblings of div that are span elements.

A way to remember which of the symbols '+' and '~' represents the adjacent sibling combinator is to take the 't' in 'adjacent' and relate it with the symbol '+', since both look quite similar!

And this is all about CSS combinators! So what is your final verdict on their level of difficulty? Easy, too easy or a piece of cake!