HTML isn't a "tree of elements" though; it's about content token sequences described by regular languages where the symbols can also represent nested markup. The regular content model stuff is what drives SGML/HTML tag omission/inference and is a major feature of markup languages as a text format compared to primitive co-inductive expression syntax a la s-expr and co.
Also see a full web rendering engine (modern HTML + CSS + the whole layout engine) made in pure Python, that can export to PDFs: https://github.com/Kozea/WeasyPrint
They even support a lot of properties that aren't in Gecko/WebKit/Blink, like the @page rules.
My main gripe with CSS is that rules are selectors only. Classes can't compose or inherit (or, if they can, I don't know about it and would welcome a correction).
For example, let's say I use a third-party css library (materializecss, or similar) that provides a class `btn-warning` and `warning-text`, which sets say 10 fields (colors, elevation, etc) on the former and `text-transform` on the latter.
I just want to write one new class that inherits fields from both the existing classes.
I can't specify a new class `my-btn-warning` that inherits all the fields from `btn-warning` and `warning-text`.
I can't create a new class `my-btn-warning` that is composed of `btn-warning` and `warning-text`.
My only option (open to correction) is to copy-and-paste the existing `btn-warning` and `warning-text` fields into my new `my-btn-warning` class.
There's simply no reusability here.
If I want reusability, I need to go outside the spec i.e. have a build step. Not just any build step, but one that exactly matches the upstream library. Which is impossible if there are two upstream libraries, or if my existing build step is different.
This project looks nice but it combines all the disadvantages of writing CSS with all the disadvantages of a build step and adds the extra downside of not being compatible with anyone else's (including mine) build step.
To me, this is the worst of all worlds, with no redeeming advantage at all.
It sounds like you're blaming CSS for the shortcomings of the library you're using.
CSS cascades, embrace it rather than fighting it.
Have a .btn rule that styles all your buttons. Have a .warning one that makes it yellow. Then instead of `<button class="btn-warning">` use `<button class="btn warning">`.
> It sounds like you're blaming CSS for the shortcomings of the library you're using.
...
> Or just use Sass instead!
Maybe I was unclear: my gripe is that this functionality is such a necessary thing to have, that external non-spec third-party tools have to be used to get this functionality.
It is a shortcoming of CSS, because CSS is not providing this functionality that users want.
The fact that everyone is using a third party tool to get this functionality only reinforces my point: if everyone is doing it, then it's a shortcoming.
> Have a .btn rule that styles all your buttons. Have a .warning one that makes it yellow. Then instead of `<button class="btn-warning">` use `<button class="btn warning">`.
I do this, but it ends up being `class="<godawful number of named classes?"` and is prone to breakage when you need to update or modify a theme.
You're composing in the wrong abstration layer, you just use the both classes and if you need any extra stuff you want, then you just create a selector for `.btn-warning.warning-text.my-btn` and as the selector is more specific than the classes that is uses then you can override the functionality it inherits.
After dealing with the current state of affairs regarding the front end, I think this is pretty interesting. I've been writing Go web apps with templ and htmx. I've punted on dealing with CSS using a cdn and bulma. I did get Tailwind and friends working, but it required a lot of work being outside a React/JS framework like next.js. It also felt really weird using npm to install CSS.
The nice thing about this is that you can get a tailwind Go lib to programmatically build into your binary. There are no extra files, one build step, and one binary output. After trying out Fly and Vercel, I went to running things with docker on a VM, and a single binary in a container makes things much simpler IMO.
This looks pretty cool and I look forward to seeing folks do interesting things with it.
I do this too. Using a hot reload server and having live reload in the browser as I'm changing tailwind classes, go files or templ files is a very efficient workflow.
Then for the actual build, everything is built and embedded in a single binary by conditionally using embed with build tags.
I think that live feedback development cycle is probably the most satisfying way to code something by oneself.
It did need quite a bit of messing around with tooling and my Makefiles are pretty big but at least I can reuse that in every new project.
I use the "live reload with other tools" as it is described in the templ docs [0].
Basically, templ will start a live reload server in "proxy mode". Other tools can then request a reload by notifying the proxy. I started with the makefile described in the docs. But I also have tailwind in watch mode, esbuild builds and more.
I use the standard library html/template package for generating CSS dynamically, it's got pretty good CSS support. I've found it useful for things like custom themes and UI preferences.
This is cool, for binaries that provide a web interface, for admin purposes, maybe a blog, or whatever, keeping it simple with some styling to make it a little more swish, this is all I'd be looking for. I'll give it go for sure.
I’m just curious why you want to create a type of programming language that does the things it is supposed not to do, such as replacing JavaScript with Python on the front end or running an ML project in a browser with pure JavaScript...
To be fair, the project sounds completely pointless.
Why is why I absolutely love it.
It's the true hacker's spirit - about testing the frontiers of what's possible. Note what was said as well:
> This is really just a bit of fun and a way to write CSS in Go. I wanted to see if it was possible and it is with ease.
And I thought this was aspirational as well:
> CSS written in Pure Go. No JS builders, no preprocessors, no linters, no frameworks, no classes, no variables, no overrides, no plugins, no dependencies, no javascript, no templates, no bs, no nothing. Just Go.
Rust people are all about "let's rewrite it in Rust". I don't see why Gophers can't have their fun as well.
Errr cool I guess? Definitely triggers my 'possibly overengineered' intuition, but hey, even if it is, at least it's not gonna waste cycles on the user's browser.
Dev experience does look pretty good.
To be fair, i have been quite happy with templ's style support, which would not really be useable in a non-templ project.
A bit verbose, but I can see it working if media queries are added. Why one would chose this over vanilla CSS I don't quite know but there is worse out there.
"I wanted to find a way to easily control the CSS from the server side and not have to worry about pre-building the css to take variables and stuff. I didnt want to use UI libraries that are written for JS frameworks and I didn't want to use preprocessors or linters that add more steps to the build process.
The benefit of all this are
Keeps the css free of variables.
Keeps html free of classes like bg-gray-50 text-black dark:bg-slate-800 dark:text-white and eliminates the need to remember to add the dark variant.
I recently saw a button component on an html page 10 times with over 1800 characters in the class attribute of each!"
I am also yet to ever find a reasonable explanation for why adding HTML classes a la tailwind is ever bad for the end user. I can see the argument for the DX suffering cause you have a ton of classes in one long line and that can make things a bit unreadable but why does the user or the browser care how many classes there are? The browser has optimised workflows to bunch up all the styles in all those classes to render the elements and all more classes would mean is a few extra bytes to download
You've literally answered you own question - DX. To some, developer experience and the ergonomics of utility is more important. Others aren't of that mindset which is equally okay. I'm guessing you're of the latter camp in this case.
* at least FF dev tools get unusable with enough variables (and in general, it's not a fun experience to debug which one out of a thousand others is wrong)
* efficiency (one less hash lookup, less bookkeeping for the browser)
* works on older browsers (or mine ;)
* you become a member of the exclusive club of devs that don't believe in turning CSS into a turing-complete language (old fashioned, I know)
The project looks like it’s done for fun. From an architecture standpoint - the server is something you pay for, while logic and design outsourced to the browser is handled by the client’s compute and thus fun is free to you (unless your clients are on underpowered devices).Take advantage of free. See if you can move more stuff to the client instead :)
Unsure if you're trolling: your attitude is basically big cashed up corporates squatting on their users' devices, because their devs are too lazy, unempathetic, incompetent, or all three, to pick a better solution.
This shit is why basic webpages drain my battery and burn my lap.
No, the attitude is that CSS is for decoration to meet the User’s needs (colors, dark or light mode, font sizes and adjustments for accessibility, etc). So moving it to backend is a bad idea because you remove the users ability to customize or at worst make your entire service delayed both for all users and for the user who needs the customization by doing it on the server. (now I understand the tool featured here is for precompile, but this is the argument i was making before I knew that).
The whole industry of React and similar giant frameworks is to offload functionality to the browser and make the server only a data source - you reduce the amount of data that has to go through tight pipes and speed up the responsiveness of the site for your users. Basic pages drain your battery for sure. There is a gradient of that and putting CSS in the front end is the wise minimal end of that gradient, while React is the opposite side of it, then add SQLite and you go even more client heavy. It depends on the tool you are building - some justify it, but many don’t.
Please note that using slash at the end of the tag is not supported in HTML:
<link rel="stylesheet" href="base.css" />
I often see such code and it seems that people simply don't know HTML and copy random garbage they found on the Internet. In the example above, the slash is simply ignored, but in this example the code will be parsed not as intended:
<div/>
This is why you should read proper documentation or specification instead of blindly copying garbage code from Internet.
> ... if the element is one of the void elements ... then there may be a single U+002F SOLIDUS character (/) (at the end of the element, before the closing bracket)
No, spec authors simply added a rule to ignore the slash because Internet was full of garbage code and they realized that it is hopeless to expect low-quality frontend developers to fix their code. There is no such thing as "self-closing element" in HTML spec (only SVG and MathML have them because they are based on XML).
Quoting the spec [1]:
> Then, if the element is one of the void elements, or if the element is a foreign element, then there may be a single U+002F SOLIDUS character (/), which on foreign elements marks the start tag as self-closing. On void elements, it does not mark the start tag as self-closing but instead is unnecessary and has no effect of any kind. For such void elements, it should be used only with caution — especially since, if directly preceded by an unquoted attribute value, it becomes part of the attribute value rather than being discarded by the parser.