
Show HN: A completely different way to write responsive, vanilla, CSS - James0x57
https://propjockey.github.io/css-media-vars/
======
James0x57
I know the docs need a little love but I think this has potential to be a game
changer for writing responsive CSS. It has named breakpoints, lets you write
DRY selectors, doesn't rely on JS or any sort of build step, and if you're
already used to seeing --css-variables it's easier to read/maintain too.

I've created a couple JS Bins if you want to play around with it a bit, resize
the "output" pane to see it update:

Minimal example:
[https://jsbin.com/giqedowale/edit?css,output](https://jsbin.com/giqedowale/edit?css,output)

More involved example:
[https://jsbin.com/yicuqujehe/1/edit?html,css,output](https://jsbin.com/yicuqujehe/1/edit?html,css,output)

If you're familiar with CSS, it may seem like it's impossible for this to work
without scripts, but while working on another project I realized in the CSS
Spec for custom properties that combining a few small details they've
highlighted, in a specific order, it makes it possible to do all kinds of
things that have never been possible before in CSS. This is the first project
I've released using the idea.

Anyway, it's totally free and open source too so hack away if you'd like!
[https://github.com/propjockey/css-media-
vars](https://github.com/propjockey/css-media-vars)

I'll probably be refreshing this page for a while, so I'm happy to answer any
questions or dive into the CSS Spec with you and talk about the tech if you're
curious!

~~~
progx
For vanilla css-writer it could be a game changer, but who writes vanilla css
in 2020? SASS make it so easy to write complex css simple.

css-media-vars would be a game changer for me, if it will be possible to use
one var and not define many varnames and put them together to one var.

Like your Example:

    
    
      --xs-width: var(--media-xs) 100%;
      --sm-width: var(--media-sm) 49%;
      --md-width: var(--media-md) 32%;
      --lg-width: var(--media-gte-lg) 24%;
      width: var(--xs-width, var(--sm-width, var(--md-width, var(--lg-width))));
    

If it would work something like this, it would be really awesome:

    
    
      --width: var(--media-xs) 100%;
      --width: ifundefvar(--media-sm) 49%;
      --width: ifundefvar(--media-md) 32%;
      --width: ifundefvar(--media-gte-lg) 24%;
      width: var(--width);
    

Or

    
    
      --width: var(--media-xs) 100%
        else var(--media-sm) 49%
        else var(--media-md) 32%
        else var(--media-gte-lg) 24%
        else 5%
      width: var(--width);

~~~
SiVal
I write vanilla CSS in 2020, but I suspect you're right in a "most people"
sense. Still, I'm biased toward longer-lived approaches, meaning that whenever
I can make it practical, I try to build with vanilla HTML, CSS, & JS with as
few other technologies & libs as I practically can. Even my final HTML tends
to be quite human-readable.

Again, this won't work for many projects, but the point of it is long-term
maintainability. I assume that most of what is built into major, recent
browsers will have the longevity of bottled wine, while technologies outside
the browser will be more like fresh grapes. If I want the site itself to be
more like the wine than the grapes, doing something with it years from now
shouldn't require a tool that no one has used for years.

~~~
PetahNZ
To be fair sass variables have been around much longer than css variables.

~~~
SiVal
But it's not how long they've been around, it's whether they're built into
standard browsers. Presumably, CSS variables can never be removed from
standard browsers. They are permanently available in the web "toolchain". SASS
can be replaced by something else. There will be workarounds, but it will
probably be more of a problem.

------
Rotten194
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](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](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)`.

~~~
James0x57
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/1283912525248069632)
[https://twitter.com/James0x57/status/1283596399196680192](https://twitter.com/James0x57/status/1283596399196680192)
[https://twitter.com/James0x57/status/1282303255826046977](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

~~~
tobr
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?

~~~
uxamanda
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](https://twitter.com/James0x57/status/1283909866915074048)

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

------
cosmotic
When I clicked to see vanilla CSS, an NPM package was not something I expected
to see.

~~~
wbobeirne
You're more than welcome to copy the code directly into your project
([https://unpkg.com/css-media-vars@1.0.1/css-media-
vars.css](https://unpkg.com/css-media-vars@1.0.1/css-media-vars.css)) or read
the code, learn the technique, and implement it yourself. NPM is just one
option for how to use the author's flavor of the technique.

------
LukeBMM
This a profoundly creative and clever idea which I hope to never see in any
actual use, ever. I really appreciate the ingenuity, but I can't help but feel
its legibility and maintainability are nightmarish.

------
delgaudm
Interestingly this site is almost completely unreadable[0] on Android Chrome

[0][http://imgur.com/gallery/5LZ6leC](http://imgur.com/gallery/5LZ6leC)

~~~
CrazyStat
Works fine for me on Android Chrome 84.0.4147.89

------
9935c101ab17a66
This is really cool. As I was writing some media queries today, I was yearning
for a simpler solution.

Couple of nice-to-haves: \- More examples (though I'm guessing this is really
new, and they will come in time). \- Guidance on best practices for variable
naming (when an element has multiple responsive properties). I just ended up
doing `--sm-property-name` for each variable.

Are you looking for contributors? I intend to use this approach for a project
over the next few days, and I could help with the documentation.

------
russdpale
This is awesome, build steps in CSS are absurd if you really sit there and
think about what the purpose of the browser is compared to what it used to
be..

No build step should be the future of web development. The more steps that are
added that require yet more tools to learn and more dependencies to maintain,
the less inclusive and creative the web becomes. Hopefully we will one day be
able to look back on this time period as an evil necessity.. I mean writing
es6 and building to es5 is way better a lot of the time from a development
perspective but on the face of it, its absurd and its why tooling gives people
fatigue and turns away new promising developers for better programming
languages.

I would definitely provide a way to download the css without npm first. Like
big worm said, its about principalities.

~~~
James0x57
Preach! I wholeheartedly agree.

The CSS file is in the repo: [https://github.com/propjockey/css-media-
vars/blob/master/css...](https://github.com/propjockey/css-media-
vars/blob/master/css-media-vars.css)

and the readme links to this in an example link tag: [https://unpkg.com/css-
media-vars/css-media-vars.css](https://unpkg.com/css-media-vars/css-media-
vars.css)

NPM is for convenience. Can't expect people to jump out of the build env all
at once, so providing a vanilla CSS solution as a package is a good way to
start the transition. IMO /shrug

------
satvikpendem
Making CSS Turing complete, nice. Now we can run entire websites with
functionality even if we turn JS off. Maybe we'll even see CSS only
programming frameworks.

~~~
onion2k
I wrote a game in CSS to demonstrate what you can do with it -
[https://codepen.io/onion2k/pen/qBbKYee](https://codepen.io/onion2k/pen/qBbKYee)
(no mobile because I was too lazy to make it responsive). CSS is _very_
powerful, but you need to do some weird stuff to get interactivity.

------
tmpfs
This is really smart, good job. I look forward to taking this for a spin, the
point of not adding a build step is critical for some of my current work. I
think the time for using CSS preprocessors is over, they add very little value
now we can use variables and combined with tricks like these we can speed up
our builds!

------
sm4sh
Am I not getting this or is this just a slightly different way of using
breakpoints like bootstrap some years ago? I think we've come full circle.

~~~
esperent
What makes this one different is that, for example, if you want to set the
width, you just do it once. Other approaches (including bootstrap) you have to
type "width" once for every break point where it's different.

The resulting code from this approach looks a little cleaner and nicer
compared to bootstrap or normal CSS, at first glance. I'd have to test it
before commenting further though.

------
ketzo
I quite like this. It’s a small idea that tooootally changes the way
responsive stuff gets written. I’m gonna try this out on my next project.

------
captn3m0
Suggestion: provide a plain text version of the combined media queries to help
the reader understand.

------
PudgePacket
Damn.. super interesting!

------
deltron3030
This _breakpointless_ approach is interesting:

[https://utopia.fyi/](https://utopia.fyi/)

~~~
esperent
I use something similar on my own website and it's great. However, it's very
limited - I've never seen it applied to anything except for text. It's likely
that for most use cases you will need to combine this with at least some
traditional breakpoints.

~~~
deltron3030
It might work with very simple apps that have lot of excess whitespace on
larger devices. You'd focus on the mobile experience first, and then on
blowing it up in a visual pleasing way.

For the layout you'd use a rule based approach instead of breakpoints.

But yeah, vanilla css folks are more focused on content sites like blogs, not
web-apps with dense tables, dashboards etc.

