Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find classes that are not used in any CSS selector?

Tags:

html

css

Consider the following HTML excerpt from a page:

<style type="text/css">
.existing-class {
  background-color: #000;
}
</style>
<div class="existing-class non-existing-class"></div>

It has 2 classes applied. Here is the thing: non-existing-class is not defined anywhere in the CSS available in the page, however div is using it.

My question is: How can a developer programmatically detect elements in the page which are using classes that are not actually defined in the loaded CSS?

like image 612
Andry Avatar asked Feb 09 '18 09:02

Andry


People also ask

How do I know which CSS class is not used?

The idea is to load up document. styleSheets and find all the rules (the ones that are classes). Then, use a MutationObserver to watch the DOM for all HTML, and check the classList of each node to see if it matches any from any stylesheet. If the HTML has a class not found in a stylesheet, report it.

How do I find classes in CSS?

The . class selector selects elements with a specific class attribute. To select elements with a specific class, write a period (.) character, followed by the name of the class.

How do you select an element without a class?

The :not CSS pseudo-class can be used to select elements that do not contain a specific class, id, attribute etc.


1 Answers

Okay, there you go ;)
Take a look at the script I have created, especially getUndefinedClasses function.

function httpGet(theUrl) {
  var xmlHttp = new XMLHttpRequest();
  xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
  xmlHttp.send( null );
  return xmlHttp.responseText;
}


function getAllCSSClasses(cssdata) {
  var re = /\.(.+)\{/g;
  var m;
  let classes = [];
  do {
    m = re.exec(cssdata);
    if (m) {
      for(let key in m) {
        if(
           (typeof m[key] == "string") && 
           (classes.indexOf(m[key]) == -1) &&
           (m[key].indexOf(".") == -1)
          )
          classes.push(m[key].replace(/\s/g, " "));
      }
    }
  } while (m);
  return classes;
}

function getAllClasses() {
  var csses = document.querySelectorAll('link[rel="stylesheet"]'); 
   var classes = []
  for (i = 0; i < csses.length; ++i) {
    // let styledata = httpGet(csses[i].href);
    var styledata = ".hi{ display: none; }";
    var cclasses = getAllCSSClasses(styledata);
    var classes = Object.assign([], classes, cclasses);
    classes.concat(cclasses);
  }
  return classes;
}

function getHTMLUsedClasses() {
  var elements = document.getElementsByTagName('*');
  var unique = function (list, x) {
    if (x != "" && list.indexOf(x) === -1) {
        list.push(x);
    }
    return list;
  };
  var trim = function (x) { return x.trim(); };
  var htmlclasses = [].reduce.call(elements, function (acc, e) {
    return e.className.split(' ').map(trim).reduce(unique, acc);
  }, []);
  return htmlclasses;
}


function getUndefinedClasses(cssclasses, htmlclasses) {
  var undefinedclasses = [];
  for (let key in htmlclasses) {
    if(cssclasses.indexOf(htmlclasses[key])  == -1 ) {
       undefinedclasses.push(htmlclasses[key]);
    }
  }
  return undefinedclasses;
}

var cssclasses = getAllClasses();
var htmlclasses = getHTMLUsedClasses();

console.log("Undefined classes : " + getUndefinedClasses(cssclasses, htmlclasses))
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link rel="stylesheet" href="hi there">
</head>
<body>
  <div class="hi"></div>
  <div class="there"></div>
  <div class="there_thier_333"></div>
</body>
</html>

What is done:

  1. I get all the classnames from the css data, (you can pass the css data by various means).
  2. Then I get all the classes used in HTML elements, both of these are recorded in arrays.
  3. Finally, I simply push the classes which were used by HTML Elements but not found in the cssclasses array which leaves you with the undefined classes in CSS.

(jsbin here needed)

like image 140
The SuperKat Avatar answered Sep 29 '22 11:09

The SuperKat