The best part: it gives you a consistent spacing [0] and a consistent font scale [1] which is relative to rem. No more magic values, just use classes:
ma0 ... ma7 margin: 0|0.25|0.5|1|2|4|8|16 rem
ml|mr|mb|mt [0-7] marginLeft, marginRight, marginBottom, marginTop
mh [0-7] marginHorizontal
mv [0-7] marginVertical
/* Same with p for padding */
No more stylesheets, everything is there at a glance and easily fixable:
<View cls="bt bb jcfs pa2"> /* border at top and bottom, justifyContent: stretch, padding: 0.5rem */
<Text cls="white tc"> /* white color, text-align: center */
Something
</Text>
</View>
This way, MyTachyonsComp can now has all the benefits of styled-components (easy theming and overriding, power of JS for styling, ReactNative, nesting,…) while also being able to use tachyons really easily:
<MyTachyonsComp ma2 ph2 bb />
In fact, you could probably even wrap the above helper to make it really easy to use:
It's a JS library that you provide a configuration object and it generates your type/spacing CSS. I love Tachyons and am planning on building a plugin for Typography.js which will generate tachyon-like classes.
You can use it with css-in-js libs like styled-components as well. It exports two helper functions, "rhythm" and "scale".
"rhythm" is a virtual unit that's the distance of one line-height. All spacing within Typography.js are based on it. Using "rhythms" for other spacings on your site ensures everything stays consistent as you make styling tweaks.
"scale" is a function to pick font sizes off the scale you setup (with scaleRatio). This let's you tweak the body font size and all other font sizes will move along with that.
Tachyons' main-purpose is not abbreviating inline-styles, but providing the developer with a consistent and scalable layouting-system for spacing and typography, which, at the end, is what arrives at the user.
If you love your inline-styles you can keep them and use tachyons just for the scale:
For anyone unfamiliar with the syntax used to achieve this, it's called Tagged Template Literals [0] and it's part of ES2015. You have a function that receives the static strings and interpolations and can return anything you want.
One of my favorite uses of tagged template literals is for HTML-encoding variables into an HTML string with (my module) https://www.npmjs.com/package/auto-html.
I think using strings as an API is a step in the wrong direction. I like that it
produces a React component directly though.
We experimented with styling approaches for React a while ago and produced our
solution — React Stylesheet[1], which we used for over an year in different
React applications.
It also produces components out of style definitions directly:
Which you can use like any other React component later:
<GreenBox />
As you can see the API is kinda similar but uses JS instead of CSS string. What
are advantages? The following:
* Consistent syntax: you can use functions, variabls, mixins, w/o the need for
interpolation `${...}`.
* Tooling. This is big one. You can make your stylesheets linted with ESLint and
typesafe (!!!) with FlowType or TypeScript.
FlowType is supported out of the box, see [2]. Typesafe stylesheets is a huge
win for productivity, I constantly catch typos and invalid values via Flow.
What is the performance penalty of using generated styles on every render?
As far as I can see from the source code, React will have to modify `<style>` tag every time a component is being rendered.
I still think the best way to handle stylesheets is with external css file ( doesn't matter how it's generated. I use CSSModules ) and then add static class names for those components.
We've tried styled-components in medium-size projects (50-500 components) and haven't noticed any performance-hit yet. That being said, it's definitely something we're conscious about.
That's why we will be writing a babel transform that grabs all the _static_ styles and extracts them into a separate stylesheet! (just didn't have time to do it until ReactNL where I just announced it)
1. It uses the `style` prop, which modifies the CSSStyleDeclaration object on the DOM node. The style attribute gets set by the browser behind the scenes. [1]
2. The rendering happens on the server, and React produces the markup for the style attribute. [2]
The former approach has very little overhead. The second bears the overhead of having to be parsed.
In most libraries, this is what gets used. Some libraries try to be clever, though, and inject `<style>` or `<link>` elements into the DOM (mostly to support things like `:hover`). This can get extremely CPU intensive, though, and it's not uncommon to get burned by a library in this way.
After Reagent + Hiccup, I'm ruined. Nothing feels as natural as a full, general-purpose language (Clojure) combined with a natural keyword-based DSL for styling:
With components I think we are taking a step back from semantic HTML elements, where style is applied by a separate template. And business logic is also separated from the layout elements.
The cutting edge of front-end development has been arriving at ways to split business logic from layout elements for some time now.
Redux, Om, Reframe, Elm, etc. They all amount to hooking up components to a state transactor where the business logic lives separately.
Semantic HTML seems like a trade-off where you clean your markup at the expense of indirection, not a universal aspiration. And components don't dictate where your styling should live.
Interesting. What warrants a for CSS Modules co-location? Is it just because you can't write it in the same JS file as your component?
I'm also super duper skeptical of style interoperability between React Native and the browser. From experience styling in React Native suffers from the uncanny valley - its so close to browser CSS, but ends up failing in rather significant ways (mainly layout) that would prevent style reuse.
It's less about interoperability and more about using the same styling system for_all_ parts of your application. Styling on ReactNative is different enough to have to be careful when doing it, though theoretically it's very possible.
Note that while CSS modules doesn't provide an out-of-the-box solution for themeing you can use css variables and then either just swap out the variables (if you only target browsers that support the custom properties spec) or run the CSS through postCSS.
The important difference however is that CSS-in-JS can swap out themes on the fly whereas this would be a static solution that doesn't scale e.g. if you need per-user customization.
> if you only target browsers that support the custom properties spec
That "sidenote" is exactly why vanilla CSS has a "Kinda" for theming. Taking a look at caniuse[0], only 66.39% of browsers have support for custom properties – not exactly production ready.
That being said, once custom properties are well supported they're an amazing solution for theming! Take a look at this talk Glen (the co-creator of CSS modules and now styled-components) gave at JSConf BP for some hints towards this future: https://www.youtube.com/watch?v=XR6eM_5pAb0
IMO PostCSS is a workable solution until that number gets closer to 100%. It just requires the aforementioned post-processing step per theme to "render" the stylesheet with the correct variables:
The huge downside with inline styles is that they don't support all of CSS _at all_. You have to reimplement basic things like pseudo selectors (hover/active/focussed/… styles) and things like pseudo elements, media queries, keyframes are non-existant. On top of that, for the eventual global style you need (e.g. @font-face) you now have to add a separate build step for actual CSS to add that.
We have a language on the web that's made for styling. It has support for all those things by default. It's called CSS. Why not use it?
Can I forward you to these four resources? (I realize this might sound like a cop-out answer, but these people have summed up the benefits of CSS-in-JS so much better than I could in two minutes!)
[0]: Rendering Khan Academy’s Learn Menu Wherever I Please: Documenting the move from the handlebars + less combo to react and css-in-js, and why KhanAcademy did it
[1]: My thoughts on Inline Styles: A great collection of both pros and cons about styles in javascript. Most of those doubts we've tried to solve with styled-components
[2]: "Scale" FUD and Style Components: Using components as low-level styling constructs
[3]: Ryan's random thoughts about inline styles: Explaining some benefits of using styles in js
BONUS
[4] The Future of Reusable CSS: How component libraries should be styled, and why they're not yet
Real projects in the future may be! Because the current one involves a lot of components and I don't think this would be scaling well as it's gonna rerender the styles multiple times.
Sorry, how do you mean "rerender the styles multiple times"? The only time any styles ever change is if one of your interpolations changes, but otherwise we don't do much calculation at all!
That being said, there might be a performance impact in massive (1000+ components) applications. We've tried it in medium apps, and haven't seen any performance impact yet. We're also going to build a babel transform to extract the static styles to get even better performance. (see https://news.ycombinator.com/item?id=12700280)
Hmm yup I mistyped that. I was a bit worried about the performance because the app is a multi tab grafana like dashboard with real time data. I'll try by modifying components that dont change often. Will measure and go up from there.
It isn't "implemented" – it's just CSS! Literally!
(Note: Almost the sole thing we do to that CSS before injecting it into the DOM is adding a hash of the contents as the selector. Not sure if that counts as "implemented"?)
I very much realize that, which is why I've been pushing towards people recognizing this because it _does_ make a huge difference! (as seen by the OC that kicked off this discussion)
Apologies, didn't see your reply until now.
IE11 behind the company firewall, I can see a rather short set of complete HTML in the source but nothing is rendered. Sorry I can't offer more information.
The best part: it gives you a consistent spacing [0] and a consistent font scale [1] which is relative to rem. No more magic values, just use classes:
No more stylesheets, everything is there at a glance and easily fixable: [0] http://tachyons.io/docs/layout/spacing/[1] http://tachyons.io/docs/typography/scale/