Changelog
3.2.1 — 2026-11-02#
Fixed#
- While a stylesheet is first applied with
invisibleon (the default), transitions are paused. Before, elements with atransitionanimated from the browser's default styles on every page load, so buttons briefly faded from grey and links from blue.
3.2.0 — 2026-11-02#
Pseudo-elements become usable from JavaScript and hoverable in CSS, in every browser.
Added#
::before:hover,::after:hover,::before:activeand::after:activein stylesheets.css.on(type, selector, handler): delegated events that fire only when the pointer is on the pseudo-element, e.g.css.on('click', '.chip::after', fn).dialog::backdropclicks too. Returns a function that removes the listener.css.pseudo(element, '::after'):style(),set(),text,exists,contains(x, y),rect()andanimate()for one element's pseudo-element.css.pseudos(selector): every rendered pseudo-element matching a selector, likequerySelectorAll().
3.1.0 — 2026-10-15#
Twenty new built-in behaviours that replace small scripts almost every site copies.
Added#
- Navigation and scrolling:
:currentand:current(exact)for the active link,:scrolledand:scrolled(80px),:scrolling-downand:scrolling-up,:scroll-startand:scroll-end, and:target-in-viewfor scrollspy menus. - Images and layout:
img:loaded,img:broken,:wrappedfor flex and grid items that wrapped,font-size: fit(min, max)to fill a box, andheight: same/min-height: samefor equal heights. :seen(300px)and:in-view(300px): a pixel margin that triggers before the element is visible, for lazy backgrounds.- Values:
$[count],$[year],$[random(1,5)](stable per element) and$[attr(data-x)](per element, usable insideurl()). - Forms and environment:
:filled,:dirty,:offlineand:idle(30s).
Changed#
- One shared set of passive event listeners drives every scroll, form, image and idle state.
- Web fonts finishing loading now recalculate auto-updating values, so
fit()andsamemeasure the final font.
3.0.0 — 2026-10-01#
The first public release under the MIT License, and the biggest update since the library began.
Added#
:seenand:seen(30%): matches once an element has been in view.:in-viewand:in-view(50%): matches while an element is in the viewport.:stuck: matches while aposition: stickyelement is pinned, at the top or bottom, in the page or in a scroll container.:overflowing: matches when content is larger than its box.:contains("text")and:contains("text" i): select by text content.- Numeric attribute comparisons:
[data-x<5],[data-x<=5],[data-x>5],[data-x>=5]. - All new selectors work inside
:has(),:not()and:is(), and update live when the DOM changes. - Nesting:
&anywhere (.dark &,&-suffix,& + &), declarations directly inside nested rules, and@media,@supportsand@containerinside rules.
Changed#
$[index]gives each element a stabledata-css-iattribute instead of relying on:nth-child(). It is now correct when a heading comes before the items, with several containers, with wrapped elements, with selector lists and with::beforeor::after.$[index]is recalculated after the page loads, so it works when the stylesheet is opened in<head>.- The nesting engine was rewritten. Rules are written in source order, and repeated selectors are no longer merged.
- Released under the MIT License (previously GPL-3.0).
Fixed#
//comments no longer delete URLs such asurl(https://...)or@import url(//...).- Native
attr()inside values, such ascontent: attr(data-label), is no longer replaced. - Commas inside
:is(),:where(),:not()and:has()no longer break nested selectors. &:hoveras the first nested block no longer moves the following rules under it.&{}blocks no longer discard the rules before them.- A space before a pseudo-class (
.menu :focus-visible) keeps its meaning. - Text inside quotes is never changed.
- Auto-updating variables inside
@mediablocks stay inside them. css.open()accepts file names with hyphens and query strings.- Runtime updates handle URLs containing
:, multi-word properties and!importantcorrectly. - Repeated updates no longer add duplicate rules.
2.2 — 2023#
- 7/12/23:
$attrno longer overrides existing inline styles. - 6/20/20:
vertical-align: middle!andbottom!keep elements aligned when they resize. - 3/20/20: added
attr()to apply an attribute's CSS text as inline styles. - 3/5/20: fixed default parameters being overwritten.
- 1/8/20: rewrote variable extraction.
2.1 — 2019#
- 11/1/19: fixed argument extraction from variables.
- 10/18/19: when several stylesheets load at once, the page is shown after all of them finish.
- 10/17/19: fixed extraction of default arguments.
- Added the
indexvariable, auto-updating variables with!,min-/max-margin and padding, and theinvisibleoption.
1.x — 2016#
- 11/1/16: added the
localCacheoption. - 5/20/16: improved
css.vars.w()andcss.vars.h(). - 5/19/16: the page appears sooner, and
css_readyfires once the document is interactive. - 1/21/16: fixed whitespace handling in nested styles.
- 1/13/16: fixed passing a parameter equal to its default.