Here on CodePen we display a modal window (just like the one you just had to close to read this) to users with JavaScript turned off. We like to make it very clear that CodePen isn't a terribly wonderful site without it, but be clear about why. Here's the real one we show:

Example Modal

We recently added that button to actually close the modal and overlay. Normally that's JavaScript territory. Bind a click handler, change a class, CSS hides things. But this modal window needs to work without JS! Here's how.


  <input type="checkbox" class="modal-closing-trick" id="modal-closing-trick">
  <div class="noscript-overlay"></div>
  <div class="modal">
        ... text ...
        <label class="button" for="modal-closing-trick">
          Close this, use anyway.

Notice the input/label pair in there. The "button" you click to close the modal is actually a <label>. When you click that label, the checkbox becomes checked.


Nobody ever see's that checkbox because you hide it. You can even display: none; it, it never needs to be seen or directly used. What we need it for is the checkbox hack which is using CSS's ability to target checkboxes that are in their checked state (:checked) and combine it with the adjacent sibling combinator.

So style up that overlay and modal however you want to, but ultimately hide then when the checkbox gets checked (button is clicked):

  input.modal-closing-trick:checked ~ div {
  display: none !important;


  • We wanted to be very clear about why the site behaves as it does.
  • We were revisiting this idea because of some criticism about it, and wanted to remove the popup entirely from some pages that don't absolutely need JS. One of those types of pages is blog posts like these, although we still have to some work to do to make things like comments work with out JavaScript.
  • We wanted No-JS users to still be able to navigate around even if most of CodePen doesn't work.


One thing I wish I knew is why NoScript (the Firefox plugin) doesn't trigger the <noscript> tags. There is even a setting for hiding them that I don't have checked here.