DEV Community

Cover image for ⚠️ Don't try this at home: CSS _as_ the backend - introducing Cascading Server Sheets!

⚠️ Don't try this at home: CSS _as_ the backend - introducing Cascading Server Sheets!

Pascal Thormeier on February 21, 2022

Here we go again! Another one of these, and promise, you will be questioning my sanity after this one. I was just getting groceries. I walked down...
Collapse
 
liviufromendtest profile image
Liviu Lupei • Edited

Developers trying to do everything with JavaScript, no one bats an eye.
Someone trying to do everything with CSS, and everyone loses their mind.

BTW, you should use Endtest to test it.

Collapse
 
liviufromendtest profile image
Liviu Lupei • Edited

Made a meme for this occasion:

css backend

Collapse
 
thormeier profile image
Pascal Thormeier

Amazing! That one gets a special place in my collection❤️

Collapse
 
oliveiracaue profile image
Cauê Oliveira

Don't judge JavaScript. it's not the fault of this madness. 😂

Collapse
 
grahamthedev profile image
GrahamTheDev

Why so serious? 😜🤣

Collapse
 
thormeier profile image
Pascal Thormeier

It's about sending a message. Over the internet. Built with CSS.

Thread Thread
 
grahamthedev profile image
GrahamTheDev • Edited

Do you want to know how I got these vars, huh? 🤣

Thread Thread
 
thormeier profile image
Pascal Thormeier

How about a magic trick? I’m gonna' make this budget disappear! TA-DAAAA!

Thread Thread
 
grahamthedev profile image
GrahamTheDev

I am a man of my (microsoft) Word!

Ok, I think I have run out of clever Joker puns as that one was just terrible!

Although for this article I think we missed the most apt quote:

“The only sensible way to live in this world is without rules.” (when he is being interrogated by Batman)

Collapse
 
posandu profile image
Posandu

Reminds me of joker. 😏😏

Collapse
 
heyclos profile image
Carlos de Santiago

Some people just want to watch my career burn.

Collapse
 
liviufromendtest profile image
Liviu Lupei

😂 nice one

Collapse
 
ankush981 profile image
Ankush Thakur

Best comment ever! :D

Collapse
 
stephenbrooks220413 profile image
Stephen A Brooks • Edited

To me that doesn't make sense why they would act that way, especially when developers and recruiters are more for making everything dynamic. If it makes it easier to load on web browsers then you'd figure it would be opposite.

Collapse
 
grahamthedev profile image
GrahamTheDev

Well I think you and I need to team up as this is the missing piece of my “abusing the Internet” series! 🤣

Absolutely incredible idea 💡

Imagine this idea combined with this one: dev.to/inhuofficial/i-built-a-3-pa... - we could change the world! 🤣

Collapse
 
thormeier profile image
Pascal Thormeier

I'm still amazed that what you built there actually works. Not sure if we would be able to implement the contact form, but the click listeners should be doable: You could resize the HTML tag to the mouse click coordinates and implement ranges via container queries, maybe? That should work...

Collapse
 
grahamthedev profile image
GrahamTheDev

Yeah I am not going to attempt it as my head would explode but I can just imagine how much damage we could do combining them 🤣

Thread Thread
 
thormeier profile image
Pascal Thormeier

Well then, here you go:

html {
    margin: 0;
    padding: 0;
    height: calc(var(--mousey) + 0px);
    width: calc(var(--mousex) + 0px);
    position: absolute;
    overflow: visible;
    display: inline-block;
    container-type: inline-size;
    container-name: mousepos;
}

body {
    position: absolute;
}

@container mousepos (min-width: 0px) and (max-width: 100px) and (min-height: 0px) and (max-height: 100px) {
    body::before {
        content: 'Clicked in 100 by 100 area';
    }
}

/* Usage: /size?mousex=12&mousey=32 */
Enter fullscreen mode Exit fullscreen mode

The amount of overhead this generates for a simple range of two numbers is hilarious, though.

Thread Thread
 
grahamthedev profile image
GrahamTheDev

Ah, I had not thought about it that way, I was thinking "you can't get the mouse position with CSS", but now I realise I hadn't thought about SERVER CSS and we can still have fun on the front end! I really do love this idea, it is completely bonkers 🤣

Thread Thread
 
thormeier profile image
Pascal Thormeier • Edited

Yeah, it takes some time to adjust to that modus operandi, I have yet to fully understand the monstrosity I created here. It definitely needs some out of the box (haha) thinking, but with a bit of creativity, I guess you can achieve a lot.

What I'm most afraid of is mixing up frontend CSS with backend CSS. I mean, there's no way of knowing which is which just from the file tree and every CSS file could technically be executed by the backend.

My brain doesn't like this.

Collapse
 
adrai profile image
Adriano Raiano

OMG!!! Why?

Collapse
 
thormeier profile image
Pascal Thormeier

Simple: To find out if it's possible! :D I'd never use this for real, but it was a fun little experiment nevertheless.

Collapse
 
adrai profile image
Adriano Raiano

You’re awesome & crazy 🤪

Thread Thread
 
thormeier profile image
Pascal Thormeier

No, you're awesome! 😄 Crazy is right, though, being normal is boring. 🤣

Collapse
 
stereoplegic profile image
Mike Bybee

Could vs. should

Collapse
 
kiyov09 profile image
Enrique Mejías

You’re insane my man! Bravo!

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you! I actually draw some pride from my craziness - it makes you find - how should I say - creative solutions. 😁

Collapse
 
darylbarnes profile image
Daryl Barnes

This makes as much sense as JSX so there’s that…

Collapse
 
thormeier profile image
Pascal Thormeier

But contrary to JSX, this isn't meant to be used in production 😅

Collapse
 
emwadde profile image
emwadde

The craziest thing anyone has ever done with css. Embrace the craziness. When developing internal apps, there is this gray area between staging and production, i think I'm gonna use this crazy idea in that area

Collapse
 
thormeier profile image
Pascal Thormeier

If you actually found a use case for this thing, I'm really curious about it! My opinion still is that this should never be used in any project ever, because it would confuse the living hell out of everyone involved.

Collapse
 
chuvisco88 profile image
Fabian Schweizer

But then again, is it confusing just because no one ever used it? What if this were a de-facto standard of doing things? Basically saying it is only confusing because people are not used to it (which might be a good thing or not)

Thread Thread
 
thormeier profile image
Pascal Thormeier • Edited

Yes and no. I pointed out in some other comment that there's no real distinction between frontend CSS and backend CSS and that every valid CSS file can basically be executed by this app. If there's no convention coming from userland to distinguish things, there's really no way to tell, except for opening every single file and looking. I do recognize that this is the same issue with Node/JS, but most FE frameworks know a way around that. If using CSS for the backend indeed was the standard since ages, I fully agree with you. Those conventions probably would've emerged by now. Probably CSS would also look way different, because it would serve two purposes. I could imagine that CSS would've developed into more of a scripting language than what it is today.

Collapse
 
mistval profile image
Randall

Such an awesomely dumb idea, and great write-up!

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you so much! Sometimes the seemingly dumbest ideas turn out to be the most fun!

 
thormeier profile image
Pascal Thormeier

I'm actually really thinking about this right now. Ok, I do consider using Paint API to get JS into the game via CSS a tiny bit of cheating, since it's not "plain" CSS, but, alas, some database connection would be handy, wouldn't it?

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

This reminds me of my client side only post only this is way way better!

Collapse
 
thormeier profile image
Pascal Thormeier

Glad you liked my post! I had a quick look - is it the portfolio post you meant? I've got two things to tell you. First, that's comparing apples and oranges. You've built something amazing and useful, I built a silly experiment. Second, every project is awesome, especially if you've had fun building it and learned something along the way. 😀 After all, every project has its very own set of challenges, right? 🙂

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

dev.to/adam_cyclones/client-side-o...

That one there.

The portfolio post is some really old post 😅

Thread Thread
 
thormeier profile image
Pascal Thormeier • Edited

Oh, I'm sorry, I didn't look hard enough apparently... Your approach is not so different from what I'm doing here, actually - we both use data URLs, you're just doing a lot more with it. I wonder how far you could go with that. Some bootstrapping JS encoded in na data URL that reads/writes to local storage would open up a ton of possibilities!

Collapse
 
bjkippax profile image
Ben

I'm highly conflicted by this article.

On the one hand I am impressed that you made it work but on the other, I have an inkling that because it "can" be done, then some poor soul is likely going to do it in a serious manner.

Collapse
 
thormeier profile image
Pascal Thormeier • Edited

You're likely right, some person will try this in a serious manner eventually. I mentioned several times that they shouldn't, though, and my hope is that this is enough to keep people from using this productively. However, there's also some technical limitations. For example, I haven't quite figured out yet how to do multiplications, let alone trigonometry or even things like powers or roots. CSS currently lacks some fundamental features that make it very unattractive to use for those things without having to sacrifice a ton of time upfront. I hope that people will notice that they're implementing stuff that's already there in JS and just use node instead.

Collapse
 
optimisedu profile image
optimisedu

I love this. It fits very well with the YouTube presentation "code is art" - sometimes we see stuff which isn't front end, back end, performant or even something you would call a hack, but it is so conveluted that you can only call it art because it takes so much skill and reminds people passion projects are always worth the journey.

Collapse
 
thormeier profile image
Pascal Thormeier • Edited

Thank you so much! It really was just a silly experiment to see if I could do it and what it takes to get there. I learned a ton along the way, actually, and even though I made something that is utterly useless to the real world, in my opinion, it has fulfilled its purpose by teaching a thing or two. :)

Collapse
 
thormeier profile image
Pascal Thormeier

I'm not sure this works out of the box with my implementation here. The CSS SQL adapter (I honestly never thought that I would write these two words so close together) uses the CSS paint API, so it's creating an image. My server relies on fetching actual machine readable text via PDF, it cannot handle images. However, if we can somehow replace the PDF approach with OCR and simply parse whatever text is on a - say - screenshot of the page, that would open up a ton of possibilities! I was actually thinking about using OCR to begin with but deemed it a total overkill for a simple PoC.

Collapse
 
amrikasir profile image
Al Amrikasir

What ??? Whyyy ??
I know.. that awesome, but.. WHY IT WORK ?😱😱😱😱

May I use CSS to add csrf to the form 🤔🤔🤔
Or, use CSS as a backdoor 😈😈😈

Collapse
 
thormeier profile image
Pascal Thormeier

Great question, actually! CSRF would require some sort of randomness to create cryptographically secure tokens, but sadly RNG is not part of CSS just yet. However, since we've got puppeteer in there, one could technically write a browser extension for that! Code injection should be possible currently, it's not doing much validation, but adding that would've exceeded the scope of the post. Then again: Does the average hacker really think about injecting CSS? :D

Collapse
 
jwp profile image
John Peters

I like your thought process. It's how people become artists at what they do. Others will say how did he do that..

Collapse
 
thormeier profile image
Pascal Thormeier

Wow, thank you so much! I like the explorative approach very much. I feel like planning everything in advance is often hindering my creativity. Solve one problem at a time, do some research, implement, on to the next part. Don't get me wrong, there's times you need to plan carefully, but for a silly experiment, creativity is much more important. I hope it's still understandable, though.

Collapse
 
valeriavg profile image
Valeria

Bloody brilliant 🤣🤣🤣

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you so much! Gotta admit, sometimes the line between genius and madness is very thin...

Collapse
 
ekimcem profile image
Ekim Cem Ülger

LOOOOOOOOOOOOOOOOOOOL

Collapse
 
thormeier profile image
Pascal Thormeier

Glad this made you laugh! :D

Collapse
 
ekimcem profile image
Ekim Cem Ülger

Your effort on this is admirable, you should create a repo and call people to improve it :D !

Thread Thread
 
thormeier profile image
Pascal Thormeier

I'm afraid that it will then spread and that people will actually start to use it lol

Collapse
 
xowap profile image
Rémy 🤖

From "CSS is in the full stack" to "CSS is the full stack"

Collapse
 
thormeier profile image
Pascal Thormeier

Hah, love that one! :D

Collapse
 
micahlt profile image
Micah Lindley

This is beyond cursed, but I love it so much. An absolutely amazing article!

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you so much, glad you liked it, even though it's cursed :D

Collapse
 
stokry profile image
Stokry

Very, very, very cooool :-)

Collapse
 
stokry profile image
Stokry

Do you have Git repo?

Collapse
 
thormeier profile image
Pascal Thormeier

Not a publice one, no. However, you can recreate this using the code and the steps described in the post :)

Collapse
 
codermapuche profile image
Nehuen Prados

Men... I really go to try some variarion of this in my next proyect.
If the css rule match the endpoint, and the property names are hook functions and properties values are the arguments, we can use it to configure a full backend lógic.
Now, we need an html (hook template method language) for write the hook functions without javascript!
Thanks for inspire my day.
PD: what about media querys based on user agent for match mobile versión?

Collapse
 
thormeier profile image
Pascal Thormeier

That should very well be doable, actually. One could use the CSS paint API for custom language-specific logic, for example. Only downside: the PDF trick probably wouldn't work anymore...

I doubt the usefulness of media queries in the backend, to be honest, the user's screen isn't available there. And the UA is problematic at best, it can be spoofed very easily.

Collapse
 
posandu profile image
Posandu

What the...

Collapse
 
thormeier profile image
Pascal Thormeier

I know, right? :D

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
thormeier profile image
Pascal Thormeier

There essentially is none, really. Other than the fun of seeing if it works. The journey is the reward, really. :)

Collapse
 
kouliavtsev profile image
kouliavtsev

This article is nuts! And I love it! ❤️

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you so much, glad you liked it! :D

Collapse
 
techman09 profile image
TechMan09

Very creative!

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you very much! Sometimes silly stuff like this just pops out into my mind. :)

Collapse
 
romuloctba profile image
RcDev

Crazy and awesome. But how to style those? With regular static css, is it? Naahh style it using restsapi (REST Styling API)

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you so much, glad you liked it! Using regular static CSS is actually discouraged with server-side CSS, since one cannot tell the difference between server-side and client-side CSS anymore. 🤣 The only logical conclusion would be to use - as you put it - some backend technology in there for styling. Perhaps that's possible... 🤔

Collapse
 
xolo profile image
Xolo

I feel that the legend of hacking with html is possible at this point.

Collapse
 
thormeier profile image
Pascal Thormeier

Oh, absolutely! I was thinking about some database integration actually. It could render in some more DOM (you know, CSS doesn't know lists etc.) that could be styled. Would be a bit cheated, though, since it's not only CSS anymore... Using HTML as a backend lang on the other hand is an entirely different story... wasn't that how DHTML and in turn PHP were born? :D

Collapse
 
varungupta3009 profile image
Varun Gupta

I'm so proud of this community. 🫀

Collapse
 
mandar1jn profile image
mandar1jn

Why are you using a try catch instead of checking if the file exists?

Collapse
 
thormeier profile image
Pascal Thormeier

A very good question! I used try/catch as a way to catch all possible file/disk IO errors that might occur. A good example would be permission errors.

Consider this bash code:

#!/usr/bin/bash
echo "Hello, World!" > someFile.txt
chmod 000 someFile.txt
cat someFile.txt # /usr/bin/cat: foo.txt: Permission denied
Enter fullscreen mode Exit fullscreen mode

It creates a file called someFile.txt and changes its mode to no read/write/execute permissions for anyone, not even the file owner. So noone can open the file without sudo or being root.

Now, let's check if Node can tell if the file exists and if it can open it:

const fs = require('fs');
console.log('File exists: ', fs.existsSync('./someFile.txt'))
console.log('File opened: ', fs.readFileSync('./someFile.txt'))
Enter fullscreen mode Exit fullscreen mode

Shows this:

File exists:  true
internal/fs/utils.js:307
    throw err;
    ^

Error: EACCES: permission denied, open './someFile.txt'
    at Object.openSync (fs.js:476:3)
    at Object.readFileSync (fs.js:377:35)
    at [stdin]:3:33
    at Script.runInThisContext (vm.js:133:18)
    at Object.runInThisContext (vm.js:310:38)
    at internal/process/execution.js:77:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:76:60)
    at internal/main/eval_stdin.js:29:5
    at Socket.<anonymous> (internal/process/execution.js:205:5) {
  errno: -13,
  syscall: 'open',
  code: 'EACCES',
  path: './someFile.txt'
}
Enter fullscreen mode Exit fullscreen mode

So, while checking for file existence already catches the most obvious error, using try/catch helps me work around a lot more errors that I did not anticipate.

Collapse
 
starkraving profile image
Mike Ritchie

This is mad scientist level… I like it!

Collapse
 
thormeier profile image
Pascal Thormeier

Thank you! I won't put that title in my CV, though, it might raise a few eyebrows... :D

Collapse
 
kateshim625 profile image
kateshim625

Thank you for the good info!

Collapse
 
thormeier profile image
Pascal Thormeier

You're welcome! Glad you liked it :)

Collapse
 
rinodrummer profile image
Gennaro Landolfi

I have a name for it:

--CSS

It's a mix between two concepts: C++ (the pre-decrement makes clear that there are less computational options) and CSS Custom Properties syntax.

Collapse
 
thormeier profile image
Pascal Thormeier

Uuh, love it! "dash dash css" has a nice ring to it, I must say. I was also thinking about something like CSSSSSSSSSSSSSS - "Cascading Style Sheets Simply Shifted Server Side So Silly Science Supplies Sellable Shiny Solutions Seamlessly"

Collapse
 
horaceshmorace profile image
Horace Nelson

You're a mad man. 😂

Collapse
 
thormeier profile image
Pascal Thormeier

Being normal is boring, though, isn't it? 😁

Collapse
 
yoursunny profile image
Junxiao Shi

Puppeteer on the server! I thought about the same:
dev.to/yoursunny/the-worst-server-...

Collapse
 
thormeier profile image
Pascal Thormeier

PHP to invoke Node to invoke puppeteer to invoke chromium, how amazing is that! :D How well does this chain perform, actually?

Collapse
 
dylanwatsonsoftware profile image
Dylan Watson • Edited

Life.. uhhh... finds a way.<br>

Collapse
 
thormeier profile image
Pascal Thormeier

Me building this abomination:

It's alive!

Collapse
 
qaynam profile image
qaynam

now we need new css backend framework 😄

Collapse
 
thormeier profile image
Pascal Thormeier

Oh no, what have I done! 🤣 Just for the sake of the pun: How about "Headwind" as the first framework's name?

Collapse
 
arnavvashisth profile image
Nalanda Technologies

I just cannot believe it!! This is incredible !! A stroke of genius!

Perfectly recommend this post to participants of hackathons and codeathons which do not allow JS.

Collapse
 
thormeier profile image
Pascal Thormeier

Haha, even though I said to not try this at home, I would very much like to see the baffled faces of the judges when they see this monstrosity :D

Collapse
 
thonio profile image
Thonio

When Commitstrip predict the futur! => commitstrip.com/en/2019/03/15/css-...?

Collapse
 
thormeier profile image
Pascal Thormeier

LOL 3 years earlier, even :D

Collapse
 
technoknol profile image
Technoknol

World is already complicated, and now this... phew...

Collapse
 
thormeier profile image
Pascal Thormeier

At least everyone knows and realizes that this is silly and unnecessary 🤪 I like to think of this as a science experiment with no direct use in the real world and it was fun to build, so I got that going for me, which is nice!

Collapse
 
gabboman profile image
Gabriel Amador García

I would ask why. But you answered that already. and I hate you

Collapse
 
gabboman profile image
Gabriel Amador García

hate as an "thanks I hate it"

Collapse
 
qm3ster profile image
Mihail Malo

Did you mean to return Promise.resolve(x) instead of return x in an async function?

Collapse
 
thormeier profile image
Pascal Thormeier

That must've been a leftover from a previous version of the code, thanks for the find. It doesn't really make much of a difference, as simply returning a value is equivalent to returning a fulfilled promise explicitly.

Collapse
 
liznix profile image
Liz Nix

try it without javascript tho

Collapse
 
thormeier profile image
Pascal Thormeier

Given that, at least as far as I've heard, Node was invented by ripping out Chromiums JS engine and making it executable, I think it should be possible to do the same with the CSS/rendering engine. Might not even need the PDF with that approach.

The main reason I used JS for this, is that I needed some language to carry out the execution. It's basically the same as with Node and C++, only that here it's JS to run CSS, not C++ to run JS.

Collapse
 
rhuzaifa profile image
Huzaifa Rasheed

This is crazy and interesting at the same time 😄. Is it hosted?

Collapse
 
oliveiracaue profile image
Cauê Oliveira

Unnecessary method. Just create you're own css file and be happy. This doesn't make sense. MDN has a lot of this things that will learn you to do on the frontend.

Collapse
 
thormeier profile image
Pascal Thormeier

It shouldn't make sense, and that's the exact reason I built it: I wanted to see if I could use a frontend technology as the backend. It was meant as a really silly experiment and as it turns out, it works.