Skip to content

Comment on Show HN: A completely different way to write responsive, vanilla, CSS

Comments

So I think I understand how this works? Correct me if I'm wrong...

So I made this example: https://jsbin.com/meqibawotu/1/edit?html,css,output

We have two "toggle vars", `--is-hovered` and `--is-special`, which are triggered by a hover selector and a class, respectively, though they could be triggered by anything (like a media query or JS).

The "false" value for the toggle is "initial", so at the top I set:

    div {
      --is-hovered: initial;
      --is-special: initial;
    }
The first trick is that assigning a variable value as a single space token is valid according to spec (https://www.w3.org/TR/css-variables-1/#syntax), making the var(...) usage substitute a single space. So if our variable should be "true", we use whatever method to set it to a single space:
    div:hover {
      --is-hovered: ;
    }
    
    div.special {
      --is-special: ;
    }
The second trick is that an invalid property value will fall back to the second argument of the `var()` function. So we first create a property that only has a valid value if the flag is true (a single space):
    --hover-opacity: var(--is-hovered) 1.0;
If the div is hovered, `--is-hovered` is a single space, so the property value becomes:
    --hover-opacity:  1.0; // note two spaces
If the div isn't hovered, `--is-hovered` is `initial`, so the property value becomes:
    --hover-opacity: initial 1.0;
Which is invalid CSS!

We can then interpret this in our final opacity property:

    --regular-opacity: 0.5;
    --opacity: var(--hover-opacity, var(--regular-opacity));
If the div is hovered, the first argument is evaluated to:
    --opacity: var( 1.0, var(--regular-opacity));

And since that's valid syntax, the second argument is short-circuited (ignored). However, if the div isn't hovered, then the opacity property is computed as:
    --opacity: var(initial 1.0, var(--regular-opacity));
The first argument is invalid! So the property falls back to the second argument, and we get `var(--regular-opacity)`.

YEP! Absolutely nailed it. That's what's up! I've been calling it Space Toggle. It does all kinds of stuff beyond toggle though - the whole world of conditional logic is possible. You can combine them in any way, &&, ||, !, it's all possible.

You can see some more of my examples here: https://twitter.com/James0x57/status/1283912525248069632 https://twitter.com/James0x57/status/1283596399196680192 https://twitter.com/James0x57/status/1282303255826046977

The second version of augmented-ui is packed to the brim with it, I've been working on it for months :D

Can I ask, what’s the reason for using the keyword “initial”? As I understand it it could be any string that doesn’t accidentally create a valid value?

The OP tweet this about it [0], which links to the CSS spec [1]. It seems like a variable defined as initial triggers a different behavior than a traditional "syntax" error.

[0] https://twitter.com/James0x57/status/1283909866915074048

[1] https://www.w3.org/TR/css-variables-1/#invalid-variables

I was playing around with this here: https://jsbin.com/zebipenidi/1/edit and tried editing the keyword to other things.

When I tried other strings (my name, "null", other CSS "words" like opacity) it broke.

I wonder if this is because the initial variable definition needs to be valid css in order to be replaced?

This is really cool. How did you come up with this technique?

Thanks! :D I wanted really badly to be able to do it, so I read the spec very carefully top to bottom a handful of times. And suddenly one day I just realized it. Dove right in and after a bit of progress, I discovered all the logic that was possible too.

I had already been using spaces as a fallback value to do dynamic composition of standard properties ( https://twitter.com/James0x57/status/1233246818118533120 ) so it wasn't too far off to combine it with the "initial" behavior that causes the entire var dependency tree to evaluate to initial, allowing fallback behavior from any point in the tree. :)

Heads up too, Firefox and Chrome both had trouble setting a var to space from the dev tools css panel. So if you play with this further, you may have to deal with that.

I filed bugs to get it fixed though: https://bugzilla.mozilla.org/show_bug.cgi?id=1630488 (not fixed yet)

https://bugs.chromium.org/p/chromium/issues/detail?id=107129... (fixed!)

And minifiers hate it. lol

Could you get around it with a special `--empty: ;` rule in root perhaps? Would potentially make things more clear, also.

Yes, that would work. Then you just assign your properties to that var as long as you never inspect --empty on the root and you're good to test. Good thinking.

Should be fixed in FF sooner or later though, I reported it in April

dear god, how did we get here

(Neat trick I'm just weary of web languages that in practice feel like they're working against clarity)

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.