14

I'm trying to find a good way to collect the names of classes defined in the stylesheets included with a given document. I know about document.StyleSheetList but it doesn't seem like it'd be easy to parse. What I'm looking for is something like, for a stylesheet document such as:

.my_class { 
    background: #fff000; 
}
.second_class {
    color: #000000;
}

I could extract an array like ["my_class", "second_class"]. This obviously assumes the favorable scenario of a fully loaded dom and stylesheets.

I've been looking everywhere for a good way to do something like this and so far, have made little progress. Does anyone have any idea about how to pull this off? Thanks!

2
  • Are you looking for something that will work in all browsers, or is this just for development? Commented Jan 10, 2011 at 21:45
  • By "CSS classes" do you mean "All selectors regardless of any mention of an HTML class", "Selectors that include class selectors", "The bits of selectors that are class selectors" or something else? Commented Jan 10, 2011 at 21:49

5 Answers 5

25

This will show all rules defined in the stylesheets.

var allRules = [];
var sSheetList = document.styleSheets;
for (var sSheet = 0; sSheet < sSheetList.length; sSheet++)
{
    var ruleList = document.styleSheets[sSheet].cssRules;
    for (var rule = 0; rule < ruleList.length; rule ++)
    {
       allRules.push( ruleList[rule].selectorText );
    }
}

The thing, though, is that it includes all rules regardless of being class or tag or id or whatever..

You will need to explain in more detail what you want to happen for non class rules (or combined rules)

Sign up to request clarification or add additional context in comments.

4 Comments

I actually implemented something quite similar in the end (available here: gist.github.com/774111).
@Fred, just glanced over your code in github.. For the defined classes you need to account for .class1.class2, tag.class and #id.class cases.. For the unused be careful because some classes might be used from javascript (events etc..) so they will not be in the DOM when you check the DOM (if that case is important to you..)
Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules
@Berto99 yes, those would be css files on a different domain. Browsers do not grant access to those through this api.
4

You were on track with document.styleSheets (https://developer.mozilla.org/en/DOM/document.styleSheets)

https://developer.mozilla.org/en/DOM/stylesheet.cssRules

Here's a quick and dirty method to output all class selectorTexts to the console in Firefox + Firebug.

    var currentSheet = null;
    var i = 0;
    var j = 0;
    var ruleKey = null;

    //loop through styleSheet(s)
    for(i = 0; i<document.styleSheets.length; i++){
        currentSheet = document.styleSheets[i];

        ///loop through css Rules
        for(j = 0; j< currentSheet.cssRules.length; j++){

            //log selectorText to the console (what you're looking for)
            console.log(currentSheet.cssRules[j].selectorText);

            //uncomment to output all of the cssRule contents
            /*for(var ruleKey in currentSheet.cssRules[j] ){
                 console.log(ruleKey +': ' + currentSheet.cssRules[j][ruleKey ]);
            }*/
        }
    }

1 Comment

When I do this I get: SecurityError: The operation is insecure. for(j = 0; j< currentSheet.cssRules.length; j++){
3

This is probably not something you really want to be doing except as part of a refactoring process, but here is a function that should do what you want:

function getClasses() {
    var classes = {};
    // Extract the stylesheets
    return Array.prototype.concat.apply([], Array.prototype.slice.call(document.styleSheets)
        .map(function (sheet) {
            if(null == sheet || null == sheet.cssRules) return;
            // Extract the rules
            return Array.prototype.concat.apply([], Array.prototype.slice.call(sheet.cssRules)
                .map(function(rule) {
                    // Grab a list of classNames from each selector, making sure a selectorText exists (will throw errors otherwise on Media Queries)
                    return (rule.selectorText && rule.selectorText.match(/\.[\w\-]+/g)) || [];
                })
            );
        })
    ).filter(function(name) {
        // Reduce the list of classNames to a unique list
        return !classes[name] && (classes[name] = true);
    });
}

4 Comments

Is there an improvement that will allow this to bypass a NULL sheet.cssRules property (such as what is encountered when the style sheet is being accessed directly via the file system, rather than served up via a web server?
NVM, I just figured it out. Add the following line right above '// Extract the rules':
if(null == sheet || null == sheet.cssRules) return;
When you have media query rules, code answer would error out, so added safeguard to prevent that (the rule will have a conditionText but no selectorText)
0

What about

.something .other_something?

Do you want a pool of classNames that exist? Or a pool of selectors?

Anyway, have you tried iterating through document.styleSheets[i].cssRules? It gives you the selector text. Parsing that with some regexp kungfu should be easier...

Do you need it to be crossbrowser?

1 Comment

I actually did use document.styleSheets[].cssRules in my implementation, but kinda assumed there'd be some other way (I actually mistakenly thought jQuery included this functionality - I might as well contribute it now that I went through it, though).
-2

You can accompish this with jQuery. Example would be

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script>
  $(document).ready(function(){
      var allobjects = $("*")
  });
</script>

Check out the jQuery website: http://api.jquery.com/all-selector/

4 Comments

This will grab all the HTML elements in a document. It won't say anything about the stylesheet.
I very much like this answer. Not sure why the down-vote. You can pop all document objects into an array and read their classes... The OP stated classes defined in the stylesheets included with a given document so you need to first get the elements to decide which classes are used in the document.
Oh I see the confusion. OP is trying to read the styles in all included stylesheets, not the classes in all document objects. Vaguely worded.
My bad with the wording - I do want the selectors defined in stylesheets included in/or linked to from the document. I ended up going with traversing the document.styleSheets array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.