New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
view-scoped CSS via JSS #108
Comments
That's interesting. It looks like it would make maintaining styles of components a good deal easier. It also looks like it would enable things that are currently very hard to do. I could see myself using that and don't mind to be the first to try. What's the first step for that project? |
First let's decide on what makes sense. I think that defining a stylesheet per view instance is not gonna be good. JSS cannot diff/patch the stylesheets so we don't want to have to regenerate and replace them on each vm.redraw(). That leaves prototype-style JSS styesheets that can be compiled once per view class and domvm will simply handle adding an extra className to view's root elements automatically. Since each view closure/state is assumed to be isolated to each view instance, compiling and returning function MyView() {
var JSS = {};
return {
// this is view instance specific since it can use this closure's state
render: function() {},
// this would apply to any MyView views and using per-instance closure state will lead to bugs
style: JSS,
};
} This touches on #109 and the fact that we need some form of declared base function MyView() {
return {
render: function() {},
};
}
var JSS = {};
MyView.style = JSS; While more logical, this authoring style feels unnecessarily imperative. If we plan to do per-view-class stylesheets (and not per-view-instance), it would make sense to get #109 sorted out first. EDIT, removed some draft stuff that made it into this comment :) |
Agreed. Regenerating on There is another option: generate a stylesheet on mount and ditch it on unmount. That's what React-JSS does. React-JSS seems to be using per-component sheets and sharing them if multiple of the same component are mounted. Per-view-class JSS sheets seem to be closest to what we can already do with CSS preprocessors (except that JSS also provides a guarantee that styles don't get mixed up due to bad selector choices and results in smaller file size overall - at the cost of having to generate styles at runtime). I'm new to all this CSS-in-JS business, so let me try to summarize: Per-view-class
Per-instance
It may be intuitive to author, but if it's returned by the view function, the author is likely to expect that they're defining a stylesheet per-view-instance. I'm with you on this one. As you might have guessed, I don't mind the "imperative look" of attaching per-view-class styles to a view. :) It gets the job done and it's clear what it does. Sure, there's syntactic sugar (e.g. ES7 decorators) that could be used to make it "look less imperative", but that should be up to the user to do. |
Another thought on runtime-variable-dependent styles: Using a CSS-in-JS solution, we can define styles for components and we can also define "global styles". If I'm having a use case where I can make my runtime-variable-dependent styles all "global styles", it would be simple to just manually trigger a recompute of the global styles whenever the runtime-variable changes. To customize the styles of components based on the content of a runtime-variable, I'd pass in the global styles to the component, and then manually add the classes from the global styles to the elements that need them. Example: define the background color of all navigation bars on the page as a global style, then enjoy the straightforward ability to change that color based on user input. That's just one pattern that would work with per-view-class stylesheets. And then, there's still the option of using inline styles for runtime-variables whose use is so intricate that their styles can't be flattened into a global stylesheet. |
if you want to hash out some of these semantics concretely, that would be great. we can start with the imperative as far as what's required of domvm itself...
I'll let you figure out how to handle isomorphic rendering and any required [1] https://github.com/leeoniya/domvm/blob/2.x-dev/src/view/ViewModel.js#L183 |
To get up and running:
I should probably make minification optional to make the Java/Closure dependency optional or fall back to UglifyJS...or just transition to TypeScript. Maybe i'll get around to it one day ;) [1] https://github.com/leeoniya/domvm/blob/2.x-dev/package.json#L11-L22 |
Thanks for the detailed pointers, I will look into it and sketch some possible patterns of using CSS-in-JS tomorrow. |
also, it might not be a terrible idea to run the prefixer after compilation. this would allow the system to still work generically on any provided css sting rather than relying on JSS's structure in case we want to allow other css compilers. i guess this would mean that you can just compile it exterally using whatever preprocessor anyhow and all domvm would need to do is be made aware of the view having a non-null one idea is to mutate any that's probably the way to go here. minimal coupling. |
Some observations I made about the default behavior of JSS:
and
followed by attaching both style sheets results in something like this:
Cool! In different JSS sheets, I can use the same identifier to mean different things and JSS takes care of generating css class names that don't collide. This seems convenient.
and
followed by attaching both style sheets results in something like this:
Note how the resulting css class name for For most applications (e.g. those that have a fixed set of styles), this shouldn't matter, since, as long as the correct styles are applied, it doesn't matter whether the generated css class names are distinct between components. For applications where styles change dynamically, it means that css class names do change when styles are modified (let's say some end user selects orange as their profile color and resultingly the sheets are regenerated). That means that we need to redraw the component after changing its JSS stylesheet so that the component is aware of the new css class names. In a use case with per-view-class JSS stylesheets this means redrawing all instances of the particular view. Doing a redraw in the rare case of modifying a stylesheet seems unproblematic to me. When letting JSS generate css class names, collisions with external CSS are unlikely but still possible. Example: the other side uses a different css-in-js solution that by chance happens to generate the same class name. This is very unlikely to happen, but prefixing would indeed help with solving the issue quickly when it occurs. If we prefix, we might just as well not let JSS generate css class names at all. Prefixing takes care of disambiguating class names between components and third party code. I think, if the addon architecture is flexible enough, there may not even be the need for domvm's code to explicitly talk about styles. Is there a simple way for addons to use hooks (specifically, mount hooks for the vm)? This may be related to the idea of a View base class that can be extended by addons. Then, we could do the same as the React-Jss plugin: 1) attach stylesheet on mount, 2) keep a reference counter to remember the number of mounted views of the particular class on the view class itself, 3) detach stylesheet when reference counter reaches zero. |
Update: JSS has a |
You could use https://github.com/thysultan/stylis.js. |
@grumpi thanks for the research,
that's gonna be the way to go. plus i assume we won't have CSS compiler compression cause poor debugging, lack source maps (i could be wrong here). there is no global mount/unmouunt hook but we can add one. the counter sounds like a good idea. i would prefer to have domvm handle the prefixing via a single regex replace stylis looks good. i think i dont think i'd want to bake a css compiler into domvm, but leave some integration spec/api so a third-party one can be hooked up. i'll certainly add stylis to a "pairs well with" section in the docs, similar to |
@thysultan That looks interesting and seems to have about 20% the (gzipped, minified) size of JSS (without plugins, so JSS size will be even bigger with vendor prefixing). I like your approach of focusing on the essentials (vendor prefixing and componentizing styles). There's a lot that JSS offers that isn't strictly necessary. I personally need a way to reuse global style definitions without having to copy-paste them. Like SASS mixins or extending classes (extending classes generates css like It looks like selector specificity works fine as long as we scope everything with ids. That sounds like stylis would work well in a situation where style sheets aren't shared between instances or rather, where every instance has its own stylesheet so that it can be scoped to the instance's unique id. @leeoniya Btw, here's what I came up with so far while experimenting with JSS: http://jsbin.com/doquhotecu/1/edit?js,output . This mostly illustrates my earlier points.
I'm not sure I agree with this one. People who choose a particular css-in-js solution probably do so because of the compiler semantics. If domvm forces styles through a mandatory prefixing pass that doesn't seem to be decoupling, but rather coupling domvm to the idea of using a css-in-js library by clogging up the code with stuff that is only relevant if people do use a css-in-js library. I see a place for providing prefixing in the css-in-js addon. I don't see anything wrong with choosing prefixing to be the default and recommended way to deal with disambiguation of css class names. It does make sense to provide a basic prefixing implementation that can run over any generated CSS. The thing that matters most in my eyes is that "domvm.css-in-js" provides a uniform interface that can be implemented by different css-in-js adapters (e.g. "domvm.css-in-js.jss" or "domvm.css-in-js.stylis"). Some adapters may need the prefixing code, others don't (e.g. jss doesn't need it because prefixing is trivially done by setting the |
Isn't the entire value of defining a RE stylis: I guess my main beef with stylis is that its input is one large stylesheet string. This requires ugly string concat in app-space to dynamically build/define the stylesheet. Tagged template literals would help here, but still lack the full expressiveness of js. It doesnt quite fulfill the spirit of css-in-js as a json-esque structure does; when i think "html in js" i don't want JSX, i want hyperscript. Likewise, css-in-js should be a "hyperscript for css" ( EDIT: JSS seems like the spiritual equivalent to JSONML, but domvm 2 ditches it for hyperscript. There's no reason not to want the same for css if it can be done non-grotesquely. You can even do stylesheet diffing/patching if you end up hanging on to the vcss, compression/mangling for SSR, auto-px insertion and vendor prefixing, etc....mostly matching the same semantics as hyperscript vdom libs. This would bring full uniformity in a codebase to "everything is js" - it may not be for everyone, but it's how i want to author. s(".foo, .bar > span", {
width: 100,
height: 100
}, [
s(".baz", {
color: "red"
})
])
s("em", {
width: 100,
height: 100
}) or to avoid app-space concat of multiple selectors via ([".foo", ".bar > span"], {
width: 100,
height: 100
}, [
s(".baz", {
color: "red"
})
]) this would allow any post-processing plugins to ditch their (probably buggy) parser, custom DSLs and operate on the vcss directly. |
You're right, that's the value. Doing the experiment, I just noticed that if there was an authoritative way for addons to run hooks for all views and to process the views, this might be a useful part of the addon architecture for domvm. My intuitition says that we can get a clean interface using little code just with an addon, as long as the addon has an easy way to register those hooks for the view. :) (My intuition may be off, and if addons aren't supposed to be able to "transform" views by registering hooks for them, it seems easier to do the integration in domvm itself, rather than in an addon.)
True. The point of the experiment so far has been to see how things look like if done manually in the naive way so I have something to improve on. (Please consider that I hadn't even heard of css-in-js before this thread brought it up.) I don't want to do things manually because repeating this on every view would be a major pain. There clearly needs to be something that encapsulates the annoying/repetitive parts and that shows a nice, minimal interface. One thing I very much agree with is that it's not desirable to leave everyone to do their own css-in-js implementations when there is so much that can be shared. Maybe css-in-js is to the core domvm like the router is to core domvm. It's something that many people in the domvm ecosystem may want to use. It does make sense for domvm to ship with something that gives out-of-the-box support for one css-in-js solution that is favored by domvm (either that or shipping with a minimal css-in-js solution, just a tiny bit larger in scope than the current version of stylis). It's probably a preference thing... when I pointed out how I had to manually add the onclick handlers for clicked links in 2.x-dev, I was delighted that I now have this fine-grained control over how clicking links inside my app behaves. You were quick to point out that you might want to add some explicit router support in domvm core. :) Feel free to laugh. In the end, I'll trust your judgement, because I'm far better off building on what you're making here than doing my own thing. I can see how having a few tiny pieces inside domvm core to properly support different things like routers, css-in-js, and whatever else comes up may be better than having an addon architecture that could result in people writing addons that interfere with each other. |
I'm not opposed to providing global mount/unmount hooks for addons to use, in addition to exposing the global I'm actually quite tempted to test out the
This is no laughing matter! 😆 |
@grumpi actually those global hooks are already exposed by way of the You should be able to do The only minor issue with this is that if vm-instance hooks are also defined by a view, they will replace [1] https://github.com/leeoniya/domvm/blob/2.x-dev/src/builds/pico.js#L18 |
That sounds like a great idea to me. I was just about to suggest something like that, but you beat me to it and your plan sounds a lot more thought out. I certainly don't want to write css strings, and the json structure of jss seems workable, but far from optimal. I've been doing okay with SASS, but it would be really nice for maintainability to place styles right with the components that use them.
I agree that this is a good idea. It's also simple to implement. So there's ideas for two separate modules:
Sounds like a plan. When jss is out of the picture, the cognitive dissonance resulting from repeating things that jss already does is gone. 😆
That's cool. I wasn't aware of that. :) Ok, good. Will see what happens tomorrow. |
just to clarify, i didn't mean you'll be defining style inside the render() template, as this would still be subject to mutation trans-redraw, so would represent view-instance rather than view-class definitions. i was just thinking out loud about the internal implementation of having it live as something like |
Not sure, entirely, of the practical upshot of all this, though I love the idea of styles bound with component all in JS; so in my experiments having a separate CSS file has been a thorn. It is, though, highly beneficial to preserve the ability of externally loaded stylesheets to override/customize the styles of any particular component, ideally without resorting to using |
No worries. That's clear. I'll be attaching styles to document head and detaching them from there again. Even for view-instance sheets, if I'm going to support them at all. There's no reason to treat them different from per-class sheets. I'll first try and see how my use case works out with per-class sheets.
That's the straightforward way of gluing them together I was thinking of as well. It just feels a little bit odd to be stringifying and then parsing again (to prefix). But I think that's better than the alternative of supporting css vnodes as input to the css-in-js addon. Edit: Hm... nah, I'd rather work on vnodes than parse, that's for sure, now that I've seen the chaotic mess css parsing is. 😆 @lawrence-dol I think we can do the same thing jss does: give you the ability to specify a comment in your HTML doc where the styles should go. Then you can place any stylesheets that override after this position. |
Hmmm. I don't think that will meet the need. This would be totally after the fact customization with zero modifications to the component code. Such as my current project which comes out of the box aesthetically pleasing, but basic, and which the customer can trivially supply any number of CSS files loaded from their area of the web site containing targeted overriding styles. Therefore, it's important that the two style sheets, mine and theirs, are at the same level in the cascade, or that theirs' take precedence. And this can't be done with user stylesheets because they don't control their customers' computers, so from the end-user's point of view, both at just stylesheets coming from the web server. |
Okay, I just looked up cascade. So, the problem is essentially that So the only way to override styles that are defined in Edit: Do you think using a |
In general, yes, that's more elegant and flexible. In this specific case, it's not a preference but necessary, because the only way to include their styles, unknown at the time of deployment, is to optionally reference them in header links, using filenames provided in the URL. Sucking the content of the customer's files into the document between two |
where to stick the generated styles is a good question. i think since all domvm styles will be scoped (presumabley they will not have side-effects) we can prepend them as the very first styles in it feels a bit backwards to have them exist before global resets like normalize.css, border-box, bootstrap, etc, but it should work okay in practice. i dont know if this arrangement is harder on the browser's css processing, but we can test this. |
Yeah, after some testing, the regex/replace prefixing falls apart pretty quickly and then you're headed for css-parsing hell. I guess it would make sense to expose a hookup for users to define some basics for prefixing to be handled externally. Here's my proposal: // hyperstyle node generator
var s = domvm.defineStyle;
// default compiler that supports domvm.defineStyle; this can be
// swapped by the user if another DSL & processor is used
domvm.compileStyle = function(style, viewName) {
// run some loop to prefix the vcss with .viewName and barf out a stylesheet string
return stylesheet;
};
function MyView() {...}
// set the style to the css processor's native DSL. in this case a hyperstyle vtree or fragment
MyView.style = [
s()
]; |
hooks patch landed: b2ccddb |
I found this: https://github.com/jotform/css.js/blob/master/css.js It seems to be doing what's needed from a css parser. I think there's orthogonal requirements and also orthogonal deployment situations: 1: deployment is in a pure JS project that you have control over A: styles don't change during runtime possible ways of authoring CSS in JS:
possible ways of overriding CSS with user-styles:
|
How about something like this: https://jsbin.com/punuxotoki/1/edit?html,output ? I went ahead and implemented an example of a Stylesheet class with automatic prefixing on css strings using the jotform parser. I think this only serves as an example. Let's do better than that. Authoring CSS strings in JS is worse than just writing plain CSS. 😆 The idea of the
|
Would it be sensible to have a named placeholder style tag. Any DOMVM styles go in that? |
I'm a bit busy ATM, but i'll review all this later today. I wanted to bring up a point that calls into question this entire topic and see what you guys think. View-scoped css cannot prevent styles from leaking into sub-views. This is of course the folly of "C" in CSS. But is it worth providing a solution that does only half the job by preventing leakage out? |
In this first sketch, I did the same thing jss does, i.e.
Adding a data-attribute or an id to the style tag that identifies the component which the styles are for is totally feasible. I added this in http://jsbin.com/bazuzodowo/edit?html,output With "a named placeholder style tag", do you mean one style tag that will hold all the styles for all the components, or do you mean one tag for each component? Please clarify. Both is possible, but the former could mean that we'd just append the component's styles to that style tag when it's mounted for the first time.
I'm aware of the problem with view-scoping. I think prefixing the actual class names is a more precise solution. E.g. turn
Styles that are inherited may still leak into sub-components, but the subcomponent can do a reset on its main node. (Whereas in the case of descendant-scoping(is that a good name?), the subview's own styles might lose a specificity battle against the parent component's styles.) |
In my opinion, the 'C' in CSS stands for a vulgar term referring to unwilling intercourse with a group of assailants. But we are stuck with it because our industry can't, as a group, design it's way out of a paper bag. They almost partly fixed this with the introduction of As a whole, we still haven't collectively recognized that the "specificity" rules aren't rules, but more guidelines for the partly-insane and savants among us. Add to this that the cascade refers to seepage of unintended side-effects that make even the most well meaning effort devolve into gibberish with 6 weeks of having been written. So we continue to pursue the heights of madness, ever courting danger on the brink of despair, in an everlasting effort, doomed to ultimate failure, to write sane, maintainable styles to control the visuals of an application, using tools designed to produce documents. BECAUSE THERE'S NOTHING ELSE. So yes, we should wrestle with this until we can do something better, or realize that doing the same thing using a different syntax is folly. (rant over) |
I had in mind the former, but the latter would be, if feasible and efficient, better.
This seems to be an intractable problem unless and until there's some mechanism to denote an element scoping boundary whereby CSS logically does a "revert to browser defaults here". But if all styles for a component are prefixed, a reasonable level of isolation should be possible. |
Oh, but CSS is such a terrific language, as long as you can keep the number of assailants (the sum of third party sources, third party users, and coworkers) at bay and practice self-defense skills. 😉
At what point of time would you need to see the placeholder tag? Is mount time of the component early enough, or does it need to be on document ready, when the component has loaded, or at a different time? What would you be doing with the placeholder tags? Would you want to kill them to eliminate a component's styles? Let your users replace the content with something they like better? I do think putting individual placeholders and filling them on mount (and whenever the style sheet explicitly changes during runtime) is both feasible and possible. It currently seems easier and more straightforward to me than putting one placeholder for all the styles. I don't know how high the cost would be in terms of performance. We'd have to look at how many components there are. If the number of components gets high, inserting all their placeholders using something like I suppose a
wouldn't work? Still, I think that it may be worth exploring the route of
The jss people seem to think so too (by default they're creating those wacky unique class names by attaching numbers, but they can prefix, too). I think so too. |
Ahh, no, there was another way to leak into subview styles. Parent styles:
Child has a
And loses against parent's more specific rule. -> coding convention: never use descendant selector. Better: use child selector. Again better: just give the darned thing its own class, if possible. Edit: I was jumping to conclusions too quickly again. Actually, the coding convention would be "never use descendant selector without a class selector (generic selectors, like attribute selectors and tag selectors are bad descendants)". Edit: In some cases, descendant selectors are fine. I.e. when writing a view that doesn't have a subview that styles could leak into. The other question is... is isolation between view and subview always desirable? |
The stylesheet impl looks pretty good. May want limit the usage of BTW, multiple function X() {}
X.prototype = {
constructor: X,
foo: function() {},
bar: function() {},
}
Probably not. We should avoid trying to do too much. Re: placeholders, I'm not sure this is a good idea. Prepending all prefixed styles to Re: multiple vs single SSR is still gonna be whacky if we're prepending styles to Drafted this a bit earlier... I guess if we're stuck with using CSS, we'll just hope that authors use something sane to avoid clobbering sub-view styles. Fully agree that descendant selectors are generally toxic and explicit classes are ideal (lately i like BEM [1][2][3]). However, child selectors force you to maintain a rigid stucture, which becomes a nuisance and a source of bugs during any form of refactoring. Keep in mind that adding classes to everything is gonna eat into your vdom performance (initial render moreso than redraw), it's a trade-off like anything else. I think the general idea of runtime-generated css is not gonna be a common case, so let's put hyperstyle aside for now and focus on simple auto-prefixing of user-provided stylesheets, which means we'll need a fast parser. CSSTree and mensch look like the fastest css parsers [4][5] excuding Styletron [7]. I'm able to get a minified mensch down to 7.55k (min). CSSTree is ~0.7k larger since its build process is not great, some regex duplication, etc. My intuition is that any parser that's significantly smaller will be deficient in some surprising way. I'd be interested to test [5] the performance claims of the one @grumpi mentioned [6] since it's about ~1k smaller than mensch. BEM: [1] http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/ Perf: [4] https://github.com/hellofresh/css-in-js-perf-tests Styletron: This thing seems like the ferarri of CSS with a resulting size & perf that's delicious - but impossible to debug...yet. |
If we want to barf styles in the head in SSR, we need to collect all the active sheets. That's true. All that's needed is to go over the vm registry to extract them all. The css-in-js addon should provide a function to do that. Don't think we need callbacks or anything fancy.
When a Stylesheet attaches for the first time, we can check if a style element for it already exists and claim it, if it does exist. As long as the style elements are outside of the part of the DOM that is controlled by domvm, this naive approach should work just fine. Nothing to rehydrate on domvm's side.
Ahh, but the point of hyperstyle isn't runtime-generated css. It's having a sane language to write CSS in.
If we're not in the business of runtime-generated css, prefixing can be an external build step instead of "compiling" at runtime. So we could use any parser we want to. :) If a website consists completely of static content, the idea of making a Single-Page-Application written in JavaScript rendered by the client's browser is pretty nuts, do you agree? By the way, to get prefixed class-names, we don't even need to walk over the vnodes to adjust them. We could also do something like this:
(This is the same that jss does: providing a way to look up the generated class names.)
The comparison with a ferrari is pretty good. The lack of back row seats (in this case, the complete lack of child/descendant selectors means that hover styles need to be done in JavaScript) can be rather uncomfortable. Other than that, I like their idea of breaking up things into small composable pieces. Edit: Actually, something like Styletron could work really nicely for my use case - if there was a way to do hover styles and animations with child or descendant selectors. Maybe we should look at the things we want to achieve. Looking at the hyped things others are doing is fun but also leads us away from a possibly-existing simple solution to what we really need. I...
Most of what I think I need has to do with improving the usability of maintaining CSS, not with performance, and not with doing things a "modern" and "cool" CSS-in-JS way just because we could. |
I dunno, this whole thing is starting to seem like a [worse] solution to a mostly-solved problem, for little added benefit. If you have even a moderately complex system, let's face it, your time is more valuable than the investment into adding some lightweight build process that includes SASS. To prefix in SASS is so easy a 5-year-old can do it. If you also adhere to BEM, then you're in even better shape. The scoping & repetition issues are now gone. Point 3 needs some clarification:
In what specific non-contrived cases would this justify adding extra API surface. Point 4.
sure, keep them wherever you want.
if you mean at per-view-class level, we can just expose the view registry and your ssr backend can figure out what's mounted and only include those stylesheets. though this seems pointless since new things can mount later on the client. there could be some case for using i'm gonna need some solid common-case problems that this entire thread solves to justify inclusion into the lib (added API surface, code maintenance, tests, docs). it clearly can be done as an external plugin, perhaps it should stay this way. i'm against anointing some specific CSS parser and sucking it into the lib to pair with this feature. it's true that a |
Kind of. The question is what exact problem is left that runtime-inserted/compiled style tags are solving? 😆 That's why I figured we better back off and consider what we actually want.
Can't argue with that.
I had intended this to represent a point for domvm not providing any support for runtime-generated css. Sorry about the confusion. People who need runtime-generated css can just use one of the existing css-in-js solutions (they all come with their own code for inserting/removing style tags) or roll their own (I mean, I currently effectively do my run-time generated css by computing some values, inserting them in the right places in a stylesheet string and slapping that in a style tag).
I was more thinking along the lines of what https://github.com/purifycss/purifycss does (I didn't know that purifycss existed before I just stumbled upon it while searching for existing solutions a moment ago). Just something that lets me know when I'm never using a css class. But since someone already solved that, I suppose I'm covered. I think now that a workflow that fits my needs probably looks like this:
I think that describes it well. Hyperstyle could be an alternative to SASS and allow easily manipulating styles in JavaScript. It would make runtime-generated styles more convenient. I think you're right it's probably not worth to invest the effort into creating and maintaining it; there's so many people making these small css-preprocessors and css-in-js libraries these days. I'm pretty sure there must be something in the haystack that will do. :)
I've been saying it should be an external plugin from the start. 👍 So, totally agree with that. |
let's close this then. thanks for your input, guys 👍 |
Ok, I finally understood how a sane way to use css-in-js goes: Development:
Build:
How to efficiently do styles that need to be customized at runtime: Use placeholders in your generated CSS. E.g.
Postprocess the CSS to separate exactly those declarations which contain placeholders. With https://github.com/mrnocreativity/postcss-critical-split, one way to do this is:
Result:
Insert runtime-computed values into Random comments:
|
lol thanks, i needed that today :D let me know how styletron works out, specifically the debugging experience. |
So far, I can just say that the "flat" way of authoring CSS (no descendants) seems to have more upsides than downsides. Compared to writing SASS, there is much less I need to keep in my head: no need to think about what to I wrote a little wrapper so I can write styles this way:
I've mostly been porting over existing styles. Still have to port the parts of compass-vertical-rhythm that I use, and a bunch of other things. Can't say much about debugging yet. I do set the style identifier as class name on the node in development, next to the styletron-generated classes, so I can easily see where in my code I have to look to find the style definition I might need to change. I suppose I could also put this into a data-attribute or somewhere else, but, since my style identifiers are extremely unlikely to clash with anything, I just put them there. I also run the generated CSS through https://github.com/stylelint/stylelint, but I haven't found an option to make it check that the generated CSS is truly valid. It does help with catching some things, though. Just did a quick search for a validator, and it looks to me like the simplest way to get good warnings is to run the generated CSS through the w3c validator (https://github.com/gchudnov/w3c-css). |
Now that view closures can return
{render: ...}
objects, we should evaluate offering the option of returning{css: ...}
as part of the mix, possibly accepting a JSS-style [1] stylesheet definition. Each vm is already tagged with a globally unique sequential.id
, so the styles can be prefixed to isolate/prevent leakage. Another option is to prefix the defs with thefunction.name
of the the view closure. This means all views created using the same closure would by styled uniformly. In both cases the view's root nodes would need the generated prefixes auto-appended to their className.JSS pairs well with vdom/hyperscript style libs since it's js-assembled CSS, much like like js-assembled DOM.
This would make for a good isolated and high-ROI project if anyone wants to take charge, since it wouldn't require intricate familiarity with domvm's internals. 98% of it can live decoupled as an addon.
cc @grumpi, @yosbelms, @lawrence-dol
[1] https://github.com/cssinjs/jss
The text was updated successfully, but these errors were encountered: