Today I Learned...

...about the :user-invalid CSS pseudo-class

By mherchel, 2 October, 2023

The user-invalid CSS peudo-class allows you to display styles when an input is invalid. This is different than :invalid, because it will only trigger after a user has interacted with it. You can also combine it with :has() or the sibling selector to show/hide error messages.

This is currently available in Firefox, and Safari (16.5), and will be in Chromium 119.

input[type="search"]:user-invalid {
  outline: solid 1px red;

..about the Scripting CSS media feature

By mherchel, 25 September, 2023

The Scripting CSS media feature allows you to use a media query to detect whether the browser supports JavaScript.

.my-element {
  display: none;
} {
  display: block;

@media (scripting: none) {
  .my-element {
    display: block;

Why is this important?

Currently the standard way to do this is to add a js CSS class to the HTML element.

This allows you to do a html:not:(.js) { /* no JS styles */ } in your CSS, to apply styles when JS is not available.

However this is problematic because the browser can sometimes take a bit of time for the JS to load. This results in the user seeing the non-JS styles… which can result in a flash of unstyled content (FOUC).

You can work around this by adding a <noscript> tag in the <head> of your HTML, and then adding a special noscript.css in there, but this is a pain.

The new method works perfectly, doesn’t require a <noscript> tag, removes any FOUC, and is easy to implement with nesting (either Sass, PostCSS, or native).

How do I plan on using this?

Currently in Drupal core, there’s a good amount of jankiness on the admin side because of showing and hiding of elements based on either inline styles (in the case of Drupal state), or because of the html:not(.js) method. These can be entirely eliminated in the future!

Browser support

Firefox has supported this since version 113 (May 2023), and Chrome and Safari will have this enabled in their very next releases! See CanIUse for more.