Rebass – Functional React UI component library built with styled-components
jxnblk.com
jxnblk.com
...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.
See my article about styles in JavaScript and the difference to inline styles here: https://mxstbr.blog/2016/11/inline-styles-vs-css-in-js/
document.body.style.marginTop = '200px'
The non-camel-case version works as well (in modern browsers, there was a time when browsers supported either one or the other): document.body.style['margin-top'] = '400px'I still don't know what `my` means.
- m = margin on all sides
- mt = margin top
- mb = margin bottom
- ml = margin left
- mr = margin right
- mx = margin on x axis (left & right)
- my = margin on y axis (top & bottom)
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.
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?
What a mess.
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.
* or https://github.com/dowjones/react-inline-style or https://github.com/martinandert/react-inline ... there's a lot of options
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.
What happens when I want to change every button from green to red? Does that happen in one place, or now many?
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.
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.
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.
CSS modules are about 95% of the way to making this a solved problem.
Obviously this relies on imported components implementing CSS modules, but for a greenfield project this kind of thing works remarkably well.
It's not about CSS in JS, it's about having locally scoped CSS. Using JS to do it is just one approach.
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.
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.
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.
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.
This tool isn't even "putting CSS in javascript", it's putting CSS interfaces as first class interfaces on JSX.
Encapsulation.
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.
CSS is old tech based on old ideas. It still has its place but needs to be superseded.
Keep in mind that even Rebass uses CSS to style.
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.
Got it.
<Fixed m={2} right bottom>
Hello, this is a Fixed Element...
</Fixed>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.