/focus-within

Style elements when they are focused or contain a focused element

Primary LanguageJavaScriptCreative Commons Zero v1.0 UniversalCC0-1.0

Focus Within

NPM Version Build Status Support Chat

Focus Within lets you style elements when they are focused or contain a focused element, following the Selectors Level 4 specification.

.field label {
  /* style a label */
}

.field:focus-within label {
  /* style a label when its field also contains a focused element */
}

Usage

From the command line, transform CSS files that use :focus-within selectors:

npx focus-within SOURCE.css TRANSFORMED.css

Next, use your transformed CSS with this script:

<link rel="stylesheet" href="TRANSFORMED.css">
<script src="https://unpkg.com/focus-within/browser"></script>
<script>focusWithin(document)</script>

That’s it. The script is 379 bytes and works in all browsers, including Internet Explorer 9.

How it works

The PostCSS plugin duplicates rules containing :focus-within, replacing them with an alternative [focus-within] selector.

.field:focus-within label {
  font-weight: bold;
}

/* becomes */

.field[focus-within] label {
  font-weight: bold;
}

.field:focus-within label {
  font-weight: bold;
}

Next, the JavaScript library adds a focus-within attribute to elements otherwise matching :focus-within natively.

<html focus-within>
  <body focus-within>
    <form focus-within>
      <div class="field" focus-within>
        <label for="a">Field</label>
        <input id="a" value="This element is focused" focus-within>
      </div>
      <div class="field">
        <label for="b">Field</label>
        <input id="b" value="This element is not focused">
      </div>
    </form>
    <p>Some sibling text element.</p>
  </body>
</html>

GOTCHA!

One cannot simply add the [focus-within] selector to an existing rule:

.field:focus-within label, .field[focus-within] label {}

Browsers that don't support :focus-within will throw the entire rule away! This is why you should follow the Usage instructions.