title: CSSRules group selectors with common properties
body: <p>This script when included in an HTML document which includes any declared styles (excluding those set by <code>style=""</code>) will output an optimized stylesheet to the to the page. The script uses the following methods...</p>
  
  <ol>
  <li>Ignore any <code>@</code> or <code>:</code> rules to leave responsive styles as is.</li>
  <li>Separate the rules into single selector rules so we can test for inheritance later on.</li>
  <li>Remove rules that apply to selectors which don't exist in the document, thanks to <a href="https://stackoverflow.com/users/3903374/rick-hitchcock">@RickHitchcock</a> for this.</li>
  <li>Retrieve both the declared and computed styles in the same format (excluding percentages) then compare both values each other, then remove the property and check again.</li>
  <li>if the declared value matches the computed value and by removing the property the value changes, then set the keep flag. This tells us whether the property has an effect on an element, if no elements were affected by the property... remove it.</li>
  <li>If there are no properties in the remaining <code>CSSRule</code> then remove that rule.</li>
  <li>As a side effect most selectors which don't change the browsers default setting will be removed (unless using <code>font</code> as opposed to <code>font-*</code> and similar which will activate the rest of the settings for that property).</li>
  </ol>
  
  <p>While running this script on a site which includes styles relating to dynamic elements, I just wrap them in a media query</p>
  
  <pre><code>@media (min-width: 0px) {
      /* This says that these styles always apply */
  }
  </code></pre>
  
  <h3>Question</h3>
  
  <p>How can I group the selectors with common properties?</p>
  
  <p>(<a href="http://jsfiddle.net/humbleRumble/w27ze0hr/15/" rel="nofollow noreferrer">Demo</a>)</p>
  
  <pre class="lang-js prettyprint-override"><code>var stylesheets = document.styleSheets, stylesheet, i;
  var ruleText = "";
  if(stylesheets &amp;&amp; stylesheets.length) {
      for (i = 0; (stylesheet = stylesheets[i]); i++) {
          var rules = stylesheet.rules, rule, j;
          if(rules &amp;&amp; rules.length) {
              for (j = 0; (rule = rules[j]); j++) {
                  if(rule.type === rule.STYLE_RULE) {
                      if(rule.selectorText.indexOf(',') &gt;= 0) {
                          var newRules = [];
                          var selectors = rule.selectorText.split(','), selector, k;
                          for(k = 0; (selector = selectors[k]); k++) {
                              var styles = rule.style, style, l;
                              var elements = document.querySelectorAll(selector.trim()), element, l;
                              if(elements.length) {
                                  var styleString = '';
                                  for(m = 0; (style = styles[m]); m++) {
                                      styleString += style + ': ' + styles.getPropertyValue(style) + "; ";
                                  }
                                  newRules.push((selector.trim() + ' { ' + styleString.trim() + ' }'));
                              }
                          }
                          stylesheet.deleteRule(j);
                          for(k = 0; (rule = newRules[k]); k++) {
                              stylesheet.insertRule(rule, j);
                          }
                      }
                  }
              }
              for (j = 0; (rule = rules[j]); j++) {
                  if(rule.type === rule.STYLE_RULE &amp;&amp; rule.selectorText.indexOf(':') &lt; 0) {
                      var styles = rule.style, style, k;
                      var elements = document.querySelectorAll(rule.selectorText);
                      if(elements &amp;&amp; elements.length) {
                          for(k = 0; (style = styles[k]); k++) {
                              var value = styles.getPropertyValue(style);
                              if(value.indexOf('%') &lt; 0) {
                                  var elements = document.querySelectorAll(rule.selectorText), element, m;
                                  var keep = false;
                                  for(m = 0; (element = elements[m]); m++) {
                                      var computed = window.getComputedStyle(element).getPropertyValue(style);
                                      var match1 = value === computed;
                                      styles.removeProperty(style);
                                      var computed = window.getComputedStyle(element).getPropertyValue(style);
                                      var match2 = value === computed;
                                      styles.setProperty(style, value);
                                      if( match1 &amp;&amp; !match2 ) {
                                          keep = true;
                                      }
                                  }
                                  if(!keep) {
                                      styles.removeProperty(style);
                                  }
                              }
                          }
                          ruleText += rule.cssText + "\n";
                      }
                  } else {
                      ruleText += rule.cssText + "\n";
                  }
              }
          }
      }
  }
  document.body.innerHTML = '&lt;pre&gt;' + ruleText + '&lt;pre&gt;';
  </code></pre>
  
  
  
  <p>Future viewers: this is available on github as <a href="https://github.com/humbleRumble/optiCSS" rel="nofollow noreferrer">optiCSS</a> (read: eye-pleasing)</p>