0

I'm building a userscript and to avoid the dreaded 'jittering' effect as the userscript edits the page's styles once the page has finished rendering I'm attempting to do it while the page is still loading.

Doing this by inserting rules into a pre-existing style object works as expected....
http://pastebin.com/NNjLjKA5 ...wait until a style object exists then add a new style to it.

However when trying to create a new style object to insert the rules into I'm experiencing weird behavior...

// ==UserScript==
// @name           script
// @include        *
// @run-at document-start
// ==/UserScript==

// Add style rules while page is loading (to prevent jumping)
function addStyleRules(){

    // Check if stylesheets exist yet, if not try again in a bit
    if( !document.styleSheets[0] ) return setTimeout( addStyleRules,1 );

    // Get/create stylesheet element (if not already created)
    if( !document.querySelector( 'style[title=new_stylesheet]' ) ){
        var css = document.createElement( 'style' );
        css.type = "text/css";
        document.head.appendChild( css );
        css.title = 'new_stylesheet';
    }

    // Get stylesheet object
    var ss;
    for(i in document.styleSheets )
        if( document.styleSheets[i].title == 'new_stylesheet' )
            ss = document.styleSheets[i];

    // Add style rules
    if(ss.addRule)
        ss.addRule( '*','background-color:black',0);
    else
        ss.insertRule('*{background-color:black}',0);

    //debug
    console.log( 'page loading', ss, new Date().getTime() );
}
addStyleRules();

// Page has finished loading
document.addEventListener('DOMContentLoaded',function(e){

    // Get stylesheet object
    var ss;
    for(i in document.styleSheets )
        if( document.styleSheets[i].title == 'new_stylesheet' )
            ss = document.styleSheets[i];

    //debug
    console.log('page loaded', ss, new Date().getTime() );
});


This script should create a new style element, find the new style object in 'document.styleSheets', then apply a new rule.

It seems to do this fine, as observed by the first log event. However once the page has finished loading the new style object no longer exists (even though the style element is present in the DOM).

So yeah, my question is...
What's happening to the newly created stylesheet object in between it being created, having a new rule successfully applied, and the 'DOMContentLoaded' event firing?

  • Browser is Chrome 16.0.912.77
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
JBradwell
  • 11,433
  • 3
  • 15
  • 8

1 Answers1

1

Several things:

  1. For style overrides, don't reinvent the wheel. Use the Stylish extension. It allows for quick, easy changes, and sharing/reuse of styles. There are zillions of styles already developed at userstyles.org.

  2. If you want it in a script anyway, avoid all that stylesheet and addRule() rigamarole. Just add the CSS using your script's manifest. :

    1. Create a CSS file with your changes, EG:
      * {background-color:lime!important;}
      and place it in the same folder as your script's JS.
    2. Add a line to the manifest file that includes the CSS file. EG:
      "css": [ "myCSS.css" ],
    3. See this answer for more information on script locations and the manifest file.

  3. Your current script works, but apparently doesn't give the results you want because the rule that the script sets (background-color:black) is being overruled by later CSS.

    1. Use the !important keyword to stop most (but not all) later CSS rules from taking precedence. EG:

      if (ss.addRule)
          ss.addRule ('*', 'background-color:black!important;', 0);
      else
          ss.insertRule ('*{background-color:black!important;}', 0);
      

      This may be all you need, in your case, but refer to points 1 and 2. ;)

    2. The rule is being set against the universal selector (*). That means that more-specific rules may override it. So, you may need to be more specific, EG: body {background-color:lime!important;} to get the changes to stick.
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295