Search code examples
javascriptcssdomcomputed-style

how to query whole DOM for elements matching some computed style ? (in pure js)


For example I want to find all elements that have computed style position: fixed;. How to do it without making much load on the CPU ?

Is iterating every getElementsByTagName('*') and then doing for loop the only way ?


Solution

  • Instead of selecting all (*) elements, and use getComputedStyle + getPropertyValue, you can follow the following steps:

    • Loop through all CSS rules (via document.styleSheets [1]) and take the selectors which contains position: fixed.

    • Select all elements whose style attribute contains position: fixed.

    • Use document.querySelectorAll to select all elements which match the selector.

      • Test whether window.getComputedStyle(elem, null).getPropertyValue('position') equals fixed to filter elements which are not at a fixed position (possibly overridden through a more specific selector, or !important).
      • If it matches, push the element in an array
    • At this point, you have an array containing all position: fixed elements.

    [1] The external stylesheets have to be located at the same origin, because of the Same origin policy.

    Code (small demo: http://jsfiddle.net/GtXpw/):

    //[style*=..] = attribute selector
    var possibilities = ['[style*="position:fixed"],[style*="position: fixed"]'],
        searchFor = /\bposition:\s*fixed;/,
        cssProp = 'position',
        cssValue = 'fixed',
        styles = document.styleSheets,
        i, j, l, rules, rule, elem, res = [];
    
    for (i=0; i<styles.length; i++) {
        rules = styles[i].cssRules;
        l = rules.length;
        for (j=0; j<l; j++) {
            rule = rules[j];
            if (searchFor.test(rule.cssText)) {
                possibilities.push(rule.selectorText);
            }
        }
    }
    possibilities = possibilities.join(',');
    possibilities = document.querySelectorAll(possibilities);
    l = possibilities.length;
    for (i=0; i<l; i++) {
       elem = possibilities[i];
       // Test whether the element is really position:fixed
       if (window.getComputedStyle(elem, null).getPropertyValue(cssProp) === cssValue) {
           res.push(elem);
       }
    }
    res; //<-- = Array containing all position:fixed elements