A lot of people are surprised by this, but sometimes, JavaScript isn't available.

There are a number of reasons why it might not be, but about 1% of users visiting your site probably won't have it for one reason or another.

Sometimes you'll be working on a project that requires JavaScript to work. That's often the reality of the web these days (though, I'm not sure if it needs to be, but that's an argument for another day).

But, when possible, we should provide a fallback of some sorts because right now if it isn't working, they'll have some filters that don't do anything.

We have two options:

  • Hide the filters, and use JavaScript to show them on the page
  • Keep the filters and use the CSS-only option as a fallback

Hiding the filters

Hiding the filters is very easy.

First, we can add a hidden attribute on both selects, and then when our JavaScript loads, we remove them:

function enableFiltering() {
  seasonalFilter.removeAttribute("hidden");
  edibleFilter.removeAttribute("hidden");
}

enableFiltering();

Using a CSS-only fallback

Rather than using a hidden attribute, we could put a no-js class on the html element, and then do this:

.no-js {
  .mushroom-guide:has(#season [value="spring"]:checked)
    .card:not(:has([data-season="spring"])) {
    display: none;
  }

  /* other styles here */
}

And use JS to remove the class when JS loads:

function enableJavaScript() {
  document.documentElement.classList.remove("no-js");
}

enableJavaScript();

The two look the same

Right now, they do behave in the same way, though I know very well how a lot of people will complain about the CSS-only solution because it is difficult to read.

The JavaScript option has the added bonus of adding the message if no filters match, though this could be replicated with CSS too.

The simpler approach with JavaScript (and DOM manipulation is more of a JS thing anyway), we can fancy up the animations a little as well.