Hacker News new | past | comments | ask | show | jobs | submit login
Rebass – Functional React UI component library built with styled-components (jxnblk.com)
146 points by mxstbr on July 5, 2017 | hide | past | web | favorite | 64 comments

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.

[1] http://basscss.com/

[2] http://jxnblk.com/axs/

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.

[1] https://github.com/cssinjs/react-jss

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)

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/

[0]: https://styled-components.com

The shortening of properties is very much a bad idea and should be avoided. "What the hell is `mb`?" is going to come up a lot.

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.

I think it's a very short hump to overcome, and then you're just rolling with Tachyons.

I’d agree. I can see how it isn’t for everyone. But I like typing fewer characters when there’s a system behind it. :)

I'd agree too. For those who are turned off by the looks of it, you should give a try. Read some experience reports here: https://medium.com/@cole_peters/building-and-shipping-functi... and https://hackernoon.com/full-re-write-with-tachyons-and-funct...

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).

Is there any reason to use shorthand like mb instead of using the React standard marginBottom?

FWIW, marginBottom is not a React "standard", it's a DOM getter on the style object:

    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'

A legacy production application is not live-editable in the same way.

I still don't know what `my` means.

A little trial and error, and I think I figured it out:

- 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)

I'd really like to understand why -3 for such an innocuous comment. Live-editable code is an important tool for just this reason.

Guessing you got downvoted because it's not really relevant - live editable code is nice for docs but doesn't explain why a property is poorly named.

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 prefer glamorous, CSS properties as JSX props is so much nicer.

give react-jss a look... :-)

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.

What a mess.

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.

That said, with react tools like https://github.com/threepointone/glamor or https://github.com/milesj/aesthetic * you can get the best of both worlds. Isolated css plus :hover and other psuedo attributes.

* or https://github.com/dowjones/react-inline-style or https://github.com/martinandert/react-inline ... there's a lot of options

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/

Nice explanation. I agree. Removing the cascading effects is an especially big one.

> are we now putting CSS in Javascript?

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.

Yes. These concepts are gradually starting to take hold in the web and traditional DOM world as well. Oh what a wonderful world it will be!

Don't knock it 'til you've tried it.

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.

There's tooling for that: https://github.com/simlrh/dead-css-loader

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.

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.

Why not?

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.

No, that's the OPPOSITE of what happens.

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.

Here's a good explanation of 'why CSS-in-JS': https://medium.com/seek-blog/a-unified-styling-language-d0c2...

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.

Au contraire, global stylesheets are a mess. Good riddance.

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.

You know what's better than namespaces?


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 a stopgap until the next styling technology comes along. The idea/implementation is correct but the technology is not.

CSS is old tech based on old ideas. It still has its place but needs to be superseded.

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?

Keep in mind that even Rebass uses CSS to style.

Well, HTML is a stopgap, just as CSS and JS are.

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.

So... let's write everything in Javascript.

Got it.

Not sure what you're getting at. I'm literally suggesting the exact opposite would be preferable.

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.

I think Arkham Asylum has a wing for non CSS-in-JS nutcases ;)

This might be good for react native apps as well.

The "hello" in the bottom right corner seems like it was put there by accident. It causes a small problem on mobile.

That's the Fixed element. You can live-edit the code:

    <Fixed m={2} right bottom>
      Hello, this is a Fixed Element...

Seems like you are reinventing HTML and CSS, what's the benefit of using such component library?

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?

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact