Open mdgriffith opened 7 years ago
As long as two stylesheets are based on the same union types, they can be easily merged
I would expect each stylesheet to come with its own union type. When I'm working on a module, I only want to work with styles related to it directly. If I'm defining 10 classes in a module, but there's 50 classes defined elsewhere (based on the same union type), how I can be sure which parts of this union type actually belong to the current module and which parts elsewhere?
I was thinking it would be possible to merge any two stylesheets, this would allow building a stylesheet tree which would reflect a module hierarchy (or simply a list). stylesheet.class
, however, will stop working with this approach. Perhaps we need two data types, e.g. Stylesheet
and StylesheetGroup
?
Alternatively, we could just define classes independently from each other, e.g.:
title = class "title" [
width (px 300)
, height auto
]
use them in DOM like this:
div [ title.class ] [ ... ]
group into stylesheets like this:
stylesheet = Style.render [ title, main, ... ]
then merging becomes as simple as:
mergedStylesheet = Stylesheet.merge [ stylesheet1, stylesheet2, ...]
and rendering stylesheets stays the same.
In regards to mixins, I'd like to see some examples of common mixins that people use. From my experience, it has always been possible to avoid mixins altogether:
For organizing the master union type, you could easily break it up into sections.
type MyClasses
= Nav
| Button
| MyOtherStyles OtherStyles
-- in MyModule.elm
type OtherStyles
= Widget
| CatPortrait
You could support that with a special merge function as well. Something like:
Style.merge MyOtherStyles myOtherStylesheet
, which would just map MyOtherStyles
to all the classes in the sub-stylesheet.
I'm also playing around with being able to generate/maintain this Union type via the elm-style
CLI. We'll see if that makes sense at all.
So, the advantage of the independent function based approach that you suggest is that it avoids having to maintain a union type. However, it makes something like hash guards mandatory and requires you to manually add each style definition to the stylesheet.
I'll see if I can put together some examples using the semantic grouping method I'm proposing.
How did this work out? Did you get around to creating those examples?
After some discussion, it's become apparent that addressing high level style organization of styles s pretty important for this library.
Mixins
Mixins are fascinating because they've become standard to css preprocessors. On the one side they allow you to capture commonly grouped style properties. On the flip side, reliance on them leads to an extra level of indirection.
A style class composed of multiple mixins is harder to debug because you have to go to many places to figure out where the bad interaction is happening. Changing a mixin is also challenging because you'll have to verify that the change you're making works with every class that uses that mixin.
The power of mixins relies on the insight of the CSS creator. This library is focused on not relying on developer expertise to create a good stylesheet. We want that baked in, just like Elm bakes in so many best practices.
Option 1: Remove Mixins
This is a real option. However, I believe both the positives and negatives of mixins are valid. This eliminates both, so I'm not sure if it's the way to go.
Option 2: Semantic Mixins
One of the root causes of mixins being a pain is that you have no idea what properties you're bringing in. Whenever you declare a mixin, you can bring in literally any set of css properties, including child selectors.
Semantically grouping style properties provides a potential solution. What if the only mixins that are allowed are based on these groups? Here's an example of a semantic mixin:
Why is this more powerful?
The class using the mixin knows exactly the type of properties coming in.
The actual mixin has all the information needed to avoid bad interactions. Color only cares about other colors. This does rely on getting the grouping correctly, which is covered/discussed here.
Merging Smaller Stylesheets
It's fairly common to want a few different small stylesheets instead of one large one.
As long as two stylesheets are based on the same union types, they can be easily merged if the library provides a function like
Style.merge
which would allow you to embed a stylesheet in another one.Some sort of check/warning when you forget to embed a stylesheet would be really nice. Not 100% on how that would work though.
Something like
Style.merge
might also create an opportunity for "auto-embedding". I don't know exactly how this would work, but the gist would be to pass styling information along with the Html you're rendering, and then have the root element merge all stylesheets into one. I've played around with this before and the issues I ran into were in implementing something likeHtml.Keyed
andHtml.Lazy
. However I'm willing to revisit!