This content originally appeared on Bram.us and was authored by Bramus!
Back in February I created @bramus/specificity
, an NPM package to calculate the Specificity of CSS Selectors.
As that version was more of a though experiment/POC, there was a lot of room for improvement. Yesterday, after 11 betas, version 2.0.0 of @bramus/specificity
was released. Let’s take a look …
~
Quick Example
To give you an idea of what it’s all about, here’s a quick demo:
See the Pen
Calculate Specificity by Bramus (@bramus)
on CodePen.
The input accepts a string that contains one or more CSS Selector(s) — a Selector List. @bramus/specificity
will calculate the specificity for each Selector that it detects (powered by csstree
).
~
Notable Changes since v1
✨ Introduce and use a Specificity
class
Where v1 exposed a standalone calculate
function which returned simple Objects, v2 now exposes a Specificity
class which represents a calculated specificity. The calculate
function is now a static method of that class.
import Specificity from '@bramus/specificity';
const selectors = 'header:where(#top) nav li:nth-child(2n), #doormat';
const specificities = Specificity.calculate(selectors);
specificities.map((s) => s.toString());
// ~> ["(0,1,3)", "(1,0,0)"]
The class also has many instance methods for you to use.
-
Read the specificity value using one of its accessors:
const s = specificities[0]; s.value; // { a: 0, b: 1, c: 3 } s.a; // 0 s.b; // 1 s.c; // 3
-
Convert the calculated value to various formats using one of the
toXXX()
instance methods:s.toString(); // "(0,1,3)" s.toArray(); // [0, 1, 3] s.toObject(); // { a: 0, b: 1, c: 3 }
-
Extract the matched selector string:
s.selectorString(); // "header:where(#top) nav li:nth-child(2n)"
-
Use one of its instance comparison methods to compare it to another
Specificity
instance:s.isEqualTo(specificities[1]); // false s.isGreaterThan(specificities[1]); // false s.isLessThan(specificities[1]); // true
-
Don’t worry about using
JSON.stringify()
:JSON.stringify(specificities[0]); // { // "selector": 'header:where(#top) nav li:nth-child(2n)', // "asObject": { "a": 0, "b": 1, "c": 3 }, // "asArray": [0, 1, 3], // "asString": "(0,1,3)", // }
~
👨👩👧👦 Support Selector Lists
v1 only accepted single selectors to calculate. v2 accepts Selector Lists. Because of that, Specificity.calculate(…)
will always return an array, with each entry being a Specificity
instance — one per found selector.
If you know you’re passing only a single Selector into Specificity.calculate()
, you can use JavaScript’s built-in destructuring to keep your variable names clean.
const [s] = Specificity.calculate('header:where(#top) nav li:nth-child(2n)');
s.value; // { a: 0, b: 1, c: 3 }
~
🗜 Reduced Bundle Size
By only importing the selector-parser
from css-tree
, the bundle size was greatly reduced. Thanks to a code contribution to css-tree
, some of the code in @bramus/specificity
could also be removed.
~
🔀 Utility functions for comparing, sorting, and filtering
On the Specificity class, several static methods are exposed for comparing, sorting, and filtering.
-
Comparing:
Specificity.compare(s1, s2)
: Compares s1 to s2. Returns a value that can be:> 0
= Sort s2 before s1 (i.e. s1 is more specific than s2)0
= Keep original order of s1 and s2 (i.e. s1 and s2 are equally specific)< 0
= Sort s1 before s2 (i.e. s1 is less specific than s2)
Specificity.equals(s1, s2)
: Returnstrue
if s1 and s2 have the same specificity. If not,false
is returned.Specificity.greaterThan(s1, s2)
: Returnstrue
if s1 has a higher specificity than s2. If not,false
is returned.Specificity.lessThan(s1, s2)
: Returnstrue
if s1 has a lower specificity than s2. If not,false
is returned.
-
Sorting:
Specificity.sortAsc(s1, s2, …, sN)
: Sorts the given specificities in ascending order (low specificity to high specificity)Specificity.sortDesc(s1, s2, …, sN)
: Sorts the given specificities in descending order (high specificity to low specificity)
-
Filtering:
Specificity.min(s1, s2, …, sN)
: Filters out the value with the lowest specificitySpecificity.max(s1, s2, …, sN)
: Filters out the value with the highest specificity
A specificity passed into any of these utility functions can be any of:
- An instance of the included
Specificity
class - A simple Object such as
{'a': 1, 'b': 0, 'c': 2}
These helper functions can also be imported as standalone functions, thanks to the use of SubPath Exports.
import { compare, equals, greaterThan, lessThan } from '@bramus/specificity/compare';
import { min, max } from '@bramus/specificity/filter';
import { sortAsc, sortDesc } from '@bramus/specificity/sort';
~
🤖 Type Definitions
Although @bramus/specificity
is written in Vanilla JavaScript, it does include Type Definitions which are exposed via its package.json
.
~
💻 CLI script
@bramus/specificity
exposes a binary named specificity
to calculate the specificity of a given selector list on the CLI. For each selector that it finds, it’ll print out the calculated Specificity
as a string on a new line.
$ specificity "header:where(#top) nav li:nth-child(2n), #doormat"
(0,1,3)
(1,0,0)
~
Getting @bramus/specificity
@bramus/specificity
’s source is available on GitHub and is distributed through NPM:
npm i @bramus/specificity
If you encounter any issues, you can leave them in the Issue Tracker.
~
Thank me with a coffee.
I don't do this for profit but a small donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.
This content originally appeared on Bram.us and was authored by Bramus!
Bramus! | Sciencx (2022-03-31T21:52:55+00:00) What’s new in @bramus/specificity v2. Retrieved from https://www.scien.cx/2022/03/31/whats-new-in-bramus-specificity-v2/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.