Fuckin’ incompatible vendor’s pseudo selectors

work arround for сombine several incompatible selectors in one rule

by denvdmj

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify-css.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.11.0/highlight.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.11.0/styles/androidstudio.min.css">
<input class="range" type="range" value="0" max="1000" min="0" />

<h2 class="source-css">Source CSS</h2>
<pre id="idSourceCSS"></pre>
<h2 class="current-css">Current CSS</h2>
<pre id="idCurrentCSS"></pre>

<pre style="display:none">
Firefox:
::-moz-range-track
::-moz-range-thumb

Internet Explorer:
::-ms-thumb
::-ms-track
::-ms-fill-lower
::-ms-fill-upper

Webkit (Chrome, Safari, Opera):
::-webkit-slider-runnable-track
::-webkit-slider-thumb
</pre>

<style>
  @import url(https://codepen.io/DenVdmj/pen/NBGQxq.css);
  :root {
    margin: 2em;
  }
  body {
    font: 16px/1.5 "Roboto Condensed";
    max-width: 40rem;
    min-width: 18rem;
    margin: 2em auto;
  }
  pre {
    font: 14px/1.5 "Iosevka Web", "IosevkaWEB", monospace;
    margin: 1em 0;
    padding: 1em;
    border-top: 12px solid #777;
  }
  h2.source-css { color: #099 }
  h2.current-css { color: #909 }
  #idSourceCSS { border-color: #099 }
  #idCurrentCSS { border-color: #909 }
  
  .range {
    margin: 0;
    height: 20px;
    width: calc(100% - 10px);
    background-color: #999;
   -webkit-appearance: none;
  }
  
</style>

CSS

[type="range"][pseudo=-webkit-slider-thumb],
[type="range"][pseudo=-moz-range-thumb] {
 -webkit-appearance: none;
  border: 1px solid red;
  border-radius: 5px;
  padding: 0;
  margin: 0;
  width: 30px;
  height: 30px;
  background-color: #BC9;
}

JavaScript

(() => {
  //
  // work arround for сombine several incompatible selectors in one rule:
  //
  for (let sheet of document.styleSheets) {
    // except those that are added dynamically
    if (!sheet.ownerNode.firstChild && !sheet.ownerNode.href) continue;
    let cssRulesEntries;
    // test on cors error
    try {
			cssRulesEntries = [].entries.call(sheet.cssRules);
    } catch (e) {
     	continue;
    }
    // patching styles:
    for (let [index, rule] of cssRulesEntries) {
      for (let selector of (rule.selectorText||'').split(/\s*,\s*/)) {
        const match = selector.match(/^(.*?)\[pseudo\s*=\s*["']?([\w-]+)["']?\s*\]/);
        if (!match) continue;
        const cssText = `${match[1]}::${match[2]} ${
          rule.cssText.substr(rule.selectorText.length+1)
        }`;
        try {
          sheet.insertRule(cssText, index+1);
          sheet.deleteRule(index);
        } catch (err) {}
      }
    }
  }
})();


//////////
// DEMO //
//////////

const getCurrentCSS = filter => {
  const list = [];
  for (let sheet of document.styleSheets) {
    if (!sheet.ownerNode.firstChild && !sheet.ownerNode.href) continue;
    try { sheet.cssRules } catch (e) { continue }
    for (let rule of Array.prototype.values.call(sheet.cssRules)) {
      if (filter.test(rule.cssText))
        list.push(rule.cssText);
    }
  }
  return list.join('\n');
};

const option = { indent_size: 2 };

idSourceCSS.textContent =
  css_beautify(
    document.querySelector('head > style').textContent,
    option
  )
;

idCurrentCSS.textContent =
  css_beautify(getCurrentCSS(/type="range"/), option)
;

hljs.highlightBlock(idSourceCSS);
hljs.highlightBlock(idCurrentCSS);