I've really enjoyed using jxnblk's approach to styling. I started with basscss [1], then moved on to rebass, and finally settled on axs [2]. They all take more or less the same approach, but operate differently. Rebass generates inline styles; basscss is simply a CSS file that defines a set of utility classes (like `mb2`, `p3`, `flex-none`, etc.); and axs dynamically generates CSS classnames and stylesheets.
...Or at least, that used to be the case. Looking at the most recent version of rebass, it looks as if it uses the same dynamic classname/stylesheet generation strategy. Now I'm not so sure what the difference between rebass and axs are, except that the former seems to be a comprehensive set of UI components, and the latter a tool for generating your own component library.
In any case, I'm glad jxnblk keeps experimenting with these libraries, even if it's hard to keep up with the changes. Their surface area is so small that it's easy to pick up the API and it doesn't feel like a risk or burden to stay on older versions.
Similarly, I've been enjoying JSS[1] a lot... it works similar to inlined, but under the covers it creates classes per component and renders to styles... can pre-render via server pass too.
Yeah the newest version of rebass uses styled-components[0] under the hood which does the same thing as axs does. (generate an actual stylesheet with classnames)
I first encountered this with tachyons. It takes some getting used to, but it winds up feeling alright once you do. Maybe that’s just for folks who like fewer keystrokes, though. Admittedly, it’s not the easiest thing to approach cold.
In fairness the code is live-editable and so you can figure out what it means by changing it and seeing how the output differs. (mb means margin bottom).
I understood the OP as saying they couldn't figure out what "mb" meant because the author didn't define it in the text. I noted that there was another path to figuring out what it meant, by changing the live-editable code and seeing what it does.
Having a live-editable example is certainly nice, but you shouldn't have to fiddle around with a parameter to see what it does. It should be clearly documented so that you know what to expect and what the intention is. Otherwise, the behavior that you observe could be a bug for all you know.
Its also useless for discoverability. Sure, you might be able to figure out some code you read in an example through trial and error, but you won't learn what's actually available.
If the rebass approach to css is interesting to you, i recommend checking out tachyons.io
It plays nicely with React as well. Sadly most of the discussion around Tachyons is hidden away from the web in a burrow of Slack channels, but it's an active community and there's a lot of help and show+tell to be found.
Didn't dive in too much yet but heads up that your hero animation is a bit funky in Chrome (stable). Here's a screencap: https://cl.ly/0D031Z0p3v26. The glitch happens towards the end of the recording.
I do really like a lot of things about the styled-components approach and general CSS in JS approach.
I do though have a few concerns that stem from loosing the abstraction of ascetics vs function of a component, mainly though - ease of designer collaboration;
It seems harder to have a designer collaborate on your styles. (Maybe they are more used to CSS more than JS, or an external contractor, or just more specialised etc). You can't have somebody change your design without them having full access and knowledge of your entire component source and architecture.
I notice that styled-components can automatically generate a style sheet with nice names, it would be good if this could be a step at build time. And maybe a step that can also reverse the process? adding any changed styles back into your JS files? (syncing it with an externally edited stylesheet) Does anyone else see value to this?
Why the hell are we now putting CSS in Javascript? I'm losing my mind with web developers trying to control everything in the world with client-side javascript.
Styling with JS is simply a much better experience than using stylesheets.
Like it or not, styling often changes in accordance to changes in the application state. Instead of reacting to state changes by appending/removing class names, you can remove much of the friction by making style a part of the application state and changing style directly when the appropriate state changes.
By using inline styles exclusively, styles are now completely local and isolated by default, and can never have any unpredictable cascading effects throughout the rest of your app. We simply cannot understate the importance of this guarantee of isolation in a component-oriented architecture.
We also gain all the facilities we might possibly need to programmatically manipulate our styles since they're now just JS objects, without having to resort to the clunky DSLs offered by preprocessors like LESS and SASS.
Last but not least, we can enable far more granular style reuse using plain JS objects by leveraging the excellent built-in ES6 module system, and automatically benefit from module optimization techniques in advanced module loaders like Webpack to remove unused styles in production.
Only real downside of inline styles is that they're a subset of real css, and are not as expressive. Goodbye using pseudo classes like :focus, :active, etc with just the React 'style' object. And for things like designing input components, they're really important. You could hack around this by maintaining component state (e.g., flipping a boolean for mouseEnter and mouseLeave to emulate :hover), and use the boolean within your styling logic, but that is pretty hacky.
Note: The library rebass uses, styled-components, doesn't use inline styles. It takes your styling and injects it as an actual style.sheet with automatically generated class names! This means you have the full power of CSS at your fingertips without having to resort to component state for e.g. hover.
See this article for more information about the difference: mxstbr.blog/2016/11/inline-styles-vs-css-in-js/
You are missing the point. Forget about client vs server, the idea is that in React you are working with components.
NOT putting component-local styles into the component's implementation is a mistake, and is equivalent to creating a cluttered global namespace with lots of stuff you shouldn't touch because the component expects it to work a certain way.
The right way is to let each component accept style props that the consumer is supposed to be able to change, but to keep the rest of the component's implementation private.
The idea of encapsulation is pretty basic in software engineering (functional and OOP) but for some reason people fail to realize that what makes components useful is that they create an encapsulation boundary that should reduce the cognitive load of using the component.
While I don't necessarily disagree with the benefits of encapsulation - not even native Android applications behave this way. What are your thoughts on that system, and is this simply because CSS is unreliable, or is your stance that this should always be the case?
What happens when I want to change every button from green to red? Does that happen in one place, or now many?
> What happens when I want to change every button from green to red
If you have a component that you maintain, it can depend on a global style definition that is itself a module. You can change the color of the button in that module.
If you have a component that you do not maintain, then you may look at the implementation of that component and change something that is currently "blue" to "red", but how do you know for sure that the maintainer of the component may not have something in mind or may choose to refactor that code or change the naming convention?
> is this simply because CSS is unreliable, or is your stance that this should always be the case?
My view applies to any approach to code that benefits from a distinction being drawn between a public and private interface. Generally, these are scenarios where the person or team maintaining the component may be different from the person or team using the component as a part of other code. The public interface is meant to be stable and behaves like a contract between the author of the code and the person using it. Semantic versioning is about declaring that public interfaces are or are not stable from the previous version.
If we put our styling code (usual data literals of some sort) into the global scope, but we plan to use conventions established by a component's author as our own convention, we risk the chance that the component's author may change something that we are depending on. The logical separation of styling code that is an implementation detail is what is important, not where in the codebase the declarations reside.
If a component author determines that the user of that component should be able to change style attributes a,b,c,d, and e, then those should be explicitly handled as part of the public API and the values passed to them (and whether they are required for proper functioning of the component) should be defined as well.
This is just good component hygeine. It helps insulate the consumer (person using the component in her own code) from having to read the component's source code to see how the implementation works simply to add styling information.
This is what Shadow DOM and CSS Custom Properties are for: Let the browser encapsulate styles, with both upper and lower bounds, and let specific values inherit through the encapsulation boundary.
I thought progressive enhancement was gospel until app complexity exploded. I thought JSX was an abomination. I was wrong.
CSS Grid is better than table-based and float-based layout. JSX is better than templates. A lot of our old school ideas have either been proven wrong or evolved.
Is styled-components better? I don't know yet, but so far I like it.
> Is styled-components better? I don't know yet, but so far I like it.
Consider these two scenarios:
a) Someone using your component must also understand your component's full stylesheet and must determine (through analysis or through your naming conventions) what she can safely change about your component's styling, vs which parts are likely to be changed by you (or completely refactored) in future versions.
b) Someone using your component gets an API for the things they should be able to change about your component. The rest of your component can be updated (and its implementation changed) as you see fit, and as long as the consumer has followed your public API, the new version will work.
I think that with scenario A you lose most of the benefit of components, since you expose (and force the user to understand) some of the implementation details that she should not modify.
Whereas with scenario B you get the benefit of having an encapsulated unit of code with a clear interface, while being free to modify its implementation as long as the public interface continues to work as expected.
An additional bad part of A, if you look at many bootstrap sites, themes and components that aren't built from source projects, is you also wind up with a LOT of bloat for style definitions that aren't even used. Winding up with kludge on top of kludge, in a large project, where eventually you have to deeply namespace everything to overcome some abstract rule for a part of the app/site you can't even find if it's used anymore.
Have you ever built an SPA with globally defined stylesheets? It's a huge pain that's near impossible to maintain. I still have nightmares from that time I tried to migrate a backbone application from Bootstrap 1 to 2.
It's not about CSS in JS, it's about having locally scoped CSS. Using JS to do it is just one approach.
Yes - more than one. The complexity is also a function of team size. I ran an SPA by myself for an entire organization and didn't have a single problem writing raw CSS.
Sure, everything is easy when it's just you. The value of having abstracted, localized CSS on a long-lived team with multiple developers cannot be understated.
Don't get me wrong, I had the same reaction as well when I first saw it, but the HTML/CSS/JS divide only really makes sense when you're making a traditional HTML document. When we're making component-ised UI elements, separating out that code across HTML templates, a JS file and a CSS file doesn't actually make that much sense.
I don't personally use JS-ed CSS like this, but I also don't think it's a totally insane idea.
Imagine the case where button color is embedded into the implementation of every component. If a UX designer decided that the new apps' brand will be partly new button colors - congrats, you'll have to change every button component instead of a single line of CSS.
Fully encapsulating components is one thing, especially if their encapsulated implementations use shared stylings under the hood. Anything else is repetitive copy-pasta that will be difficult to maintain.
> Imagine the case where button color is embedded into the implementation of every component. If a UX designer decided that the new apps' brand will be partly new button colors - congrats, you'll have to change every button component instead of a single line of CSS.
Not at all. In fact I'd argue it's just as simple if not even simpler than having plain old CSS in that use case. You could easily have brand colours in either a theme or config file and there you go: one line of change. As others have said it's a lot easier than it sounds and styled-compenents makes a lot of sense especially in a world where a lot of places are preprocessing their stylesheets with SASS or LESS.
I don't get it, why do you have so many button components? If you have different buttons for a number of valid scenarios, it follows that each scenario should be reconsidered during such a rebranding.
The problem you're describing shouldn't actually exist in a well-structured component system based on a well-considered design system.
Secondly, nothing is stopping you importing constants representing brand colours, spacing and typography from other modules, then using them in your component styles. In fact, this is what people actually do.
With styled-components you define the theme once, and then just use those variables in all of your components.
With plain CSS you end up sometimes repeating the same value as a color or a background-color or a fill or stroke and then you need it to generate a dynamic value in JS and suddenly you either have to come up with clever tricks involving semi-transparent overlays or you copy the same value from your CSS into your JS and now everything's horrible.
Styled-components and "CSS in JS" solve that. Sure, CSS variables solve that too (except when you need the variables in JS), but out here in the real world people have to support browsers that don't support CSS variables.
Rendering CSS from javascript is not new nor unique and in my opinion not "a mess". Hell, rendering domain-specific declarative languages in programming languages is not new or unique.
This tool isn't even "putting CSS in javascript", it's putting CSS interfaces as first class interfaces on JSX.
Their very structure is one which is namespaced, there is no other way to format a stylesheet. Sort of like "Global code" oh woe is me, I put my new class in a namespace but it's still accessible from everywhere and can be shared to other places.
Why bother coming up with namespaces in CSS in addition to the structure of your JS if your components need both if you can simply let your tooling generate the namespaces for you?
And god help you if you ever need to resolve naming conflicts when using third-party CSS. With "CSS-in-JS" you get that for free as part of the conflict resolution of your module loader.
If CSS is a stopgap, then HTML is a stopgap. What other technology for styling HTML and browser web pages do you think should exist? What do you think should replace it?
The idea that we're trying to build medium-scale application UIs using a tool set intended to mark up documents with modest formatting requirements is still as crazy as it always was. Pragmatically, we can do it and make stuff work, and because of the compelling advantages of browser ubiquity and the distributed nature of the Web, we put up with the shortcomings, at least for now.
However, none of HTML, CSS or JS is actually very good for full application development. We had better technologies for native applications decades ago. If mainstream operating systems had solved their application deployment, maintenance and security problems within the same time frame, web apps would probably never have existed, and developing modern front-end code for distributed software would probably be much, much easier.
HTML is holding up pretty okay at it's stated mission. We're able to learn to avoid the shit parts, and we're able to build abstractions on top of it. CSS is failing at it's stated mission, which is to separate style from markup. Only the simplest toy apps can separate style concerns in practice. The whole thing is shit, there's no good part, and there's no way to compose it or build abstractions, except to just do it in javascript.
That's the goal. It used to be that JavaScript and web development was very difficult because the languages were lacking. Today the languages aren't lacking but there's still a psychosis that won't go away. React was built for extremely complex websites like Facebook, specifically for Facebook. And now people use it just to make buttons or range sliders. Or to develop a blog, or an about page.
Despite the fact that you can make a button or a range slider natively in HTML and CSS which would be much more performant with a smaller footprint on both bandwidth and cpu. What can you say; ever since jQuery everyone has been dying to reinvent HTML and CSS, it's exactly what you just pointed out.
They're well-styled widgets that are composable and easy to integrate into client code without adding a bunch of dependencies (like globally-defined CSS classes). What's not to love?
...Or at least, that used to be the case. Looking at the most recent version of rebass, it looks as if it uses the same dynamic classname/stylesheet generation strategy. Now I'm not so sure what the difference between rebass and axs are, except that the former seems to be a comprehensive set of UI components, and the latter a tool for generating your own component library.
In any case, I'm glad jxnblk keeps experimenting with these libraries, even if it's hard to keep up with the changes. Their surface area is so small that it's easy to pick up the API and it doesn't feel like a risk or burden to stay on older versions.
[1] http://basscss.com/
[2] http://jxnblk.com/axs/