I’ve been thinking a lot about the problems we have with styling and modularity. For those unaware, CSS (and even to a greater degree Less) are sort of a square hole / round peg problem. They don’t fit nicely with the modlet structure we all love. Both were designed with the idea of styling a page, not styling a component. This is the root source of our problems.
I don’t have a firm solution in mind at the moment, when I do I’ll probably put that here. But I thought why not share with the community some of my ideas anyways! Maybe someone will have some better ideas than mine.
These are scattered thoughts so please forgive me.
Compile time vs. runtime variables
Less and Sass and probably every other compile-to-css language uses compile-time variables, mixins, and functions. Less and Sass lets you define variables/mixins and functions in the same files that contain styling rules.
This is hard for us, in order to compile styles we need those variables/mixins at compile time, so you need to import them. But if you import them you might also be importing styling rules. So you can quite easily wind up with duplicate styling rules and all other sorts of messes.
CSS doesn’t support mixins or functions (yet). It does support variables though. CSS variables are awesome! You can change a variable at runtime to retheme your application on the fly. That’s amazing!
What’s even more amazing is that CSS doesn’t get “compiled” so it doesn’t matter if the variable exists in the file where you use it:
.sidebar {
color: var(--main-fg-color, #fff);
}
CSS doesn’t care if you defined --main-fg-color
or not, it will just ignore it if not.
This makes CSS very appealing to people who like modlets. The downside is that many browsers don’t CSS variables yet.
That’s ok, though, you can have compile them in your production build process. Modlets is about development, if you can get the benefit of modlets during development it’s not so bad if dev doesn’t work perfectly well in IE11.
The downside is that mixins and functions aren’t there yet. Mixins (@apply
rules) are being worked on so there’s hope!
My point of this section is that I favor a CSS-based solution (maybe one that extends CSS) over choosing a compile-to-css language.
What is a modlet’s “main”?
StealJS and just about every other solution out there treats JavaScript as the lower common denominator with regard to web assets. I think this is wrong. HTML is the lowest common denominator. HTML is the format that can load all other formats that a browser recognizes. That’s why I think HTML Imports make a lot of sense. A HTML import file might look something like this:
<link rel="stylesheet" href="./tabs.css">
<script type="text/stache" id="myTemplate">
<div class="foo">
{{bar}}
</div>
</script>
<script type="steal-module">
import Component from "can-component";
import stache from "can-stache";
Component.extend({
tag: "my-tabs",
view: stache.from("myTemplate"),
...
});
</script>
An HTML file that is your modlet’s main could contain it’s JavaScript (or link to it), it’s CSS (or link to it) and its Stache (or link to it). We have something like this today with done-component but it’s not nearly as powerful as you can’t include arbitrary HTML or reference the HTML in that file using document.querySelector and friends.
The argument against HTML Imports is that they are only supported by Chrome but I don’t find that to be a convincing argument given that importing CSS in JavaScript isn’t supported by any browser; it’s something we implement ourselves. Given that we have to extend the module system anyways, we might as well choose the right format, and HTML is a better choice than JavaScript for modlets.
An alternative idea would be defining a manifest file for a modlet, something like this:
{
"script": "./tabs.js",
"style": "./tabs.css"
}
When perhaps you could load from other files like:
import "~/components/tabs.json!modlet"
Or something to that effect. The downside here is that writing a manifest file is a burden on developers.