[css-houdini-drafts] [css-custom-functions] user-defined custom CSS functions (#1007)

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

== [css-custom-functions] user-defined custom CSS functions ==
I wish there was a way to make re-usable CSS "functions".

Currently, we can't make re-usable logic without unfortunately coupling to HTML markup. See:

- https://stackoverflow.com/questions/63459791/why-do-these-css-variables-not-work-when-passed-into-calc
- https://stackoverflow.com/questions/52015737/css-scoped-custom-property-ignored-when-used-to-calculate-variable-in-outer-scop

As you can tell from those pages, in order to make re-usable expressions ("functions"), we must couple the re-usability to the HTML markup, which is not ideal.

It would be great to be able to create re-usable logic/functions in a way that does not require a CSS author to ever touch any HTML code.

How might an proposal syntax look like, to work around the current limitation?

Perhaps:

```css
:root {
  --sum: function( calc( var(--a) + var(--b) ) )
}

/* Then anywhere in any CSS rules, without dependence on HTML markup: */
.foo.bar.whatever {
  --a: 4px; --b: 6px;
  font-size: call(--sum);
}
```


^ In that example, the user does not have to worry about "evaluating CSS variables at the level where they are needed" (which requires the CSS author to touch the HTML markup as shown by @Afif13's nicely-written answer in the second SO question).

There's probably a bunch of other ways we could do it.

Here's another idea for sake of spinning up some ideas:

```css
:root {
  --sum: function(--a, --b, calc( arg(--a) + arg(--b) ) )
}

/* Then anywhere in any CSS rules, without dependence on HTML markup: */
.foo.bar.whatever {
  font-size: call(--sum, 4px, 6px);
}
```

Or, maybe we can create a new special type of block (it may be cleaner):

```css
@function sum(a, b) {
  return: calc(arg(a) + arg(b))
}

/* Then anywhere in any CSS rules, without dependence on HTML markup: */
.foo.bar.whatever {
  font-size: sum(4px, 6px);
}

/* Maybe `call()` or similar is required to distinguish from builtins? */
.foo.bar.whatever {
  font-size: call(sum, 4px, 6px);
}
```

Maybe functions can also return a rule expression, which could be "mixed" onto a rule (not sure about syntax though):

```css
@function foo(a, b, c) {
  return {
    background: a b c;
  }
}

.whatever {
  call(foo, lightblue, url("foo.gif"), no-repeat); /* How to handle commas? */
  color: red;
}
```

results in equivalent of

```css
.whatever {
  background: lightblue url("foo.gif") no-repeat;
  color: red;
}
```

or something.

With `@function`, maybe the return just has to match the context where the function is being used. For example in the previous two examples we saw it used to return a property value, and to return a rule that is mixed in the rule where it is used.

Maybe we could also use it at the top level to create top-level rules (not sure about the particular syntax, probably someone with CSS implementation expertise can weigh in):

```css
@function makeKeyframes(name, a, b, c) {
  @keyframes arg(name) { ... something here ... what are a, b and c? ... }
}
```

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


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

Received on Thursday, 20 August 2020 20:27:42 UTC