Search code examples
javascripthtmlcssgoogle-chrome-extensiondarkmode

Chrome extension - how to apply dark mode CSS correctly (as soon as possible)?


Ok so I want to make a "dark mode" add-on but the problem is I can't apply dark CSS quick enough. When I reload the web page it loads with white background for a 1/2 sec and than it loads my dark css. That wouldn't be a problem but in the night my monitor flashes on each page reload (which is not nice user experience). This is what I have so far: manifest (scripts loading part):

  "permissions": [
    "activeTab",
    "storage",
    "https://www.example.com/*"
    
  ],
"content_scripts": [ 
  {
    "js": [ "jquery.min.js",  "content.js" ],
    "matches": [ "https://www.example.com/*"],
    "run_at": "document_start"
  },
  {
    "css": ["style.css"],
    "matches": [ "https://www.example.com/*"]
  }
  ],
    "background": {
        "scripts": ["background.js"],
        "persistent": false
    },

This is the content.js

chrome.storage.sync.get({
    dark: true
    }, function(items) {
    init(items.dark);
});
function init(options) {
var dark = options;
if(dark){
        $( "body" ).addClass( "darkmode" );
        if (document.readyState == 'loading') {
          $( "body" ).addClass( "darkmode" );
          document.addEventListener('DOMContentLoaded', function(){
              $( "body" ).addClass( "darkmode" );
          });
        }
    }
}

You see here I added "addClass" in every page loading stage just to be sure. The first one works fine, but the problem is that sometimes that line of the code doesn't execute because DOM is not loaded quickly enough.

Inside style.css file I am changing the style using css like this:

.darkmode .somediv .etc a {
color:#fff;
}

I just need to change background of the website to black as soon as the page loads so I don't have that white flash at the beginning. Rest of the CSS can load after 1/2 sec, it doesn't matter.


Solution

  • Remove all document.readyState, DOMContentLoaded, jQuery stuff and replace with this:

    document.documentElement.classList.add('darkmode');
    

    It will add the class on <html> node that already exists at document_start.

    Note that a more efficient approach would be to register/unregister the content script depending on the switch variable in the storage dynamically via chrome.declarativeContent API with RequestContentScript action instead of declaring content_scripts in manifest.json. This action is marked as experimental but it actually works in stable Chrome.