Creating an issue to track our discussion in Slack. I will continue to update this issue as more ideas arise.
Fallbacks keep things clean var(--some-var, 4rem);
Complexity
Other frameworks have had issues maintaining variables
http://jxnblk.com/writing/posts/rethinking-variables-in-css/
Thanks for kicking this off. I'm new to all this so bear with me if my questions are silly.
@samselikoff I can't answer your first question - but I can attempt to answer your second question.
While variables may seem simple to you - they are often not for beginners. It's an added layer of abstraction. Say you are looking through source code and you see:
.bg-red {
background-color: var(--red, red);
}
There are multiple things here you may or may not have seen. The syntax for declaring var, what does the double dash mean? Is that a requirement? Or was that an author choice to put a double dash there?
What is --red set to? Now you need to go find the definition of red. So you go find that (which can be non-trivial to do for some new people). Then you decide to change it, but you don't know what else uses --red and now you need to look that up to. Now again, this all might sound simple for an expert like yourself. But what value does the variable bring? And at what cost? To me variables in css are often just hacks to supplement peoples lack of ability to edit text efficiently - and are ripe for messiness in any system where multiple people are touching front-end code. Contrast this with the simple and clear
.bg-red {
background-color: #ff0000;
}
As a beginner you might still have questions. What is this weird code? Do I have to have a pound sign?
But it's closer to the metal so to speak. css is just css. But memorizing various syntaxes and understanding how variables are utilized and tie together to other classes is an additional hurdle for some. And this makes me hesitate. In my 9 years of working with variables in css I have rarely if ever seen them solve more problems than they create. Tachyons is a personal framework for me - and one of my goals is to be able to collaborate with experts and beginners a like, in a system that suits both their needs. This is a lofty goal for sure, but much of tachyons is the result of user testing both groups and observing in real life how people consume css. And these are some of the best patterns I've found so far. In my user testing though, time and time again I've seen both experts and beginners struggle with pulling apart how the variables are used and what consumes them. And I haven't seen it speed up peoples workflows. I've often debated just ripping out variables all together. So this whole conversation is making me wonder if I should have a variables version and a non-variables version. Because if people want variables - i'd like to make it easy for them to get up and going and configure certain things for sure. But I have also witnessed the complexity that it introduces. You are correct in that the end API is basically the same. But I do think it adds a completely different layer of difficulty for beginners on how to quickly parse the class and understand what is going to happen.
Just my two cents on the matter. Please let me know if this doesn't answer your question.
Thanks for your thoughts. I think with a library like Tachyons one of the first things people will reach for is the ability to customize, e.g. the scales. I personally like the constraints of only being able to choose say 6 font sizes, and knowing I can alter them for my project, but only getting 6. I feel like that's Tachyons nudging me towards good architecture, but not boxing me in, since it's letting me customize.
The point is you should end up with a set of Tachyons suited specifically for your project. Variables seems the best and most natural way to me to achieve this. Of course, I don't have nearly as much experience as you, nor have I done any user testing ever. I just know that as a user of a new CSS library, one of my first instincts will be to try to customize it by seeing what variables the library uses, and changing them (especially when scales are involved).
Hey, not a problem, @samselikoff. @mrmrs and I have been discussing this topic for quite a while (months 馃樃 ).
Why fallbacks, instead of variable defaults?
The only reason I lean towards fallbacks in place of defaults as I think it will be more straightforward, as we want this to be as beginner friendly, though I could be entirely off base in this regard. If we incorporate variables I'm fine going with either implementation.
I don't see how this makes tachyons more difficult for beginners. If the variables have default, isn't the basic API the same?
Yeah. I agree with you on this point. Especially since variables are already used in the spacing and skin modules. Continuing in this fashion seems intuitive and consistent.
One of my favorite things about Tachyons is the ability for newcomers to get up and running with it. The CSS itself is simple and efficient. However, I do wonder if we are overemphasizing this when it comes to the source CSS. I'd anticipate that the beginner CSSer (please correct my if my assumption is wrong) would be using the built CSS rather than src, and when it comes down to it, the source is just that -- the source. We already use a version of variables for custom media.
I agree with your points, @mrmrs, that variables are often used for bad things and undoubtedly introduce another layer of complexity. I also think that the architecture of Tachyons limits this substantially as variable changes won't propagate to seemingly unrelated declarations (the Sass effect). If we point users to the built CSS, they won't have to know about the existence of variables in the source CSS. This is exceptionally viable for those that consume Tachyons via a git clone or directly editing in node_modules. Unfortunately, not all of us will consume Tachyons CSS in that manner.
The key pieces to the implementation are:
node_modules/ with PostCSS/webpack/build tool du jourWith this, we're never editing the source CSS for Tachyons, and install via npm to help facilitate library updates (ends up being more efficient and elegant than copy pasta-ing as a consumer). Imagine a scenario where we're a given design has a slightly different type scale or measure widths. Without variables, one has a couple options:
.my-f1 or .my-measureThe first approach isn't desirable because this requires additional classes and their own documentation. The second approach isn't exactly "functional", and is an unfortunate way to handle the need for 2.2rem rather than 2rem. After all, we're using Tachyons so there's no need to write more CSS, I'm lazy af.
I definitely understand if my use case isn't the norm, and we can step around things if necessary. Creating a tachyons-vars library that contains more customizable variables would be a perfectly adequate approach.
Though, for consistency's sake, it seems like if we look to not include variables for certain things like typescale, we should also remove them from spacing (IMO). Otherwise the distinction between what modules have variables and which don't seem sort of arbitrary. As, anything with color or scale should be handled similarly.
Ultimately, @mrmrs, you're the BDFL of Tachyons CSS (I just do the JavaScripts : )), and your decisions have always been better for my stylesheets. It's like you know something I don't or something 馃殌 馃摗 馃寱 . So, I trust whatever your decision will be on this. I seek to provide a bit more context on my use case and why I lean towards using variables.
馃懐
I agree with your thoughts John. Adam's writings and the Tachyons library have been my introduction to functional css over the past few weeks. As I've showed the library to my colleagues, the first thing I explain is how functional css brings constraints, and why this is a good thing. We install Tachyons (by copying the built .css file), and start building out mockups. It's awesome that we can build custom designs using only css classes from a third-party library.
Then, we need a class that doesn't exist, or we need to modify a scale. We don't have PostCSS in any of our apps at the moment - most of our apps have the ability to work with Sass. They ask if we're supposed to customize things at all, or if we're supposed to stay within the boundaries and scales that Tachyons come with. I explain that no, the author explicitly says the library is meant to be customizable. But, the lesson is still important - you don't go making just _any_ class you want, you stick to a scale and incorporate that into your design. More consistency, fewer decisions, etc.
At this point, if we were able to crack open a variables.scss file, or even look for variables at the top of a source, this would be really helpful. In our Ember apps using Bootstrap, we do it like this:
// app.scss
// Customize Bootstrap
$brand-primary: red;
@include 'bootstrap';
That gives us customized Bootstrap, and I think it's great. We still work within the constraints of the lib, but we're able to override defaults.
I think this is the convention over configuration argument. Ultimately, there are a lot of decisions made by Tachyons about class names, scale names and the like. These decisions don't affect things one way or another, and I'm glad Tachyons has made these decisions. I think it's good if other teams' projects can leverage them, to stay on board with the community, and to be more productive. But as with any conventional library there does need to be an escape hatch for when the defaults don't line up.
We use variables with fallbacks in production with several different customers. They've been useful for configurability from customer to customer allowing us to quickly change the branding to fit each customer's needs.
However, we take this to the extreme. This may be deemed as overkill and pointless, but after testing we ran into issues during the Bamboo's build and deploy leaving some things unstyled or broken. Since our client's assets/config don't live in the base project we have a set of default variables that live in base + client variables for each customer. This setup means that regardless of the client's config their site won't ever be broken or look too out of wack.
In short, we use variables as a fall backs as well. This only adds more complexity, but has been useful for theming, changing fonts, and even for different page layouts. Here's an example:
--link-color : var(--client__link-color, var(--default__link-color));
--text-color : var(--client__text-color, var(--default__text-color));
--text-muted-color : var(--client__text-muted-color, var(--default__text-muted-color));
I'd like to add on to @johnotander's comments. The issue with overriding or defining your own classes after importing tachyons is that it breaks responsiveness. Say we want to change .f4 from font-size: 1.25rem to font-size: 1.125rem, we would do something like this:
/* from tachyons: */
.f3 { font-size: 1.5rem }
.f4 { font-size: 1.25rem }
@media (--breakpoint-not-small) {
.f3-ns { font-size: 1.125rem }
.f4-ns { font-size: 1.125rem }
}
/* my overrides: */
.f4 { font-size: 1.125rem }
@media (--breakpoint-not-small) {
.f4-ns { font-size: 1.125rem }
}
If I have a <div class="f4 f3-ns"></div>, the .f3-ns no longer overrides .f4 because .f4 now appears after .f3-ns.
Then we're left with editing the source directly which makes bringing updates from upstream more difficult.
edit: Seems like https://github.com/hail2u/node-css-mqpacker would fix the issue by forcing the media query to the bottom
[Edit 7/10/2018] The "f7" class specifically has been implemented and my individual issue is resolved. I cannot agree more about it's lack of readability... still, some projects will dictate ant font sizes it seems.
Experiencing the same issue as @kentor ; my media queries don't do their thing with my mobile-first custom "f7" to default tachyons "f5-m". Has this been resolved elsehow/internally (w/o using node-css-mqpacker)?
We have several flavors of tachyons that use variables for those that desire them. Outside of colors going to refrain from using vars in the main repo.
Most helpful comment
I agree with your thoughts John. Adam's writings and the Tachyons library have been my introduction to functional css over the past few weeks. As I've showed the library to my colleagues, the first thing I explain is how functional css brings constraints, and why this is a good thing. We install Tachyons (by copying the built
.cssfile), and start building out mockups. It's awesome that we can build custom designs using only css classes from a third-party library.Then, we need a class that doesn't exist, or we need to modify a scale. We don't have PostCSS in any of our apps at the moment - most of our apps have the ability to work with Sass. They ask if we're supposed to customize things at all, or if we're supposed to stay within the boundaries and scales that Tachyons come with. I explain that no, the author explicitly says the library is meant to be customizable. But, the lesson is still important - you don't go making just _any_ class you want, you stick to a scale and incorporate that into your design. More consistency, fewer decisions, etc.
At this point, if we were able to crack open a
variables.scssfile, or even look for variables at the top of a source, this would be really helpful. In our Ember apps using Bootstrap, we do it like this:That gives us customized Bootstrap, and I think it's great. We still work within the constraints of the lib, but we're able to override defaults.
I think this is the convention over configuration argument. Ultimately, there are a lot of decisions made by Tachyons about class names, scale names and the like. These decisions don't affect things one way or another, and I'm glad Tachyons has made these decisions. I think it's good if other teams' projects can leverage them, to stay on board with the community, and to be more productive. But as with any conventional library there does need to be an escape hatch for when the defaults don't line up.