CSS descendant combinator?

Hi guys I’m going through the CSS Flexbox chapter and currently doing the following challenge: https://learn.freecodecamp.org/responsive-web-design/css-flexbox/add-flex-superpowers-to-the-tweet-embed

No problem with the challenge itself, I’m just trying to figure out this notation as it’s the first time I see it:

header .profile-thumbnail {
    width: 50px;
    height: 50px;
    border-radius: 4px;
  }

By playing around with the code I realized that what it basically does is making available the .profile-thumbnail class only in HTML elements nested below an <header> and if used outside of it it doesn’t affect the element.
First: am I correct?
Second: does this notation have a name?
By looking around it seems to me that it might be descendant combination but I’m not sure as the examples I found are slightly different.

Thanks for your help!

You have the name of the selector right it is a descendant selector (or combinator). The styles in the class will apply to any element with the class, using the descendant selector scopes it to only apply the styles to elements inside the element.

Let say for some reason you had two profile-thumbnail, one was in the header and one was somewhere else on the page and you wanted to give them different styles depending on the DOM location.

/* base style */

.profile-thumbnail {
  width: 50px;
  height: 50px;
}

/* styles for when in the header */
header .profile-thumbnail {
  border-radius: 4px;
  margin-right: auto;
}

/* styles for when in the user-card element */
.user-card .profile-thumbnail {
  border: none;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, .4);
}

This type of scoping when applying styles is not really best practice because the styles are now tied to the DOM structure which makes it less flexible. It would be better to treat them as components and have separate classes and/or use utility classes to overwrite some styles.

1 Like

Yes, that’s what it does, the space is called a descendent combinator. It can be used multiple times to allow nesting to any depth – div .class1 .class2 .class3 etc.

There is also the child combinator (>) which selects a direct child, so like header > .profile-thumbnail will select the thumb that is a direct child of the header, whereas header .profile-thumbnail will select the thumb nested at any depth below the header.

header .profile-thumbnail will select the thumb here:

header
  .profile-thumbnail

And here:

header
  div
    div
      div
        .profile-thumbnail

Whereas header > .profile-thumbnail will only select the thumb in the first case.

Note though:

  • you should understand how CSS specificity works: using combinators will increase the specificity, rules defined under header .profile-thumb will beat rules defined under just .profile-thumb. This seems like a good thing but tends to cause no end of problems, so it is very often preferable to have specific classes rather than nesting. eg a .header-profile-thumb class on the profile thumb in the header rather than header .profile-thumb.
  • CSS matches right-to-left. Performance problems relating to this aren’t generally that much of a concern these days, but be aware that the parser doesn’t look at the rule, go to the header, then to the .profile-thumbnail, it instead finds every profile-thumbnail and then filters it on ones that are in a header. Which sounds a bit abstract, but take for example .main-nav ul li div. The parser selects every div on the page, then filters by every one in a li, then every on in an ul, then every one in an element with the class .main-nav.
2 Likes

Thanks guys, answers on point! :ok_hand:

1 Like