Is there a way to determine whether or not a CSS class exists using JavaScript?
-
2What do you mean by a class exists? That there is at least one element with that class or that there is at least one CSS rule that is applied on elements with that class?Gumbo– Gumbo2009-06-11 20:53:18 +00:00Commented Jun 11, 2009 at 20:53
-
3Sorry, I mean... Does the class definition exist in the browser's memory? In other words, has the class been defined internally or in a loaded stylesheet?gidmanma– gidmanma2009-06-11 20:57:10 +00:00Commented Jun 11, 2009 at 20:57
-
1hey I know it's an old question but did you find a code to solve this?I 've been trying for hours with no luck.ThankscssGEEK– cssGEEK2016-06-22 22:13:36 +00:00Commented Jun 22, 2016 at 22:13
-
I believe I ended up writing something myself using the accepted answer. It's been a long time though. I haven't had access to that code base in years. Sorry.gidmanma– gidmanma2016-06-23 22:48:49 +00:00Commented Jun 23, 2016 at 22:48
-
1Solutions that loops stylesheets don't work well in Chrome and Firefox, which have same-origin check. The code is unable to read a stylesheet from another domain!user746461– user7464612016-08-22 23:27:02 +00:00Commented Aug 22, 2016 at 23:27
12 Answers
This should be possible to do using the document.styleSheets[].rules[].selectorText and document.styleSheets[].imports[].rules[].selectorText properties. Refer to MDN documentation.
9 Comments
function getAllSelectors() {
var ret = [];
for(var i = 0; i < document.styleSheets.length; i++) {
var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
for(var x in rules) {
if(typeof rules[x].selectorText == 'string') ret.push(rules[x].selectorText);
}
}
return ret;
}
function selectorExists(selector) {
var selectors = getAllSelectors();
for(var i = 0; i < selectors.length; i++) {
if(selectors[i] == selector) return true;
}
return false;
}
4 Comments
Based on the answer, I created a javascript function for searching for a CSS class in the browser's memory -
var searchForCss = function (searchClassName) {
for (let i = 0; i < document.styleSheets.length; i++) {
let styleSheet = document.styleSheets[i];
try {
for (let j = 0; j < styleSheet.cssRules.length; j++) {
let rule = styleSheet.cssRules[j];
// console.log(rule.selectorText)
if (rule.selectorText && rule.selectorText.includes(searchClassName)) {
console.log('found - ', rule.selectorText, ' ', i, '-', j);
}
}
if (styleSheet.imports) {
for (let k = 0; k < styleSheet.imports.length; k++) {
let imp = styleSheet.imports[k];
for (let l = 0; l < imp.cssRules.length; l++) {
let rule = imp.cssRules[l];
if (
rule.selectorText &&
rule.selectorText.includes(searchClassName)
) {
console.log('found - ',rule.selectorText,' ',i,'-',k,'-',l);
}
}
}
}
} catch (err) {}
}
};
searchForCss('my-class-name');
This will print a line for each occurrence of the class name in any of the rules in any of the stylesheets.
1 Comment
Here is my solution to this. I'm essentially just looping through document.styleSheets[].rules[].selectorText as @helen suggested.
/**
* This function searches for the existence of a specified CSS selector in a given stylesheet.
*
* @param (string) styleSheetName - This is the name of the stylesheet you'd like to search
* @param (string) selector - This is the name of the selector you'd like to find
* @return (bool) - Returns true if the selector is found, false if it's not found
* @example - console.log(selectorInStyleSheet ('myStyleSheet.css', '.myClass'));
*/
function selectorInStyleSheet(styleSheetName, selector) {
/*
* Get the index of 'styleSheetName' from the document.styleSheets object
*/
for (var i = 0; i < document.styleSheets.length; i++) {
var thisStyleSheet = document.styleSheets[i].href ? document.styleSheets[i].href.replace(/^.*[\\\/]/, '') : '';
if (thisStyleSheet == styleSheetName) { var idx = i; break; }
}
if (!idx) return false; // We can't find the specified stylesheet
/*
* Check the stylesheet for the specified selector
*/
var styleSheet = document.styleSheets[idx];
var cssRules = styleSheet.rules ? styleSheet.rules : styleSheet.cssRules;
for (var i = 0; i < cssRules.length; ++i) {
if(cssRules[i].selectorText == selector) return true;
}
return false;
}
This function offers a speed improvement over other solutions in that we are only searching the stylesheet passed to the function. The other solutions loop through all the stylesheets which is in many cases unnecessary.
5 Comments
/* You can loop through every stylesheet currently loaded and return an array of all the defined rules for any selector text you specify, from tag names to class names or identifiers.
Don't include the '#' or '.' prefix for an id or class name.
Safari used to skip disabled stylesheets, and there may be other gotchas out there, but reading the rules generally works better across browsers than writing new ones. */
function getDefinedCss(s){
if(!document.styleSheets) return '';
if(typeof s== 'string') s= RegExp('\\b'+s+'\\b','i'); // IE capitalizes html selectors
var A, S, DS= document.styleSheets, n= DS.length, SA= [];
while(n){
S= DS[--n];
A= (S.rules)? S.rules: S.cssRules;
for(var i= 0, L= A.length; i<L; i++){
tem= A[i].selectorText? [A[i].selectorText, A[i].style.cssText]: [A[i]+''];
if(s.test(tem[0])) SA[SA.length]= tem;
}
}
return SA.join('\n\n');
}
getDefinedCss('p')//substitute a classname or id if you like
the latest item in the cascade is listed first.
1 Comment
Firefox is now halting with CORS errors with previous answers, even when viewing about:blank, so this one has added a try...catch block, with the option to showErrors in a way that does not block further execution.
It would look rather hackish, but if you trust your stylesheets and know what to expect, you could also use rules[j].cssText instead of rules[j].selectorText, to search for arbitrary strings using regex.
// A function to find any CSS rule, not just classes.
function hasCSSRule(rule, showErrors = false) {
const sheets = document.styleSheets;
for (let i = 0; i < sheets.length; i++) {
try {
const rules = sheets[i].cssRules || sheets[i].rules;
for (let j = 0; j < rules.length; j++) {
if (rules[j].selectorText === rule) {
return true;
}
}
} catch (e) {
if (showErrors) { // CORS errors in FireFox
console.error(`Error accessing CSS rules: ${e}`);
}
}
}
return false;
}
hasCSSRule(".nope"); // false
Note that we are looking for if a CSS class rule exists, not whether or not an element exists (which could have easily been found with document.querySelector()).
Rationale. It can be handy for a module or framework to load a default style if not already defined.
3 Comments
ul.my-class li existing if you only pass it .my-class?indexOf() on rules[j].cssText instead of .selectorText (but you could receive false positives if your text search isn't specific enough, so it wouldn't make a good answer.)Building on Helen's answer, I came up with this:
//**************************************************************************
//** hasStyleRule
//**************************************************************************
/** Returns true if there is a style rule defined for a given selector.
* @param selector CSS selector (e.g. ".deleteIcon", "h2", "#mid")
*/
var hasStyleRule = function(selector) {
var hasRule = function(selector, rules){
if (!rules) return false;
for (var i=0; i<rules.length; i++) {
var rule = rules[i];
if (rule.selectorText){
var arr = rule.selectorText.split(',');
for (var j=0; j<arr.length; j++){
if (arr[j].indexOf(selector) !== -1){
var txt = trim(arr[j]);
if (txt===selector){
return true;
}
else{
var colIdx = txt.indexOf(":");
if (colIdx !== -1){
txt = trim(txt.substring(0, colIdx));
if (txt===selector){
return true;
}
}
}
}
}
}
}
return false;
};
var trim = function(str){
return str.replace(/^\s*/, "").replace(/\s*$/, "");
};
for (var i=0; i<document.styleSheets.length; i++){
var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
if (hasRule(selector, rules)){
return true;
}
var imports = document.styleSheets[i].imports;
if (imports){
for (var j=0; j<imports.length; j++){
rules = imports[j].rules || imports[j].cssRules;
if (hasRule(selector, rules)) return true;
}
}
}
return false;
};
1 Comment
querySelectorAll()- Document contains Element with class
my-class:const isExists = !!document.querySelector('.my-class') // boolean - Existing Element has class
my-class:const el = document.querySelector(...) const isExists = !!el?.classList.contains('my-class') // boolean
References: querySelector() • classList • contains() • ?. chaining • !! logical not
5 Comments
You could check and see if an object of the style your are looking for already exists. If it does then the css class must exist because an object is using it. For example if you wanted to make sure that distinctly named svg objects each have their own style:
function getClassName(name) {
//Are there any elements which use a style named 'name' ?
if (document.getElementsByClassName(name).length === 0){
//There are none yest, let's make a new style and add it
var style = document.createElement('style');
style.type = 'text/css';
//Where you might provide your own hash function or rnd color
style.innerHTML = '.'+name+' { fill: #' + getHashColor(name) + '; background: #F495A3; }';
//Add the style to the document
document.getElementsByTagName('head')[0].appendChild(style);
}
return name;
}
Note that this is NOT a good approach if you are looking for a style which isn't necessarily used in your document.
1 Comment
querySelectorAll()if ($(".class-name").length > 0) {
}
That is a nice way to check the class in HTML by using javascript
2 Comments
querySelectorAll()Oneliner:
[].slice.call(document.styleSheets)
.reduce( (prev, styleSheet) => [].slice.call(styleSheet.cssRules))
.reduce( (prev, cssRule) => prev + cssRule.cssText)
.includes(".someClass")
1 Comment
[].slice.call( document.styleSheets ) .reduce((last, currentStyleSheet) => [] .slice .call( currentStyleSheet.cssRules ) ) .reduce((last, currentCssRule) => last + currentCssRule.cssText ) .includes(".name") in firefox gives error SecurityError: The operation is insecure.function getAllSelectors() {
var ret = {};
for(var i=0;i<document.styleSheets.length;i++){
try {
var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
for(var x in rules) {
if(typeof rules[x].selectorText === 'string'){
if(ret[rules[x].selectorText] === undefined){
ret[rules[x].selectorText] = rules[x].style.cssText;
}
else {
ret[rules[x].selectorText] = ret[rules[x].selectorText] + ' ' + rules[x].style.cssText;
}
}
}
}
catch(error){
console.log(document.styleSheets[i]);
}
}
return ret;
}
function selectorExists(selector) {
var selectors = getAllSelectors();
if(selectors[selector] !== undefined){
return true;
}
return false;
}
// var allSelectors = getAllSelectors();
3 Comments
document.classes.indexOf("myClassName")!=-1 or document.classes.has("myClassName") or 'myClassName' in document.classes.