Skip to content

tomhodgins/caffeinated-style-sheets

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 

Repository files navigation

Caffeinated Style Sheets

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

How Event-Driven Styling Works

  1. You listen to global events in the browser, or events on DOM nodes, or observers: ResizeObserver, IntersectionObserver, and MutationObserver
  2. 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
  3. 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 and computed-variables plugins linked below are event-driven style managers and can be used to extend CSS stylesheets (and rules), and CSS variables

Writing Caffeinated Stylesheets

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.

Writing Custom At-rules in CSS

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

Writing Custom Selectors in CSS

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

Writing Custom Properties in CSS

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>

Slides to the “Caffeinated Style Sheets” Talk

Demos

Plugins

Event-Driven Style Managers (CSS reprocessors)

Parse JS-powered Styles from CSS

  • deqaf (parse CSSOM client-side)
  • qaffeine (parse .css files server-side)

Building Blocks for CSS Tooling

Plugins Compatible with jsincss, deqaf, and qaffeine

Custom At-rule Plugins

Custom Selector Plugins

Videos

Explorations and Experiments