[css-houdini-drafts] [css-properties-values-api][css-paint-api] Feature proposal: Value Transform worklets (#1088)

matthew-dean has just created a new issue for https://github.com/w3c/css-houdini-drafts:

== [css-properties-values-api][css-paint-api] Feature proposal: Value Transform worklets ==
Hi, all. Thanks for continuing to push this forward. Recently, I was working on a blog post to compare the current state of CSS to what's currently possible with Less / Sass.

When I got to a section talking about custom functions / utilities in Less & Sass, I dived back into Houdini specs and documentation to look at what's possible or would be possible in the current spec.

Interestingly, while Houdini's Paint API is very powerful, I found it actually has a gap in emulating / supporting the most common use case of Less / Sass functions and mixins, which is **simple value transforms**.

### The Current Scenario

Say you wanted to implement something like Less's `darken` function, to derive a color based on another given color. A common use case for this is to set a color theme, and derive colors based on theme colors.

In Less, you could do something like:
```less
.box {
  border: 1px solid darken(#80e619, 20%);
}
```
In Houdini, in order to emulate this, you could, I suppose, create a canvas, and draw the pixels for the border, but you would of course, need to do all your own calculations in JavaScript for things like border radius, or various border thickness or styles. In other words, you'd be re-implementing entire sections of browser rendering code just to change the color of a border.

The advantage with a value transform is that the calculations / drawing a much more efficient, because the rendering is still left entirely to the browser.

### The Proposal

Instead, I propose an extension to worklets that, instead of providing an image, provide a CSS value, and can be used wherever that value is allowed in CSS.

The form of the worklet could be something like:
```js
registerValue('darken', class {

  static get inputArguments() { return ['<color>', '<percentage>']; }
  static get output() { return ['<color>']; }

  value(ctx, geom, properties) {
    // return a simple transform of values
    // see: https://github.com/less/less.js/blob/master/packages/less/src/less/functions/color.js#L282
  }
})
```

#### Including in CSS
After the worklet is registered...
```js
CSS.valueWorklet.addModule("color-extensions.js");
```
...then it could be called with a simple referencing syntax. I'm not sure what's best / most logical for CSS here, but some options I thought of are:

```css
border-color: use.darken(#80e619, 20%);
border-color: use-darken(#80e619, 20%);
border-color: fn.darken(#80e619, 20%);
border-color: fn-darken(#80e619, 20%);
```
If it were more like the Paint worklet API, it could be like the following:
```css
border-color: use(darken, #80e619, 20%);
```

### Why?

Just to re-iterate, there are lots of Less and Sass utility functions (as well as other CSS value transformation utilities on NPM) which would be trivially or near-trivially immediately implementable with a value transform, and would be extremely non-trivial to implement using the Paint API.

### Why not just continue to use pre-processors?

CSS, in the last decade, has largely taken a "pave the cowpaths" approach to common pre-processor patterns, such as the [Nesting proposal](https://www.w3.org/TR/css-nesting-1/) and the [Conditional At-Rules proposal](https://tabatkins.github.io/specs/css-when-else/), not to mention Custom Properties which can, in many cases, be a replacement for CSS variables. (It's also worth noting that CSS has often adopted functions that exist / existed in Sass / Less.) Sass and Less (or at least I can speak for Less) are intended to enable easier DX patterns, but with the understanding that the easiest DX may be, in the future, to simply use CSS.

In addition, there are many use cases for defining properties / values at runtime based on certain conditions or user input. A Value Transform worklet could replace use cases for approaches like CSS-in-JS, by using a much-more efficient worklet model to derive CSS values.

### Note

Btw, my apologies if something like this is already possible using the Paint API. I've searched through everything I could find, and I couldn't find anything for doing simple value transforms.

Please view or discuss this issue at https://github.com/w3c/css-houdini-drafts/issues/1088 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Saturday, 25 March 2023 18:32:21 UTC