Extend .css
with JavaScript the easy way!
Below is information, learning resources, code, and demos relating to extending CSS in valid .css
files using JavaScript
- You listen to global events in the browser, or events on DOM nodes, or observers: ResizeObserver, IntersectionObserver, and MutationObserver
- When an event you're listening to is triggered, you call a "stylesheet function" that returns CSS. This can be a string of CSS, or a CSSStylesheet object, or a CSSRule object, or other ways of representing a set of property declarations for one or more elements
- After the stylesheet function is processed, the returned CSS is applied to the document, or output as objects or a string
Using this simple model we can polyfill existing CSS features in old browsers using small amounts of CSS and JavaScript that run very fast, as well as prototype and implement new styling functionality that's not part of CSS.
- you never have to go lower-level than CSS (don't use JS to reinvent CSS, use it to extend CSS)
- do everything in CSS that you can do in CSS
- use JavaScript to make CSS higher-level and more declarative
- split your styles by the events that drive their calculation
Both the
jsincss
andcomputed-variables
plugins linked below are event-driven style managers and can be used to extend CSS stylesheets (and rules), and CSS variables
You can use the event-driven model for processing style information with plugins like jsincss
and computed-variables
from JavaScript, and you can build on top of them with your own plugins and your own abstractions for storing and processing style information.
The idea of Caffeinated Style Sheets, or writing CSS that's extended by JavaScript builds on top of what these plugins provide and are concerned with how to store JS-powered style information in valid CSS syntax, as well as easy ways to read that information out of CSSOM and DOM so JavaScript can work with it, avoiding the need for custom syntaxes or having to express everything in JavaScript.
This is all about keeping your CSS in CSS and your Javascript in JavaScript, but finding ways to write CSS and JavaScript that compliment each other and make advanced styling techniques effortless.
You can invent custom at-rules in valid CSS syntax by extending @supports () {}
using a custom identifier like --custom()
or --example()
, and if you have arguments to pass into the function to encode them as something JSON.parse()
can read to maximum compatibility and simplicity. This is useful for polyfilling at-rules coming to CSS like @document
, as well as inventing your own queries, like element queries or container queries.
@supports (--custom("arg1", 2, {"arg": 3})) {
div {
color: blue;
}
}
This is valid CSS that includes information that's simple for JavaScript to find, parse, and process, we could end up with a call to a JavaScript function like this:
custom("arg1", 2, {"arg": 3}, `
div {
color: blue;
}
`)
Read more about writing custom at-rules in the deqaf readme
CSS syntax also includes the ability for us to invent any attribute selector we want, so if we invent a custom attriute selector like [--custom]
we can be sure that will never match anything in HTML. If we have arguments to pass into the function we can encode them in a format JSON.parse()
and read and extract that with JavaScript later. In this example it wouldn't be hard to read this and extract custom("div", "arg1", 2, {"arg": 3})
to run with a JavaScript function named custom()
:
div[--custom='"arg1", 2, {"arg": 3}'] {
color: blue;
}
Read more about writing custom selector in the deqaf readme
CSS already includes the ability for us to define custom properties as long as we start the name with a double-dash --
to ensure it never collides with any future CSS property. What's great about custom properties (aka css variables) in CSS is that they can be defined and set in CSSOM (css stylesheets) or in DOM (html style=""
attribute), and can be read and written from JavaScript. This makes them an amazing way for JavaScript functions to supply values to CSS that it can use for styling:
In CSS:
div {
--custom: ["arg1", 2, {"arg": 3}];
color: var(--custom);
}
Read more about some ways you can use the
computed-variables
to write JS-powered CSS custom properties in the computed-variables readme
or in HTML:
<div style='--custom: ["arg1", 2, {"arg": 3}];'></div>
- deqaf-demo
- qaffeine-demo
#merryCSSmas
plugin roundup with deqaf#merryCSSmas
plugin roundup with qaffeine- Caffeinated Style Sheets collection on Codepen
- Computed Variables collection on Codepen
- jsincss (manage dynamic stylesheets)
- computed-variables (update CSS variable values)
- parse-css-stylesheet
- parse-css-rule
- process-css-rules
- stringify-css-stylesheet
- stringify-css-rule
- css-polyfill-patterns
- element-query-tests
- element-unit-tests
- jsincss-viewport
- jsincss-overflow
- jsincss-protocol-sniffer
- jsincss-days
- element queries
- @document
- navigator queries
localStorage
andsessionStorage
queries- date queries
- jsincss-parent-selector
- jsincss-has-selector
- jsincss-closest-selector
- jsincss-first-selector
- jsincss-last-selector
- jsincss-elder-selector
- jsincss-previous-selector
- jsincss-string-match
- jsincss-regex-match
- jsincss-custom-specificity
- computed style selector
- nth-letter and nth-word
- playing, paused, muted, and current-time pseudo-classes for
<video>
and<audio>
- not-blank valid/invalid selector
- compare attribute values as numbers
- Excerpt from “Caffeinated Style Sheets” talk about writing custom JS-powered selectors and custom at-rules in valid CSS syntax
- Methods of Extending CSS Selectors and At-Rules with JavaScript
- Defining Custom At-Rules in CSS (extending CSS with JavaScript)
- An Approach for Defining Custom Events for JS-powered Rules Inside CSS Stylesheets
- Using JS-Powered Custom Pseudo Classes from CSS