Skip to main content
kld.dev

Detecting JavaScript support in CSS

Let’s say you’ve added a “Copy to clipboard” button to your web app. And let’s also assume that this is a critical application that needs to be resilient enough to work even when JavaScript is disabled by the user. How can you only show the “Copy to clipboard” button when JavaScript is available?

Use JavaScript of course

If this is a pattern you only need once for your clipboard button, then one obvious solution is to simply use JavaScript to show the button.

<!-- Button is initially hidden -->
<button style="display: none">Copy to clipboard</button>
// Button is revealed some time after page load...
buttonElement.style.display = 'inline-block';

However, this can get tiring quickly if you need to do this for other elements.

Noscript? Noproblem

This is a neat trick I picked up years ago. You can place a <style> block inside a <noscript> block, and those styles will only apply when JavaScript is disabled.

<noscript>
  <style>
    button.clipboard-button {
      display: none;
    }
  </style>
</noscript>

You can take this a step further by creating some convenient utility classes.

Keep it classy

Here are some classes I’ve used that follow the Tailwind variant naming convention (e.g. sm:hidden, hover:bg-black, etc.). They are defined within my HTML’s <head> section.

<head>
  <noscript>
    <style>
      .nojs\:hidden {
        display: none !important;
      }
      .nojs\:block {
        display: block !important;
      }
      .nojs\:flex {
        display: flex !important;
      }
      .nojs\:grid {
        display: grid !important;
      }
      /* ... inline, inline-block, etc. as needed */
    </style>
  </noscript>
</head>

I can then show or hide elements based on whether JavaScript is enabled, and I don’t have to add any more <noscript> tags or additional JavaScript.

<button class="nojs:hidden">Do JavaScript</button>

<button class="hidden nojs:inline-block">Do non-JS stuff</button>

Isn’t there a media query for this?

Yes, there is a scripting media feature for whether JavaScript is enabled!

@media (scripting: none) {
  .nojs\:hidden {
    display: none !important;
  }
}

@media (scripting: enabled) {
  .clipboard-button {
    display: inline-block;
  }
}

In the long run, I think this is a preferable solution since it does not require the <noscript> and can be easily incorporated into your existing CSS. However, as of writing, the global support for this is 89.76%, so depending on your user base, the media query approach may or may not be a viable option.

Use cases

I could probably think of a million other uses for this if someone locked me in a cell and forced me to do so.

  • Showing a search button next to a search input that would otherwise search as you type
  • Showing a submit button for a form that would otherwise do a fetch after input, change, or blur events
  • Hiding loading spinners
  • Hiding live chat support, custom video players, interactive data visualizations, and all those other gizmos
  • And although this approach might be overkill for it, I have to include the dreaded “You must enable JavaScript to use this site.”

Bonus tip

In case you were not aware, you can enable and disable JavaScript in Chrome DevTools for testing purposes:

  1. Press Cmd+Shift+P or Ctrl+Shift+P to open the Command Menu.
  2. Start typing javascript, and select the Disable JavaScript or Enable JavaScript command.
  3. Press Enter. You will see a little exclamation triangle icon on the Sources tab while JavaScript is disabled.
  4. Reload the page.

Bonus to the bonus tip

In Firefox DevTools, the Disable JavaScript command can be found in the Debugger tab’s gear menu.

Webmentions

Kevin Lee Drum
@amxmln Another one for the tool belt! Thanks!
Amadeus Maximilian
@kevinleedrum it’s also great if you do something like fading out lazy-loaded images until they’re available. ????