Pseudo Classes FTW


Most people who have written more than a few lines of CSS are familiar with pseudo classes. I use :hover in every stylesheet, :nth-child has been a savior on occasion, and I find :not() to be an elegant and readable solution for many layout problems. In this post I would like to discuss the :empty and :only-child selectors and present practical applications for each of them.
 


:only-child

The :only-child pseudo selector can be applied to styling one of the most common features on the web - a dropdown navigation. Imagine the HTML for a dropdown navigation.

  <ul class="nav">
    <li class="nav__item">
      <a class="nav_link" href="#">Home</a>
    </li>
    <li class="nav__item">
      <a class="nav_link" href="#">About</a>
    </li>
    <li class="nav__item">
      <a class="nav_link" href="#">Portfolio</a>
      <ul class="dropdown">
        <li class="drop__item">
          <a class="dropdown__link" href="#">Paintings</a>
        </li>
        <li class="drop__item">
          <a class="dropdown__link" href="#">Drawings</a>
        </li>
        <li class="drop__item">
          <a class="dropdown__link" href="#">Sculpture</a>
        </li>
      </ul>
    </li>
  </ul>

In this case we have a dropdown menu within only one of the top-level menu items. We want to give the user a visual cue when a dropdown is available. We can accomplish this without any additional markup using the :only-child pseudo selector.

First we can easily display a simple down arrow next to all of the top-level navigation links with a little help from the :after pseudo element.

  .nav__link {
    &:after {
      content: "⇓";
    }
  }

Then we can remove the arrow for links that don't have a dropdown within them (aka links that are the only child of their parent element).

  .nav__link {
    &:after {
      content: "⇓";
    }
    &:only-child {
      &:after {
        content: none;
      }
    }
  }

There you have it. See a CodePen here.
 


:empty

I recently got stuck on a unique layout problem. I had a module that contained two column s that were displayed next to each other. They each occupied half the width of their parent. On occasion, however, one of the columns would be empty, in which case the other needed to expand to fill the container and center its content. I was unable to change much of the markup, so I was hoping to solve this problem with pure CSS. Luckily I remembered the :empty pseudo class.

Take the basic markup for the issue above.

  <div class="row">
    <div class="col"></div>
    <div class="col">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Perspiciatis, doloremque?
    </div>
  </div>

It's easy to style this layout as two columns (I'd use inline-block), but how can we style it as one column when one of the s is empty? You guessed it, :empty.

  .col {
    &:empty {
      display: none;
    }
  }

Now we have the empty out of the way, but we still need to style the other accordingly. Fret not! By combining :empty and the adjacent sibling selector (+) we can target that and style it however we need to.

  .col {
    &:empty {
      display: none;
      & + .col {
        text-align: center;
        width: 75%;
        display: block;
        margin: 0 auto;
      }
    }
  }

See a CodePen here.


There you have it. CSS has some pretty obscure rules, and while you may not need to know them all it certainly helps to at least know that they're there. Happy coding.

Share this post

The Author

Zack Piper

Front End Developer