A single hexagonal snowflake against a yellow and blue background

The logical next step from the :empty and :only-child CSS selectors, only-of-type selects single instances of particular elements in a particular context.

Whereas :only-child cares only if the targeted element is by itself inside its container, :only-of-type actually looks at the element to determine if it is the only one of its kind in its context. That is, given this markup:

<div>
    <h1>Major heading</h1>
    <p>Body text…</p>
</div>

The following test will fail to change the paragraph:

div p:only-child { color: red; }

…since the paragraph is not the only child of its <div> parent. But using :only-of-type will turn the paragraph red:

div p:only-of-type { color: red; }

… since the paragraph is the only one of its kind inside the <div>. Naturally, this can be extended by using classes and other selectors:

div.wolf span.cub { … }

… which would select a <span> element with a class of cub only if it is the sole span with a class of cub inside a <div> with a class of wolf.

Uses for :only-of-type

:only-of-type is especially useful for styling images inside of <figure> elements. Since those elements will almost always contain a <figcaption> in addition to an <img>, :only-child will not apply to the image… but only-of-type will. If we know that the image is the only one inside its container, we can responsively scale it to be 100% the width of it’s containing element:

figure img:only-of-type {
    width: 100%; 
    height: auto;
}

If there was more than one image within the <figure>, you could apply flexbox or another solution to evenly distribute the elements. You can also use the inverse, with the :not selector, to determine that there is more than one image in the <figure>:

figure img:not(:only-of-type) {
    flex: 1;
}

If there is no ancestor selector defined in the selector, it is assumed that :only-of-type will eliminate from selection any matching elements that have siblings of the same type, at the same level. That is, given the following markup:

<article></article>
<article></article>
<div>
  <article></article>
</div>

And the following CSS:

article:only-of-type { 
    border: 1px solid red;
}

… only the third article will have a border applied to it.

Support

:only-of-type is supported in every modern browser, including IE9+, far backwards in terms of versions (Safari 3.1+ supports the selector, for example); it is not supported in IE8.

Photograph by Alexey Kljatov, licensed under a Creative Commons Attribution-NonCommercial 2.0 Generic license

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.