Help - Search - Members - Calendar
Full Version: [Tool] CSS Specificity Calculator
Invision Power Services > Community Forums > Community Web Design and Coding
Stephen
I made a CSS specificity calculator today because I was bored (its fairly pointless but so what wink.gif). Just thought I'd post the URL so people can play around with it

http://www.rebelinblue.com/specificity.php

Find any problems just let me know.

For those who don't know CSS specificity is how the browser knows which rules to apply when multiple rules conflict, the selector with the higher score gets used
Michael K.
Ooh.. nice, not seeing any problems so far. original.gif
Just a question, but how do you measure specificity? Happen to have a reference or something?
Stephen
The way it works is with an "abcd" formula (the way the W3C explains it, just replace the result of a, b, c, d below)

a) 1 if the selector is a "style" attribute otherwise 0
b) count the number of ID attributes in the selector
c) count the number of other attributes (classes and [attribute]) and pseudo-clases (:hover etc) in the selector
d) count the number of elements and pseudo-elements (:before etc) in the selector

The way I do it

Start at 0, add 1000 for style attribute, add 100 for each ID, add 10 for each attribute/pseudo-class, add 1 for each element name/pseudo-element


So "body #content .data img:hover" would be 121 (or 0121)

1 for body, 100 for #content, 10 for .data, 1 for img and 10 for :hover

So they both work out the same

You can see more info at http://www.w3.org/TR/CSS21/cascade.html#specificity
Veracon
Might want to set 'Properties' as 'position: fixed'...
Stephen
nah thats OK was just a quick knock up for something I needed today whilst at work, will sort out the html itself when I get home from work
Michael K.
QUOTE(Stephen @ Jun 29 2005, 06:32 AM) *
The way it works is with an "abcd" formula (the way the W3C explains it, just replace the result of a, b, c, d below)

[..snip..]

You can see more info at http://www.w3.org/TR/CSS21/cascade.html#specificity

Ah, alright. Thanks. original.gif
And yeah, all it needs now (if you get bored again) is a little touching up really. Who ever said a generator couldn't look pretty? tongue.gif
Stephen
Found an error html>body #item returns 100, it must be more than that but I'm not sure what it would be, I assume 102
ReloadedElement
Thats a nice script you got there. Sure it will come in handy.
Brendon Koz
Aww, no source? original.gif
Stephen
will add a view source option later, but trust me its ugly wink.gif Literally knocked it up because I wanted a quick way to find out the values of my CSS files without having to manually do it
Stephen
CODE
<html>
<head>
<title>CSS Specificity Calculator</title>
<script type="text/javascript">
function show(data) {
window.document.getElementById('code').innerHTML = data;
}

function floatdetails() {
var posY = 0;
var netscape = (navigator.appName.indexOf("Netscape") != -1);

function move(id) {
var divpos = document.getElementById ? document.getElementById(id): document.all ? document.all[id] : document.layers[id];

divpos.sP = function(y) {
this.style.top = y + "px";
};

divpos.y = posY;
return divpos;
}

window.floatdiv = function() {
var pY = netscape ? pageYOffset : document.body.scrollTop;
pos.y += (pY + posY - pos.y) / 8;
pos.sP(pos.y);
setTimeout("floatdiv()");
}

pos = move("code");
floatdiv();
}
</script>
</head>
<body>
<div align="center">
<h1>CSS specificity calculator</h1>
<?php

/*
*
* CSS specificity calculator
* Written by Stephen Ball
* http://www.rebelinblue.com
* --------------------------
* If you improve on this script
* please do let me know
*
*/

function cleanup(&$data, $value) {
$data = trim($data);
}

// Pseudo classes
$classes = array(":link", ":visited", ":hover", ":active", ":focus", ":target", ":lang", ":enabled",
":disabled", ":checked", ":indeterminate", ":root", ":nth-child", ":nth-last-child",
":nth-of-type", ":nth-last-of-type", ":first-child", ":last-child", ":first-of-type",
":last-of-type", ":only-child", ":only-of-type", ":empty", ":contains", ":not");
// Pseudo elements
$elements = array(":before", ":after", ":first-line", ":first-letter", ":selection");

// HTML tags
$tags = array("a", "abbr", "acronym", "address", "applet", "area", "b", "base", "basefont", "bgsound",
"bdo", "big", "blink", "blockquote", "body", "br", "button", "caption", "center", "cite",
"code", "col", "colgroup", "comment", "dd", "del", "dfn", "dir", "div", "dl", "dt", "em",
"embed", "fieldset", "font", "form", "frame", "frameset", "h", "h1", "h2", "h3", "h4", "h5",
"h6", "head", "hr", "html", "i", "iframe", "img", "input", "ins", "isindex", "kbd", "label",
"legend", "li", "link", "listing", "map", "marquee", "menu", "meta", "multicol", "nextid",
"nobr", "noframes", "noscript", "object", "ol", "optgroup", "option", "p", "param", "plaintext",
"pre", "q", "s", "samp", "script", "select", "server", "small", "sound", "spacer", "span",
"strike", "strong", "style", "sub", "sup", "table", "tbody", "td", "textarea", "textflow",
"tfoot", "th", "thead", "title", "tr", "tt", "u", "ul", "var", "wbr", "xmp");

// Check if form has been submitted
if (isset($_POST["css"])) {
// Strip slashes
$_POST["css"] = get_magic_quotes_gpc() ? stripslashes($_POST["css"]) : $_POST["css"];

$data = preg_replace("/\/\\*[\\s\\S]*?\\*\//", "", $_POST["css"]); // Strip comments
$data = preg_replace("/\{(.*?)\}/s", ", ", $data); // Strip content and replace with delimiter
$data = str_replace(" ,", ",", $data); // Strip spaces after selectors

$tmp = explode(",", $data); // Get rid of selector groupings
array_walk($tmp, 'cleanup'); // Trim whitespace from end of selectors

?>
<table border="1" width="760" style="margin: auto;">
<tr>
<td>
<table>
<tr align="middle">
<th width="40%">Selector</th>
<th width="5%">Score</th>
<th width="5%">Properties</th>
</tr>
<?php

// Loop through the selector array
foreach ($tmp as $var) {
$score = 0; // Set the score to 0
if (!empty($var)) {
$score += substr_count($var, '#') * 100; // Count the IDs and multiple by 100 (i.e. #itemID)
$score += substr_count($var, '.') * 10; // Count the classes and multiple by 10 (i.e. .classname)
$score += substr_count($var, '[') * 10; // Count the attributes and multiple by 10 (i.e. input[type=text])

foreach ($classes as $test) { // Count the pseudo-classes and multiple by 10
$score += substr_count($var, $test) * 10;
}

foreach ($elements as $test) { // Count the pseudo-elements and multiple by 10
$score += substr_count($var, $test);
}

$cleaned = str_replace(":", " ", $var); // Remove the pseudo selector
$cleaned = str_replace("+", " ", $cleaned); // Remove the adjacent sibling selector
$cleaned = str_replace(">", " ", $cleaned); // Remove the child selector
$cleaned = str_replace("*", " ", $cleaned); // Remove the universal selector
$cleaned = str_replace(".", " ", $cleaned); // Remove the class selector
$cleaned = str_replace("#", " ", $cleaned); // Remove the ID selector

$cleaned = explode(" ", $cleaned); // Explode on space
foreach ($cleaned as $rubbish) { // Count the type selectors (i.e. HTML tags)
if (in_array(strtolower($rubbish), $tags)) {
$score++;
}
}

// Now to find the actually properties
$code = substr($_POST["css"], strpos($_POST["css"], $var)); // Find the position of the current selector
$first = strpos($code, "{") + 1; // Get the position of the first {
$last = strpos($code, "}"); // Get the position of the first }

$code = substr($code, $first, $last - $first); // Get the content between the { and }
$code = preg_replace("/\/\\*[\\s\\S]*?\\*\//", "", $code); // Strip any comments from the properties

// Now make the data safe for javascript
$code = trim($code); // Trim the properties
$code = str_replace("\\", "\\\\", $code); // Escape any slashes
$code = str_replace("'", "\\'", $code); // Escape any apostrophes
$code = str_replace("\r\n", "<br>", $code); // Convert new lines to HTML break (Can't use nl2br as it doesn't remove the newlines)
$code = str_replace("\n", "<br>", $code);
$code = str_replace("\r", "<br>", $code);

$score = str_pad($score, 3, '0', STR_PAD_LEFT); // Pad the final score to 3 characters
$defined = substr_count($code, ":"); // Count the number of properties the selector defines

?>
<tr>
<td onmouseover="show('<?=$code;?>');" onmouseout="show('');" style="cursor: pointer;"><?=$var;?></td>
<td align="center"><?=$score;?></td>
<td align="center"><?=$defined;?></td>
</tr>
<?php
}
}

?>
</table>
</td>
<td width='50%' valign='top' style="padding: 5px;">
<center><strong>Property data</strong></center>
<div id='code' style='position: relative;'></div>
<script type='text/javascript'>floatdetails();</script>
</td>
</tr>
</table>
<p>Note: Inline styles using the HTML &quot;styles&quot; attribute have a score of 1000.</p>
<p><a href="specificity.php">Start over</a></p>
<?php
}
else {
?>
<p>Paste your CSS into the field below, the specificity of your selectors will be calculated for you.</p>
<h2>Current limitations</h2>
<ul>
<li>Your CSS <b>must</b> <a href="http://jigsaw.w3.org/css-validator/" title="Ensure the file is valid CSS">be valid</a> in order for the calculator to work</li>
<li>Currently only HTML elements are counted in the score, custom tags such as XML are not</li>
</ul>
<form method="post" action="specificity.php">
<textarea name="css" rows="25" cols="90"></textarea>
<br /><input type="submit" value="Calculate" />
</form>
<?
}
?>
</div>
</body>
</html>


I've over commented it so you can see whats going on, have fun wink.gif
Brendon Koz
sad.gif Half the fun is in figuring out what others do and how they do it. I guess that's the debugger in me from college when I was helping to look over classmates' C++ programs that had well over 144 compiler errors...then you fix 10 or so errors and it would run further (not knowing it stopped as I didn't read ALL errors) and you'd get 500+ errors the next time around. wink.gif

Thanks though, much appreciated! This will help me out while I continue to (ever so slowly) learn CSS.
Stephen
Ah yes, know whats thats like biggrin.gif
elj
Nice. original.gif
Cool Dude 2k
Looks awesome Very nice job you did on it Stephen. cool.gif happy.gif
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.