Search code examples
htmlfirefox-addonnoscript

Alternative to noscript tag that works with firefox NoScript addon


I am making a website that uses a small amount of javascript javascript for non-essential or merely aesthetic functionalities. I am aware that there is a percentage of users that prefer to navigate with javascript disabled, so in principle I tried to use a css style sheet within a noscript tag in the head of the page so that where javascript was not available, certain elements of the page will be hidden.

However, while this approach works when javascript is disabled in the browser, it fails for users that block javascript with certain browser extensions (I tested with NoScript for Firefox, surely there are others). What would be an alternative method to achieve what I wanted to with the noscript tag in this scenario?


Solution

  • NoScript works by removing the script tags from the document and thus preventing the js files from being loaded, but it does not disable the execution of scripts, so the noscript tag does not work.

    To remove certain elements of the page when javascript is not available, regardless of the cause, the best approach is to make those elements hidden by default, and reveal them with javascript after loading the page. The first step would be creating a CSS class like the one below in your stylesheet and apply it to everything you do not want to be visible unless JS scripts can be executed:

    .hideOnNoScript {
        display: none !important;
    }
    

    Second step would be to remove that CSS class with javascript on page load:

    //Execute after page is ready
    function ready(callback){
      // in case the document is already rendered
      if (document.readyState!='loading') callback();
      // modern browsers
      else if (document.addEventListener)
          document.addEventListener('DOMContentLoaded', callback);
      // IE <= 8
      else document.attachEvent('onreadystatechange', function(){
          if (document.readyState=='complete') callback();
      });
    }
    
    var removeHideOnNoScript = function() {
      var elementstohide = window.top.document.querySelectorAll('.hideOnNoScript ');
      for (let i= 0; i< elementstohide.length; i++) {
        const element = elementstohide[i];
        element.classList.remove('hideOnNoScript');
      }
    }
    
    ready(removeHideOnNoScript);
    

    Note: I really dislike having to use !important, but I have not managed to make this solution work without it. I would be glad to change it if anyone can point me to an alternative.