How to list all css variables names/values pairs from element












7















I have JS library and I have this issue: I'm creating temporary element for calculating size of character using monospace font. Right now I'm copying inlie style, but I need all styles from original including css variables. I don't want to clone the element, because there are elements, that are inside, that I don't need. Also element may have id set by the user, not sure how this will behave when there will be two elements with same id, so it would be better (I think) to just copy each style to new temporary element.



I have code based on these:




  • Accessing a CSS custom property (aka CSS variable) through JavaScript

  • Set javascript computed style from one element to another


My code look like this:



function is_valid_style_property(key, value) {
//checking that the property is not int index ( happens on some browser
return typeof value === 'string' && value.length && value !== parseInt(value);
}

function copy_computed_style(from, to) {
var computed_style_object = false;
computed_style_object = from.currentStyle || document.defaultView.getComputedStyle(from, null);

if (!computed_style_object) {
return;
}
Object.keys(computed_style_object).forEach(function(key) {
var value = computed_style_object.getPropertyValue(key);
if (key.match(/^--/)) {
console.log({key, value}); // this is never executed
}
if (is_valid_style_property(key, value)) {
to.style.setProperty(key, value);
}
});
}


the problem is that getComputedStyle, don't return css variables. Is there any other solution to get list of css variables applied to element?



I need CSS variables because I have css that is applied to element that are inside of my temporary item, that is based on css variables. Is clone node the only way to copy CSS variables from one element to other?



EDIT:



this is not duplicate because css variable can also be set inline not only in style sheet per class. And my element can have style added by very different css selectors that I can't possibly know.










share|improve this question

























  • Possible duplicate of Get all CSS properties for a class or id with Javascript/JQuery

    – user6656728
    Jan 2 at 10:26











  • @MumbaiWadala does this consider CSS Custom properties?

    – Temani Afif
    Jan 2 at 10:27











  • do look at the example it will help you

    – user6656728
    Jan 2 at 10:28













  • CSS custom properties != CSS variables

    – connexo
    Jan 2 at 10:36








  • 2





    @MumbaiWadala this is not a duplicate because I don't want to find css for single selector but for single element that can be accessed in very different selectors, that I can't possibly know. I also need to include inline styles.

    – jcubic
    Jan 2 at 10:53


















7















I have JS library and I have this issue: I'm creating temporary element for calculating size of character using monospace font. Right now I'm copying inlie style, but I need all styles from original including css variables. I don't want to clone the element, because there are elements, that are inside, that I don't need. Also element may have id set by the user, not sure how this will behave when there will be two elements with same id, so it would be better (I think) to just copy each style to new temporary element.



I have code based on these:




  • Accessing a CSS custom property (aka CSS variable) through JavaScript

  • Set javascript computed style from one element to another


My code look like this:



function is_valid_style_property(key, value) {
//checking that the property is not int index ( happens on some browser
return typeof value === 'string' && value.length && value !== parseInt(value);
}

function copy_computed_style(from, to) {
var computed_style_object = false;
computed_style_object = from.currentStyle || document.defaultView.getComputedStyle(from, null);

if (!computed_style_object) {
return;
}
Object.keys(computed_style_object).forEach(function(key) {
var value = computed_style_object.getPropertyValue(key);
if (key.match(/^--/)) {
console.log({key, value}); // this is never executed
}
if (is_valid_style_property(key, value)) {
to.style.setProperty(key, value);
}
});
}


the problem is that getComputedStyle, don't return css variables. Is there any other solution to get list of css variables applied to element?



I need CSS variables because I have css that is applied to element that are inside of my temporary item, that is based on css variables. Is clone node the only way to copy CSS variables from one element to other?



EDIT:



this is not duplicate because css variable can also be set inline not only in style sheet per class. And my element can have style added by very different css selectors that I can't possibly know.










share|improve this question

























  • Possible duplicate of Get all CSS properties for a class or id with Javascript/JQuery

    – user6656728
    Jan 2 at 10:26











  • @MumbaiWadala does this consider CSS Custom properties?

    – Temani Afif
    Jan 2 at 10:27











  • do look at the example it will help you

    – user6656728
    Jan 2 at 10:28













  • CSS custom properties != CSS variables

    – connexo
    Jan 2 at 10:36








  • 2





    @MumbaiWadala this is not a duplicate because I don't want to find css for single selector but for single element that can be accessed in very different selectors, that I can't possibly know. I also need to include inline styles.

    – jcubic
    Jan 2 at 10:53
















7












7








7


1






I have JS library and I have this issue: I'm creating temporary element for calculating size of character using monospace font. Right now I'm copying inlie style, but I need all styles from original including css variables. I don't want to clone the element, because there are elements, that are inside, that I don't need. Also element may have id set by the user, not sure how this will behave when there will be two elements with same id, so it would be better (I think) to just copy each style to new temporary element.



I have code based on these:




  • Accessing a CSS custom property (aka CSS variable) through JavaScript

  • Set javascript computed style from one element to another


My code look like this:



function is_valid_style_property(key, value) {
//checking that the property is not int index ( happens on some browser
return typeof value === 'string' && value.length && value !== parseInt(value);
}

function copy_computed_style(from, to) {
var computed_style_object = false;
computed_style_object = from.currentStyle || document.defaultView.getComputedStyle(from, null);

if (!computed_style_object) {
return;
}
Object.keys(computed_style_object).forEach(function(key) {
var value = computed_style_object.getPropertyValue(key);
if (key.match(/^--/)) {
console.log({key, value}); // this is never executed
}
if (is_valid_style_property(key, value)) {
to.style.setProperty(key, value);
}
});
}


the problem is that getComputedStyle, don't return css variables. Is there any other solution to get list of css variables applied to element?



I need CSS variables because I have css that is applied to element that are inside of my temporary item, that is based on css variables. Is clone node the only way to copy CSS variables from one element to other?



EDIT:



this is not duplicate because css variable can also be set inline not only in style sheet per class. And my element can have style added by very different css selectors that I can't possibly know.










share|improve this question
















I have JS library and I have this issue: I'm creating temporary element for calculating size of character using monospace font. Right now I'm copying inlie style, but I need all styles from original including css variables. I don't want to clone the element, because there are elements, that are inside, that I don't need. Also element may have id set by the user, not sure how this will behave when there will be two elements with same id, so it would be better (I think) to just copy each style to new temporary element.



I have code based on these:




  • Accessing a CSS custom property (aka CSS variable) through JavaScript

  • Set javascript computed style from one element to another


My code look like this:



function is_valid_style_property(key, value) {
//checking that the property is not int index ( happens on some browser
return typeof value === 'string' && value.length && value !== parseInt(value);
}

function copy_computed_style(from, to) {
var computed_style_object = false;
computed_style_object = from.currentStyle || document.defaultView.getComputedStyle(from, null);

if (!computed_style_object) {
return;
}
Object.keys(computed_style_object).forEach(function(key) {
var value = computed_style_object.getPropertyValue(key);
if (key.match(/^--/)) {
console.log({key, value}); // this is never executed
}
if (is_valid_style_property(key, value)) {
to.style.setProperty(key, value);
}
});
}


the problem is that getComputedStyle, don't return css variables. Is there any other solution to get list of css variables applied to element?



I need CSS variables because I have css that is applied to element that are inside of my temporary item, that is based on css variables. Is clone node the only way to copy CSS variables from one element to other?



EDIT:



this is not duplicate because css variable can also be set inline not only in style sheet per class. And my element can have style added by very different css selectors that I can't possibly know.







javascript css css-variables






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 14:50







jcubic

















asked Jan 2 at 10:24









jcubicjcubic

34.4k31128230




34.4k31128230













  • Possible duplicate of Get all CSS properties for a class or id with Javascript/JQuery

    – user6656728
    Jan 2 at 10:26











  • @MumbaiWadala does this consider CSS Custom properties?

    – Temani Afif
    Jan 2 at 10:27











  • do look at the example it will help you

    – user6656728
    Jan 2 at 10:28













  • CSS custom properties != CSS variables

    – connexo
    Jan 2 at 10:36








  • 2





    @MumbaiWadala this is not a duplicate because I don't want to find css for single selector but for single element that can be accessed in very different selectors, that I can't possibly know. I also need to include inline styles.

    – jcubic
    Jan 2 at 10:53





















  • Possible duplicate of Get all CSS properties for a class or id with Javascript/JQuery

    – user6656728
    Jan 2 at 10:26











  • @MumbaiWadala does this consider CSS Custom properties?

    – Temani Afif
    Jan 2 at 10:27











  • do look at the example it will help you

    – user6656728
    Jan 2 at 10:28













  • CSS custom properties != CSS variables

    – connexo
    Jan 2 at 10:36








  • 2





    @MumbaiWadala this is not a duplicate because I don't want to find css for single selector but for single element that can be accessed in very different selectors, that I can't possibly know. I also need to include inline styles.

    – jcubic
    Jan 2 at 10:53



















Possible duplicate of Get all CSS properties for a class or id with Javascript/JQuery

– user6656728
Jan 2 at 10:26





Possible duplicate of Get all CSS properties for a class or id with Javascript/JQuery

– user6656728
Jan 2 at 10:26













@MumbaiWadala does this consider CSS Custom properties?

– Temani Afif
Jan 2 at 10:27





@MumbaiWadala does this consider CSS Custom properties?

– Temani Afif
Jan 2 at 10:27













do look at the example it will help you

– user6656728
Jan 2 at 10:28







do look at the example it will help you

– user6656728
Jan 2 at 10:28















CSS custom properties != CSS variables

– connexo
Jan 2 at 10:36







CSS custom properties != CSS variables

– connexo
Jan 2 at 10:36






2




2





@MumbaiWadala this is not a duplicate because I don't want to find css for single selector but for single element that can be accessed in very different selectors, that I can't possibly know. I also need to include inline styles.

– jcubic
Jan 2 at 10:53







@MumbaiWadala this is not a duplicate because I don't want to find css for single selector but for single element that can be accessed in very different selectors, that I can't possibly know. I also need to include inline styles.

– jcubic
Jan 2 at 10:53














1 Answer
1






active

oldest

votes


















1














Based on this answer https://stackoverflow.com/a/37958301/8620333 I have created a code that rely on getMatchedCSSRules in order to retrieve all the CSS and then extract the CSS custom properties. Since Custom properties are inherited we need to gather the one defined within the element and the one defined on any parent element.






if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[w-]+/g,
ID_RE = /#[w-]+/g,
CLASS_RE = /.[w-]+/g,
ATTR_RE = /[[^]]+]/g,
// :not() pseudo-class does not add to specificity, but its content does as if it was outside it
PSEUDO_CLASSES_RE = /:(?!not)[w-]+((.*))?/g,
PSEUDO_ELEMENTS_RE = /::?(after|before|first-letter|first-line|selection)/g;
// convert an array-like object to array
function toArray(list) {
return .slice.call(list);
}

// handles extraction of `cssRules` as an `Array` from a stylesheet or something that behaves the same
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
// if this sheet is disabled skip it
if ( stylesheet.disabled ) return ;
// if this sheet's media is specified and doesn't match the viewport then skip it
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return ;
// get the style rules of this sheet
return toArray(stylesheet.cssRules);
}

function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}

// calculates the specificity of a given `selector`
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
//TODO: clean the ':not' part since the last ELEMENT_RE will pick it up
while (part = parts.shift(), typeof part == 'string') {
// find all pseudo-elements
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
// and remove them
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
// find all pseudo-classes
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
// and remove them
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
// find all attributes
match = _find(part, ATTR_RE);
score[1] += match;
// and remove them
match && (part = part.replace(ATTR_RE, ''));
// find all IDs
match = _find(part, ID_RE);
score[0] += match;
// and remove them
match && (part = part.replace(ID_RE, ''));
// find all classes
match = _find(part, CLASS_RE);
score[1] += match;
// and remove them
match && (part = part.replace(CLASS_RE, ''));
// find all elements
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}

// returns the heights possible specificity score an element can get from a give rule's selectorText
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}

function sortBySpecificity(element, rules) {
// comparing function that sorts CSSStyleRules according to specificity of their `selectorText`
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}

return rules.sort(compareSpecificity);
}

// Find correct matchesSelector impl
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}

//TODO: not supporting 2nd argument for selecting pseudo elements
//TODO: not supporting 3rd argument for checking author style sheets only
window.getMatchedCSSRules = function (element /*, pseudo, author_only*/) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = ;
// get stylesheets and convert to a regular Array
style_sheets = toArray(window.document.styleSheets);

// assuming the browser hands us stylesheets in order of appearance
// we iterate them from the beginning to follow proper cascade order
while (sheet = style_sheets.shift()) {
// get the style rules of this sheet
rules = getSheetRules(sheet);
// loop the rules in order of appearance
while (rule = rules.shift()) {
// if this is an @import rule
if (rule.styleSheet) {
// insert the imported stylesheet's rules at the beginning of this stylesheet's rules
rules = getSheetRules(rule.styleSheet).concat(rules);
// and skip this rule
continue;
}
// if there's no stylesheet attribute BUT there IS a media attribute it's a media rule
else if (rule.media) {
// insert the contained rules of this media rule to the beginning of this stylesheet's rules
rules = getSheetRules(rule).concat(rules);
// and skip it
continue
}

// check if this element matches this rule's selector
if (matchesSelector(element, rule.selectorText)) {
// push the rule to the results set
result.push(rule);
}
}
}
// sort according to specificity
return sortBySpecificity(element, result);
};
}

var element = document.querySelector(".box");

/*Get element style*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*get inline style*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}

:root {
--b: 20px;
}

.box {
background: red;
height: 100px;
--c: blue;
border: 1px solid var(--c);
}
.element {
--e:30px;
padding:var(--e);
}

<div class="box element" style="color:blue;--d:10ch;border-radius:20px;">
</div>





Here is the relevant part of the code1:



var element = document.querySelector(".box");

/*Get external styles*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*Get inline styles*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}


As you can see, this will print the needed values. You can easily adjust the code to store the values in an array or an Object.



1: This code is not optimized as it may gather non needed CSS in some cases. Will keep editing it.






share|improve this answer


























  • @jcubic did you consider all the code in the snippet? not only the relevant part

    – Temani Afif
    Jan 2 at 12:49











  • Sorry just noticed the snippets, when I run the function in CodePen get this error Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules according to this github.com/Modernizr/Modernizr/issues/2296 it's CORS issue in Chrome. So the only thing that left is node clone.

    – jcubic
    Jan 2 at 12:54











  • Maybe adding try..catch, with warning that there was CORS issue, will make solution better.

    – jcubic
    Jan 2 at 12:57













  • @jcubic I will try to edit in case I found any workarounds. Chrome is doing this on his dev tooles when you check the Computed style tab so there is for sure something that we can do.

    – Temani Afif
    Jan 2 at 12:57











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004635%2fhow-to-list-all-css-variables-names-values-pairs-from-element%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Based on this answer https://stackoverflow.com/a/37958301/8620333 I have created a code that rely on getMatchedCSSRules in order to retrieve all the CSS and then extract the CSS custom properties. Since Custom properties are inherited we need to gather the one defined within the element and the one defined on any parent element.






if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[w-]+/g,
ID_RE = /#[w-]+/g,
CLASS_RE = /.[w-]+/g,
ATTR_RE = /[[^]]+]/g,
// :not() pseudo-class does not add to specificity, but its content does as if it was outside it
PSEUDO_CLASSES_RE = /:(?!not)[w-]+((.*))?/g,
PSEUDO_ELEMENTS_RE = /::?(after|before|first-letter|first-line|selection)/g;
// convert an array-like object to array
function toArray(list) {
return .slice.call(list);
}

// handles extraction of `cssRules` as an `Array` from a stylesheet or something that behaves the same
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
// if this sheet is disabled skip it
if ( stylesheet.disabled ) return ;
// if this sheet's media is specified and doesn't match the viewport then skip it
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return ;
// get the style rules of this sheet
return toArray(stylesheet.cssRules);
}

function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}

// calculates the specificity of a given `selector`
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
//TODO: clean the ':not' part since the last ELEMENT_RE will pick it up
while (part = parts.shift(), typeof part == 'string') {
// find all pseudo-elements
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
// and remove them
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
// find all pseudo-classes
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
// and remove them
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
// find all attributes
match = _find(part, ATTR_RE);
score[1] += match;
// and remove them
match && (part = part.replace(ATTR_RE, ''));
// find all IDs
match = _find(part, ID_RE);
score[0] += match;
// and remove them
match && (part = part.replace(ID_RE, ''));
// find all classes
match = _find(part, CLASS_RE);
score[1] += match;
// and remove them
match && (part = part.replace(CLASS_RE, ''));
// find all elements
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}

// returns the heights possible specificity score an element can get from a give rule's selectorText
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}

function sortBySpecificity(element, rules) {
// comparing function that sorts CSSStyleRules according to specificity of their `selectorText`
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}

return rules.sort(compareSpecificity);
}

// Find correct matchesSelector impl
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}

//TODO: not supporting 2nd argument for selecting pseudo elements
//TODO: not supporting 3rd argument for checking author style sheets only
window.getMatchedCSSRules = function (element /*, pseudo, author_only*/) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = ;
// get stylesheets and convert to a regular Array
style_sheets = toArray(window.document.styleSheets);

// assuming the browser hands us stylesheets in order of appearance
// we iterate them from the beginning to follow proper cascade order
while (sheet = style_sheets.shift()) {
// get the style rules of this sheet
rules = getSheetRules(sheet);
// loop the rules in order of appearance
while (rule = rules.shift()) {
// if this is an @import rule
if (rule.styleSheet) {
// insert the imported stylesheet's rules at the beginning of this stylesheet's rules
rules = getSheetRules(rule.styleSheet).concat(rules);
// and skip this rule
continue;
}
// if there's no stylesheet attribute BUT there IS a media attribute it's a media rule
else if (rule.media) {
// insert the contained rules of this media rule to the beginning of this stylesheet's rules
rules = getSheetRules(rule).concat(rules);
// and skip it
continue
}

// check if this element matches this rule's selector
if (matchesSelector(element, rule.selectorText)) {
// push the rule to the results set
result.push(rule);
}
}
}
// sort according to specificity
return sortBySpecificity(element, result);
};
}

var element = document.querySelector(".box");

/*Get element style*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*get inline style*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}

:root {
--b: 20px;
}

.box {
background: red;
height: 100px;
--c: blue;
border: 1px solid var(--c);
}
.element {
--e:30px;
padding:var(--e);
}

<div class="box element" style="color:blue;--d:10ch;border-radius:20px;">
</div>





Here is the relevant part of the code1:



var element = document.querySelector(".box");

/*Get external styles*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*Get inline styles*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}


As you can see, this will print the needed values. You can easily adjust the code to store the values in an array or an Object.



1: This code is not optimized as it may gather non needed CSS in some cases. Will keep editing it.






share|improve this answer


























  • @jcubic did you consider all the code in the snippet? not only the relevant part

    – Temani Afif
    Jan 2 at 12:49











  • Sorry just noticed the snippets, when I run the function in CodePen get this error Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules according to this github.com/Modernizr/Modernizr/issues/2296 it's CORS issue in Chrome. So the only thing that left is node clone.

    – jcubic
    Jan 2 at 12:54











  • Maybe adding try..catch, with warning that there was CORS issue, will make solution better.

    – jcubic
    Jan 2 at 12:57













  • @jcubic I will try to edit in case I found any workarounds. Chrome is doing this on his dev tooles when you check the Computed style tab so there is for sure something that we can do.

    – Temani Afif
    Jan 2 at 12:57
















1














Based on this answer https://stackoverflow.com/a/37958301/8620333 I have created a code that rely on getMatchedCSSRules in order to retrieve all the CSS and then extract the CSS custom properties. Since Custom properties are inherited we need to gather the one defined within the element and the one defined on any parent element.






if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[w-]+/g,
ID_RE = /#[w-]+/g,
CLASS_RE = /.[w-]+/g,
ATTR_RE = /[[^]]+]/g,
// :not() pseudo-class does not add to specificity, but its content does as if it was outside it
PSEUDO_CLASSES_RE = /:(?!not)[w-]+((.*))?/g,
PSEUDO_ELEMENTS_RE = /::?(after|before|first-letter|first-line|selection)/g;
// convert an array-like object to array
function toArray(list) {
return .slice.call(list);
}

// handles extraction of `cssRules` as an `Array` from a stylesheet or something that behaves the same
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
// if this sheet is disabled skip it
if ( stylesheet.disabled ) return ;
// if this sheet's media is specified and doesn't match the viewport then skip it
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return ;
// get the style rules of this sheet
return toArray(stylesheet.cssRules);
}

function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}

// calculates the specificity of a given `selector`
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
//TODO: clean the ':not' part since the last ELEMENT_RE will pick it up
while (part = parts.shift(), typeof part == 'string') {
// find all pseudo-elements
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
// and remove them
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
// find all pseudo-classes
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
// and remove them
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
// find all attributes
match = _find(part, ATTR_RE);
score[1] += match;
// and remove them
match && (part = part.replace(ATTR_RE, ''));
// find all IDs
match = _find(part, ID_RE);
score[0] += match;
// and remove them
match && (part = part.replace(ID_RE, ''));
// find all classes
match = _find(part, CLASS_RE);
score[1] += match;
// and remove them
match && (part = part.replace(CLASS_RE, ''));
// find all elements
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}

// returns the heights possible specificity score an element can get from a give rule's selectorText
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}

function sortBySpecificity(element, rules) {
// comparing function that sorts CSSStyleRules according to specificity of their `selectorText`
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}

return rules.sort(compareSpecificity);
}

// Find correct matchesSelector impl
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}

//TODO: not supporting 2nd argument for selecting pseudo elements
//TODO: not supporting 3rd argument for checking author style sheets only
window.getMatchedCSSRules = function (element /*, pseudo, author_only*/) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = ;
// get stylesheets and convert to a regular Array
style_sheets = toArray(window.document.styleSheets);

// assuming the browser hands us stylesheets in order of appearance
// we iterate them from the beginning to follow proper cascade order
while (sheet = style_sheets.shift()) {
// get the style rules of this sheet
rules = getSheetRules(sheet);
// loop the rules in order of appearance
while (rule = rules.shift()) {
// if this is an @import rule
if (rule.styleSheet) {
// insert the imported stylesheet's rules at the beginning of this stylesheet's rules
rules = getSheetRules(rule.styleSheet).concat(rules);
// and skip this rule
continue;
}
// if there's no stylesheet attribute BUT there IS a media attribute it's a media rule
else if (rule.media) {
// insert the contained rules of this media rule to the beginning of this stylesheet's rules
rules = getSheetRules(rule).concat(rules);
// and skip it
continue
}

// check if this element matches this rule's selector
if (matchesSelector(element, rule.selectorText)) {
// push the rule to the results set
result.push(rule);
}
}
}
// sort according to specificity
return sortBySpecificity(element, result);
};
}

var element = document.querySelector(".box");

/*Get element style*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*get inline style*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}

:root {
--b: 20px;
}

.box {
background: red;
height: 100px;
--c: blue;
border: 1px solid var(--c);
}
.element {
--e:30px;
padding:var(--e);
}

<div class="box element" style="color:blue;--d:10ch;border-radius:20px;">
</div>





Here is the relevant part of the code1:



var element = document.querySelector(".box");

/*Get external styles*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*Get inline styles*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}


As you can see, this will print the needed values. You can easily adjust the code to store the values in an array or an Object.



1: This code is not optimized as it may gather non needed CSS in some cases. Will keep editing it.






share|improve this answer


























  • @jcubic did you consider all the code in the snippet? not only the relevant part

    – Temani Afif
    Jan 2 at 12:49











  • Sorry just noticed the snippets, when I run the function in CodePen get this error Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules according to this github.com/Modernizr/Modernizr/issues/2296 it's CORS issue in Chrome. So the only thing that left is node clone.

    – jcubic
    Jan 2 at 12:54











  • Maybe adding try..catch, with warning that there was CORS issue, will make solution better.

    – jcubic
    Jan 2 at 12:57













  • @jcubic I will try to edit in case I found any workarounds. Chrome is doing this on his dev tooles when you check the Computed style tab so there is for sure something that we can do.

    – Temani Afif
    Jan 2 at 12:57














1












1








1







Based on this answer https://stackoverflow.com/a/37958301/8620333 I have created a code that rely on getMatchedCSSRules in order to retrieve all the CSS and then extract the CSS custom properties. Since Custom properties are inherited we need to gather the one defined within the element and the one defined on any parent element.






if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[w-]+/g,
ID_RE = /#[w-]+/g,
CLASS_RE = /.[w-]+/g,
ATTR_RE = /[[^]]+]/g,
// :not() pseudo-class does not add to specificity, but its content does as if it was outside it
PSEUDO_CLASSES_RE = /:(?!not)[w-]+((.*))?/g,
PSEUDO_ELEMENTS_RE = /::?(after|before|first-letter|first-line|selection)/g;
// convert an array-like object to array
function toArray(list) {
return .slice.call(list);
}

// handles extraction of `cssRules` as an `Array` from a stylesheet or something that behaves the same
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
// if this sheet is disabled skip it
if ( stylesheet.disabled ) return ;
// if this sheet's media is specified and doesn't match the viewport then skip it
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return ;
// get the style rules of this sheet
return toArray(stylesheet.cssRules);
}

function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}

// calculates the specificity of a given `selector`
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
//TODO: clean the ':not' part since the last ELEMENT_RE will pick it up
while (part = parts.shift(), typeof part == 'string') {
// find all pseudo-elements
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
// and remove them
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
// find all pseudo-classes
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
// and remove them
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
// find all attributes
match = _find(part, ATTR_RE);
score[1] += match;
// and remove them
match && (part = part.replace(ATTR_RE, ''));
// find all IDs
match = _find(part, ID_RE);
score[0] += match;
// and remove them
match && (part = part.replace(ID_RE, ''));
// find all classes
match = _find(part, CLASS_RE);
score[1] += match;
// and remove them
match && (part = part.replace(CLASS_RE, ''));
// find all elements
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}

// returns the heights possible specificity score an element can get from a give rule's selectorText
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}

function sortBySpecificity(element, rules) {
// comparing function that sorts CSSStyleRules according to specificity of their `selectorText`
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}

return rules.sort(compareSpecificity);
}

// Find correct matchesSelector impl
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}

//TODO: not supporting 2nd argument for selecting pseudo elements
//TODO: not supporting 3rd argument for checking author style sheets only
window.getMatchedCSSRules = function (element /*, pseudo, author_only*/) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = ;
// get stylesheets and convert to a regular Array
style_sheets = toArray(window.document.styleSheets);

// assuming the browser hands us stylesheets in order of appearance
// we iterate them from the beginning to follow proper cascade order
while (sheet = style_sheets.shift()) {
// get the style rules of this sheet
rules = getSheetRules(sheet);
// loop the rules in order of appearance
while (rule = rules.shift()) {
// if this is an @import rule
if (rule.styleSheet) {
// insert the imported stylesheet's rules at the beginning of this stylesheet's rules
rules = getSheetRules(rule.styleSheet).concat(rules);
// and skip this rule
continue;
}
// if there's no stylesheet attribute BUT there IS a media attribute it's a media rule
else if (rule.media) {
// insert the contained rules of this media rule to the beginning of this stylesheet's rules
rules = getSheetRules(rule).concat(rules);
// and skip it
continue
}

// check if this element matches this rule's selector
if (matchesSelector(element, rule.selectorText)) {
// push the rule to the results set
result.push(rule);
}
}
}
// sort according to specificity
return sortBySpecificity(element, result);
};
}

var element = document.querySelector(".box");

/*Get element style*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*get inline style*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}

:root {
--b: 20px;
}

.box {
background: red;
height: 100px;
--c: blue;
border: 1px solid var(--c);
}
.element {
--e:30px;
padding:var(--e);
}

<div class="box element" style="color:blue;--d:10ch;border-radius:20px;">
</div>





Here is the relevant part of the code1:



var element = document.querySelector(".box");

/*Get external styles*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*Get inline styles*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}


As you can see, this will print the needed values. You can easily adjust the code to store the values in an array or an Object.



1: This code is not optimized as it may gather non needed CSS in some cases. Will keep editing it.






share|improve this answer















Based on this answer https://stackoverflow.com/a/37958301/8620333 I have created a code that rely on getMatchedCSSRules in order to retrieve all the CSS and then extract the CSS custom properties. Since Custom properties are inherited we need to gather the one defined within the element and the one defined on any parent element.






if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[w-]+/g,
ID_RE = /#[w-]+/g,
CLASS_RE = /.[w-]+/g,
ATTR_RE = /[[^]]+]/g,
// :not() pseudo-class does not add to specificity, but its content does as if it was outside it
PSEUDO_CLASSES_RE = /:(?!not)[w-]+((.*))?/g,
PSEUDO_ELEMENTS_RE = /::?(after|before|first-letter|first-line|selection)/g;
// convert an array-like object to array
function toArray(list) {
return .slice.call(list);
}

// handles extraction of `cssRules` as an `Array` from a stylesheet or something that behaves the same
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
// if this sheet is disabled skip it
if ( stylesheet.disabled ) return ;
// if this sheet's media is specified and doesn't match the viewport then skip it
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return ;
// get the style rules of this sheet
return toArray(stylesheet.cssRules);
}

function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}

// calculates the specificity of a given `selector`
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
//TODO: clean the ':not' part since the last ELEMENT_RE will pick it up
while (part = parts.shift(), typeof part == 'string') {
// find all pseudo-elements
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
// and remove them
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
// find all pseudo-classes
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
// and remove them
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
// find all attributes
match = _find(part, ATTR_RE);
score[1] += match;
// and remove them
match && (part = part.replace(ATTR_RE, ''));
// find all IDs
match = _find(part, ID_RE);
score[0] += match;
// and remove them
match && (part = part.replace(ID_RE, ''));
// find all classes
match = _find(part, CLASS_RE);
score[1] += match;
// and remove them
match && (part = part.replace(CLASS_RE, ''));
// find all elements
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}

// returns the heights possible specificity score an element can get from a give rule's selectorText
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}

function sortBySpecificity(element, rules) {
// comparing function that sorts CSSStyleRules according to specificity of their `selectorText`
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}

return rules.sort(compareSpecificity);
}

// Find correct matchesSelector impl
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}

//TODO: not supporting 2nd argument for selecting pseudo elements
//TODO: not supporting 3rd argument for checking author style sheets only
window.getMatchedCSSRules = function (element /*, pseudo, author_only*/) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = ;
// get stylesheets and convert to a regular Array
style_sheets = toArray(window.document.styleSheets);

// assuming the browser hands us stylesheets in order of appearance
// we iterate them from the beginning to follow proper cascade order
while (sheet = style_sheets.shift()) {
// get the style rules of this sheet
rules = getSheetRules(sheet);
// loop the rules in order of appearance
while (rule = rules.shift()) {
// if this is an @import rule
if (rule.styleSheet) {
// insert the imported stylesheet's rules at the beginning of this stylesheet's rules
rules = getSheetRules(rule.styleSheet).concat(rules);
// and skip this rule
continue;
}
// if there's no stylesheet attribute BUT there IS a media attribute it's a media rule
else if (rule.media) {
// insert the contained rules of this media rule to the beginning of this stylesheet's rules
rules = getSheetRules(rule).concat(rules);
// and skip it
continue
}

// check if this element matches this rule's selector
if (matchesSelector(element, rule.selectorText)) {
// push the rule to the results set
result.push(rule);
}
}
}
// sort according to specificity
return sortBySpecificity(element, result);
};
}

var element = document.querySelector(".box");

/*Get element style*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*get inline style*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}

:root {
--b: 20px;
}

.box {
background: red;
height: 100px;
--c: blue;
border: 1px solid var(--c);
}
.element {
--e:30px;
padding:var(--e);
}

<div class="box element" style="color:blue;--d:10ch;border-radius:20px;">
</div>





Here is the relevant part of the code1:



var element = document.querySelector(".box");

/*Get external styles*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*Get inline styles*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}


As you can see, this will print the needed values. You can easily adjust the code to store the values in an array or an Object.



1: This code is not optimized as it may gather non needed CSS in some cases. Will keep editing it.






if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[w-]+/g,
ID_RE = /#[w-]+/g,
CLASS_RE = /.[w-]+/g,
ATTR_RE = /[[^]]+]/g,
// :not() pseudo-class does not add to specificity, but its content does as if it was outside it
PSEUDO_CLASSES_RE = /:(?!not)[w-]+((.*))?/g,
PSEUDO_ELEMENTS_RE = /::?(after|before|first-letter|first-line|selection)/g;
// convert an array-like object to array
function toArray(list) {
return .slice.call(list);
}

// handles extraction of `cssRules` as an `Array` from a stylesheet or something that behaves the same
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
// if this sheet is disabled skip it
if ( stylesheet.disabled ) return ;
// if this sheet's media is specified and doesn't match the viewport then skip it
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return ;
// get the style rules of this sheet
return toArray(stylesheet.cssRules);
}

function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}

// calculates the specificity of a given `selector`
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
//TODO: clean the ':not' part since the last ELEMENT_RE will pick it up
while (part = parts.shift(), typeof part == 'string') {
// find all pseudo-elements
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
// and remove them
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
// find all pseudo-classes
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
// and remove them
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
// find all attributes
match = _find(part, ATTR_RE);
score[1] += match;
// and remove them
match && (part = part.replace(ATTR_RE, ''));
// find all IDs
match = _find(part, ID_RE);
score[0] += match;
// and remove them
match && (part = part.replace(ID_RE, ''));
// find all classes
match = _find(part, CLASS_RE);
score[1] += match;
// and remove them
match && (part = part.replace(CLASS_RE, ''));
// find all elements
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}

// returns the heights possible specificity score an element can get from a give rule's selectorText
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}

function sortBySpecificity(element, rules) {
// comparing function that sorts CSSStyleRules according to specificity of their `selectorText`
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}

return rules.sort(compareSpecificity);
}

// Find correct matchesSelector impl
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}

//TODO: not supporting 2nd argument for selecting pseudo elements
//TODO: not supporting 3rd argument for checking author style sheets only
window.getMatchedCSSRules = function (element /*, pseudo, author_only*/) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = ;
// get stylesheets and convert to a regular Array
style_sheets = toArray(window.document.styleSheets);

// assuming the browser hands us stylesheets in order of appearance
// we iterate them from the beginning to follow proper cascade order
while (sheet = style_sheets.shift()) {
// get the style rules of this sheet
rules = getSheetRules(sheet);
// loop the rules in order of appearance
while (rule = rules.shift()) {
// if this is an @import rule
if (rule.styleSheet) {
// insert the imported stylesheet's rules at the beginning of this stylesheet's rules
rules = getSheetRules(rule.styleSheet).concat(rules);
// and skip this rule
continue;
}
// if there's no stylesheet attribute BUT there IS a media attribute it's a media rule
else if (rule.media) {
// insert the contained rules of this media rule to the beginning of this stylesheet's rules
rules = getSheetRules(rule).concat(rules);
// and skip it
continue
}

// check if this element matches this rule's selector
if (matchesSelector(element, rule.selectorText)) {
// push the rule to the results set
result.push(rule);
}
}
}
// sort according to specificity
return sortBySpecificity(element, result);
};
}

var element = document.querySelector(".box");

/*Get element style*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*get inline style*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}

:root {
--b: 20px;
}

.box {
background: red;
height: 100px;
--c: blue;
border: 1px solid var(--c);
}
.element {
--e:30px;
padding:var(--e);
}

<div class="box element" style="color:blue;--d:10ch;border-radius:20px;">
</div>





if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[w-]+/g,
ID_RE = /#[w-]+/g,
CLASS_RE = /.[w-]+/g,
ATTR_RE = /[[^]]+]/g,
// :not() pseudo-class does not add to specificity, but its content does as if it was outside it
PSEUDO_CLASSES_RE = /:(?!not)[w-]+((.*))?/g,
PSEUDO_ELEMENTS_RE = /::?(after|before|first-letter|first-line|selection)/g;
// convert an array-like object to array
function toArray(list) {
return .slice.call(list);
}

// handles extraction of `cssRules` as an `Array` from a stylesheet or something that behaves the same
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
// if this sheet is disabled skip it
if ( stylesheet.disabled ) return ;
// if this sheet's media is specified and doesn't match the viewport then skip it
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return ;
// get the style rules of this sheet
return toArray(stylesheet.cssRules);
}

function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}

// calculates the specificity of a given `selector`
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
//TODO: clean the ':not' part since the last ELEMENT_RE will pick it up
while (part = parts.shift(), typeof part == 'string') {
// find all pseudo-elements
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
// and remove them
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
// find all pseudo-classes
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
// and remove them
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
// find all attributes
match = _find(part, ATTR_RE);
score[1] += match;
// and remove them
match && (part = part.replace(ATTR_RE, ''));
// find all IDs
match = _find(part, ID_RE);
score[0] += match;
// and remove them
match && (part = part.replace(ID_RE, ''));
// find all classes
match = _find(part, CLASS_RE);
score[1] += match;
// and remove them
match && (part = part.replace(CLASS_RE, ''));
// find all elements
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}

// returns the heights possible specificity score an element can get from a give rule's selectorText
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}

function sortBySpecificity(element, rules) {
// comparing function that sorts CSSStyleRules according to specificity of their `selectorText`
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}

return rules.sort(compareSpecificity);
}

// Find correct matchesSelector impl
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}

//TODO: not supporting 2nd argument for selecting pseudo elements
//TODO: not supporting 3rd argument for checking author style sheets only
window.getMatchedCSSRules = function (element /*, pseudo, author_only*/) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = ;
// get stylesheets and convert to a regular Array
style_sheets = toArray(window.document.styleSheets);

// assuming the browser hands us stylesheets in order of appearance
// we iterate them from the beginning to follow proper cascade order
while (sheet = style_sheets.shift()) {
// get the style rules of this sheet
rules = getSheetRules(sheet);
// loop the rules in order of appearance
while (rule = rules.shift()) {
// if this is an @import rule
if (rule.styleSheet) {
// insert the imported stylesheet's rules at the beginning of this stylesheet's rules
rules = getSheetRules(rule.styleSheet).concat(rules);
// and skip this rule
continue;
}
// if there's no stylesheet attribute BUT there IS a media attribute it's a media rule
else if (rule.media) {
// insert the contained rules of this media rule to the beginning of this stylesheet's rules
rules = getSheetRules(rule).concat(rules);
// and skip it
continue
}

// check if this element matches this rule's selector
if (matchesSelector(element, rule.selectorText)) {
// push the rule to the results set
result.push(rule);
}
}
}
// sort according to specificity
return sortBySpecificity(element, result);
};
}

var element = document.querySelector(".box");

/*Get element style*/
var obj = window.getMatchedCSSRules(element)[0];
var all_css = obj.parentStyleSheet.cssRules;
for(var i=0;i < all_css.length;i++) {
var rules = all_css[i].cssText.substring(all_css[i].cssText.indexOf("{")+1,all_css[i].cssText.indexOf("}"));
rules = rules.split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}
}
/*get inline style*/
var rules = element.getAttribute("style").trim().split(";");
for(var j=0;j<rules.length;j++) {
if(rules[j].trim().startsWith("--")) {
console.log(rules[j]);
}
}

:root {
--b: 20px;
}

.box {
background: red;
height: 100px;
--c: blue;
border: 1px solid var(--c);
}
.element {
--e:30px;
padding:var(--e);
}

<div class="box element" style="color:blue;--d:10ch;border-radius:20px;">
</div>






share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 2 at 12:54

























answered Jan 2 at 12:13









Temani AfifTemani Afif

80.2k94692




80.2k94692













  • @jcubic did you consider all the code in the snippet? not only the relevant part

    – Temani Afif
    Jan 2 at 12:49











  • Sorry just noticed the snippets, when I run the function in CodePen get this error Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules according to this github.com/Modernizr/Modernizr/issues/2296 it's CORS issue in Chrome. So the only thing that left is node clone.

    – jcubic
    Jan 2 at 12:54











  • Maybe adding try..catch, with warning that there was CORS issue, will make solution better.

    – jcubic
    Jan 2 at 12:57













  • @jcubic I will try to edit in case I found any workarounds. Chrome is doing this on his dev tooles when you check the Computed style tab so there is for sure something that we can do.

    – Temani Afif
    Jan 2 at 12:57



















  • @jcubic did you consider all the code in the snippet? not only the relevant part

    – Temani Afif
    Jan 2 at 12:49











  • Sorry just noticed the snippets, when I run the function in CodePen get this error Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules according to this github.com/Modernizr/Modernizr/issues/2296 it's CORS issue in Chrome. So the only thing that left is node clone.

    – jcubic
    Jan 2 at 12:54











  • Maybe adding try..catch, with warning that there was CORS issue, will make solution better.

    – jcubic
    Jan 2 at 12:57













  • @jcubic I will try to edit in case I found any workarounds. Chrome is doing this on his dev tooles when you check the Computed style tab so there is for sure something that we can do.

    – Temani Afif
    Jan 2 at 12:57

















@jcubic did you consider all the code in the snippet? not only the relevant part

– Temani Afif
Jan 2 at 12:49





@jcubic did you consider all the code in the snippet? not only the relevant part

– Temani Afif
Jan 2 at 12:49













Sorry just noticed the snippets, when I run the function in CodePen get this error Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules according to this github.com/Modernizr/Modernizr/issues/2296 it's CORS issue in Chrome. So the only thing that left is node clone.

– jcubic
Jan 2 at 12:54





Sorry just noticed the snippets, when I run the function in CodePen get this error Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules according to this github.com/Modernizr/Modernizr/issues/2296 it's CORS issue in Chrome. So the only thing that left is node clone.

– jcubic
Jan 2 at 12:54













Maybe adding try..catch, with warning that there was CORS issue, will make solution better.

– jcubic
Jan 2 at 12:57







Maybe adding try..catch, with warning that there was CORS issue, will make solution better.

– jcubic
Jan 2 at 12:57















@jcubic I will try to edit in case I found any workarounds. Chrome is doing this on his dev tooles when you check the Computed style tab so there is for sure something that we can do.

– Temani Afif
Jan 2 at 12:57





@jcubic I will try to edit in case I found any workarounds. Chrome is doing this on his dev tooles when you check the Computed style tab so there is for sure something that we can do.

– Temani Afif
Jan 2 at 12:57




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004635%2fhow-to-list-all-css-variables-names-values-pairs-from-element%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

A Topological Invariant for $pi_3(U(n))$