0

ATTENTION: This is not to find the rules of a specific element/node, this is to find if a combination of rules can be applied to any element.

I want to know if it's possible to determine with javascript if a combination of classes was defined in CSS.

For example, I want to know if ".some_class .small{some style}" combination was defined in CSS.

No JQuery please.

Marcio Oliveira
  • 791
  • 1
  • 5
  • 18
  • There are plenty of questions on stackoverflow about reading CSS using JavaScript. You just need to loop over the selectors and pattern match them against your rules. – Quentin Oct 13 '14 at 12:50
  • Can you please explain what your issue is? and why you need to check on something that is under your control like css class? – Dalorzo Oct 13 '14 at 12:51
  • Why no jquery? It's literally just `$(".some_class.small").length`. – C Bauer Oct 13 '14 at 13:05
  • @CBauer He's not asking to find the elements that match the selector, he's asking to find the CSS rules that match it--different thing. –  Oct 13 '14 at 14:03
  • So he's trying to write a parser that checks the other developer's commits for CSS intersections? I think he just wrote the question poorly in that case. – C Bauer Oct 13 '14 at 14:17
  • @CBauer Well it doesn't need to be a parser if there is already a function provided by Javascript. If there is not, then I'm looking for a parser – Marcio Oliveira Oct 13 '14 at 14:21
  • Well it's not a javascript function if you're looking for what @torazaburo said you were. Javascript doesn't search files on your hard-drive, it's a scripting language for html. – C Bauer Oct 13 '14 at 14:23
  • @CBauer I don't want JQuery because I need my app as light as possible. – Marcio Oliveira Oct 13 '14 at 14:23
  • @MarcioOliveira Do you want to find all elements that have both .some_class and .small, or are you looking to validate whether or not there is a css style that is hitting elements that have both classes? – C Bauer Oct 13 '14 at 14:28
  • @CBauer I want to know if a certain rule has been defined in css and can be applied in some element, some people have misunderstood it. – Marcio Oliveira Oct 13 '14 at 14:38

2 Answers2

2

In fact you can only do this using native JS. jQuery does not support methods to deal with CSS rules traversing. Firstly you have to loop through all the document.styleSheets, in each sheet, you have to loop through all the sheet.cssRules. Each CssRule has a property called selectorText, you can get this and compare against your rule text. However you need to care about the order of identifiers in the selector path here. Here is the demo code:

var rulesChecker = {   
  compactRuleText: function(text) {
                   return text.replace(/[.#][^ +~>]+/g,
                                  function(m){
                                      return m.split(/([.#][^.#]+)/).sort().join('');
                                  })
                              .replace(/(\s*?[>+~]\s*|\s+?(?=\s))/g, function(m){
                                       return m.trim();
                   });
  },
  ruleExistence : [],
  init : function(){
     var sheets = document.styleSheets;
     for(var i = 0; i < sheets.length; i++){
       var rules = sheets[i].cssRules || sheets[i].rules;    
       for(var j = 0; j < rules.length; j++){        
         var a = this.compactRuleText(rules[j].selectorText);
         this.ruleExistence[a] = true;
       }
     }
  },
  ruleExists : function(ruleText) {
     var key = this.compactRuleText(ruleText);
     return (key in this.ruleExistence);
  }
};

rulesChecker.init();
//your rule text, note about the extra spaces and how close the identifiers are ...
//this in fact should match the rule in the CSS code (which is normally written)
var ruleText = ".f+.a.b#e >          .d        .k";
//ruleText = ".c";
alert(rulesChecker.ruleExists(ruleText));

Demo.

King King
  • 61,710
  • 16
  • 105
  • 130
  • I've realized that this check works only for ***non-nested*** rules (an example of nested rules is like this `.a.b:not(.f.g:not(.k.j))`. Dealing with nested rules like this is not easy (but solvable), you need more research on this. Also when it comes to nested rules like that, we cannot solve it using just RegExp. – King King Oct 13 '14 at 17:31
0

If you have such an element in your document:

elt = document.querySelector('.some_class .small');

Then check the rules which applied with

rules = window.getMatchedCSSRules(elt)

However, I think support for getMatchedCSSRules is spotty, and it's not a standard.

See Is it possible to find CSS rules from an HTML node via JavaScript?, copy CSS styles that apply to an element, Is it possible to find CSS rules from an HTML node via JavaScript?, Javascript - How to get all matching classes and selector from css files for an element, Find all CSS rules that apply to an element, etc.

If you really want to find just the definitions for a particular selector, rather than the rules that apply to a particular element, you'll have to scan the stylsheets, as a commenter mentioned. However, selectors can be written in multiple ways, so it's not easy. For instance, #foo.bar and .bar#foo are equivalent.

Community
  • 1
  • 1