Hacker News new | ask | show | jobs
by renke1 3507 days ago
This looks really nice.

However, what I really want for React is a style-agnostic component library that basically extends the regular set of HTML elements, but comes with no "visual" styling (other than really basic styling like the browser's default styling for <input>, <select> and the like). Only styling that is necessary for the component to function should be included.

Of course, optional themes would be fine. Also, non-visual styling should be completely inlined. Themes could inject "visual" styling via context. User-defined styling would be passed via class or style props.

3 comments

Styling is still "unsolved" with react IMO.

Inline styles feel wrong, CSS alone isn't encapsulated enough to work with components correctly, CSS modules are TOO encapsulated which makes global styles and themes a royal pain, and adding another layer ala SASS or LESS feels like more of a "patch" vs a real solution.

And none of them really solve style inheritance in any way that I'd call elegant.

I end up using SASS and overriding default styles with weird hacks like using `.button.button.button` or (even worse) using `!important`, but it still feels wrong and doesn't scale very well at all.

I know everyone has their own favorite method, but one that I'm extremely satisfied with is using webpack > sass-loader > extract-text[1] to `include Styles from './MyComponent.scss'` in each component file, and then it all gets bundled up into a single css file per target (also great for eliminating dead CSS!). I use "layouts" at the root of my react hierarchy (under stores and routers and whatnot) and put my global styles there.

I haven't run into a situation using this setup where I felt like I needed a dirty hack to make something work. It does add a layer of complexity to the build, but if you can get it working once you can just copy paste it into every new webpack config, and It feels very natural and tends to organize itself.

I am really not a fan of this new "css in your js" approach that the cool kids are using, but I guess I'm just getting old.

[1] output of the following config will be:

  dist/
  |_app/
    |_bundle.js
    |_bundle.css
  |_admin/
    |_bundle.js
    |_bundle.css
```

  const webpack = require("webpack");
  const ExtractTextPlugin = require("extract-text-webpack-plugin");
  const ExtractCSS = new ExtractTextPlugin("[name].css");

  module.exports = {
    entry: {
      "./dist/app/bundle": "./app.js",
      "./dist/admin/bundle": "./admin.js",
    },
    output: {
      path: __dirname,
      filename: "[name].js"
    },
    module: {
      loaders: {
        test: /\.scss$/,
        loader: ExtractCSS.extract(["css", "sass?sourceMap"])
      }, {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/,
        include: __dirname
      },
    },
    sassLoader: {
      includePaths: "source/styles",
      sourceMap: true
    },
    plugins: [ ExtractCSS ]
  }
```
That is what we do as well, but if you use a UI toolkit that includes it's own styles, you'll need to override them. That's where the fun hacks like .button.button.button come in to override the included styles.
Oh yeah, I see what you're saying. I just don't bother with toolkits since I find that once you factor in said fun, you aren't really saving much time, and you might end up with a lot of jank. I just roll my own based on the needs of the project and keep my cascade very flat and specific. Sass makes this really easy using BEM style naming, where you can do this:

  .my-component {
    &_component-item {
      &--open {
      }
    }
  }
and you get a nice, flat output:

  .my-component {}
  .my-component_component-item {}
  .my-component_component-item--open {}
I wish framework authors would adopt this approach as it completely eliminates specificity conflicts.
I've done the same thing. An issue I run into is it's easy to end up with lots of the same media query littered over the place, which can harm performance and feels quite messy.
You can use some more advanced-ish sass features to help with the maintainability, but it can still kill perf if you over use it.
This is also my same setup. It is refreshingly easy to maintain.
> Inline styles feel wrong

Care to elaborate? I've been using in-line styles in multiple production projects and to me it feels like the way styling was meant to be done all along. The purpose of React is to be able to define your UI as a function of application state and let the library resolve the UI automatically at run-time. Styles are a part of that UI, so it's only natural that they should be included. What most people end up doing is using CSS and doing something like "state => classes => styles" rather than the simpler "state => styles", but the main benefit to that whole abstraction has always been re-usability, and components already solve that. So what exactly are we gaining by using said abstraction?

Of course, that's only in theory. In practice, we gain pseudo-selectors (which are unavailable for use in in-line styles for obvious reasons), which is a noticeable pain point. In my experience it is fairly easy to work around as I only make a lot of use of :hover (which is all of a few lines to implement), I can see how it might be troublesome to others though. The other solution is of course to use a mix of in-line styles and classes, which usually involves writing in-line styles for component-level styling and classes for global themes and anything requiring pseudo-selectors. That approach seems quite popular on the React IRC channel.

Yes, thank you. This has been my biggest problem with React as well. It feels like they are fighting against some of the most natural ways to use CSS in code. Which is too bad, b/c CSS is awesome, and React is awesome. But together it feels like they don't play well.
Why? They actually can play well, at least, just as well as standard HTML + CSS.

It's just that people are now trying to componentize everything, including styles, so it's a new requirement we didn't have before. Put another way, one could say that now that we have a good solution for client side rendering, we then turned to good old global, cascading, hard to maintain CSS to try and fix that guy next.

Perhaps it's a CSS issue. I've just noticed that when working only with CSS adding and removing classes in JS it's simple. All of the React frameworks feel like they don't meld well with that.

I will not claim to be a JS expert by any means. In my basic usage of HTML, JS and CSS; I find that I can manipulate the look and feel easier with Jquery. When I add in React, I get a really elegant MVC system, but loose the ease of adding and removing classes of different HTML elements.

Maybe I'm doing it wrong, but that's just my experience.

I saw this[1] recently by one of the guys from material-ui[2].

They're going to move to JSS.

[1] https://github.com/oliviertassinari/a-journey-toward-better-...

[2] http://www.material-ui.com/

I really like material-ui but am constantly bummed about their use of inline styles.

Each component has multiple style props, lest you resort to "div > div > div:nth-child(2)" in your own CSS.

Each "style" prop now has to be diffed by React too.

Doing things like hover on mouse/touch events seems like it will never be as efficient as using ":hover".

And when doing universal rendering, the amount of markup you send is huge. And you have to disable the browser-prefixing of style props.

Having said all that, the material-ui library is still great.

We just wrote all our own inline styles to override their stuff. It turned out to be not that bad. We just set up a context object like theirs, and wrapped all the components we used.
Yep... Settled for CSS modules for now; Works well enough.
You may want to have a look into CSS @apply - https://tabatkins.github.io/specs/css-apply-rule/ (currently supported only in Chrome trough).
> "Styling is still "unsolved" with react IMO."

How about this simple way to decouple styling from components using CSS Modules (no inline styles needed):

  components/
  |__FooComp/
     |__FooComp.jsx
     |__FooComp.css
  css/
  |__components/
     |__FooComp/
        |__styleOne.css
        |__styleTwo.css
        |...

FooComp.css contains only the very basic formatting for the component which is needed for displaying it correctly out of the box. No styling/theming, just some raw universal formatting/structuring (if necessary at all). FooComp.jsx loads and applies FooComp.css internally using CSS Modules like this:

Inside FooComp.jsx:

  import defaultClasses from './FooComp.css';

  const FooComp = props => (
    <div className={`${defaulClasses.wrap} ${props.className.wrap}` } >
      <img className={`${defaulClasses.img} ${props.className.img}` } />
    </div>
  );

  export default FooComp;
styleOne.css and styleTwo.css contain different (external) styles for FooComp. Now if you need to use FooComp with an external style you load both FooComp.jsx and the external style (again, using CSS Modules to load and apply the styles):

  import FooComp from 'components/FooComp/FooComp';
  import FooComp$styleOne from 'css/components/FooComp/styleOne.css';
and put them together like this:

  <FooComp className={FooComp$styleOne}>
This way you can easily use the same component with different styles.

> "CSS modules are TOO encapsulated which makes global styles and themes a royal pain"

You can still use:

  @import '../someGlobals.css';
or:

  .someClass { 
    composes: anotherClass from "./someFile.css";
    color: green;
  }
or:

  .someClass { 
    @apply --anotherClass;
    color: green;
  }
or:

  .someClass {
    background: var(--brandPrimary);
    color: green;
  }
or ...

There are plenty of options especially with PostCSS.

React is supposed to be the "next big thing" and yet styling is still an unsolved problem.

I'm amazed by the state of our tooling in front end web development.

I know it's fun to scoff at "those front end guys" and act like you know all the answers, but if you do know the "one true solution" to this please tell us.

It's "unsolved" in the sense that all the current solutions feel wrong (but work great), and if that's the biggest problem front-end development currently has, then it's in a pretty damn good place.

I really don't know the answer. I'm a front end guy too.

But it just seems like we are all stuck on this collective transe of needlessly complicated, overly fashionable tools that struggle with the basics.

From what I've seen (granted, not much), animation and styling look like an after thought, which is surprising. But I'm weird, I still write bare CSS to this day whenever the decision is up to me. SASS is cool, but not enough to justify adding another lever to the machine, IMO.

I tried to do something like that with react-menu-list[0]. Its components come with minimal styling, and it's recommend for users to create wrapper components which pass some default props to add their own application's CSS classnames / styling.

[0] https://github.com/StreakYC/react-menu-list

Well, you could use something like Reactstrap (https://reactstrap.github.io) which assumes Bootstrap classes, and simply not include the BS4 visual styles/themes