Why You Shouldn’t Style React Components With JavaScript

Update: I’ve announced react-pacomo, a solution for some of the problems with CSS outlined here, without the downsides of Inline Style.

So one of the hottest topics in the React world lately is Inline Style, i.e. setting styles with an element’s style property instead of CSS.

This new and shiny way of doing things promises to make your life easier. It eliminates the bugs caused by global styles, it allows you to package styles with your components, and it unifies the entire development process under the single language of JavaScript, fuck yeah. And now that all the cool kids are using it, it’s time to jump on the bandwagon too!

But don’t just take my word for it! See for yourself with this handy dandy list of all the problems which you could have fixed with plain old CSS if you hadn’t of drunk the cool-aid, and the new problems you’ll now have to deal with too.

Problems which Inline Style didn’t have to solve

Everything in CSS is a global

Let’s get this one out of the way first, because it is always the first thing that comes up in any list of reasons not to use CSS.

Yes, everything in CSS is a global:

.active {
    background: red;
}

/* ... lines and lines of unrelated code ... */

.active {
    /* oops */
    background: blue;
}

So namespace your classes and deal with it:

.app-NavItem-active {
    background: red;
}

/* ... lines and lines of unrelated code ... */

.app-ContactForm-active {
    background: blue;
}

While this may look long-winded, if you’re using SCSS or LESS then the parent selector with a dash (&-) will make wonder what you were ever worried about:

.app-ContactForm {
  &-active {
    background: blue;
  }

  &-saving, &-fetching {
    /* style goes here */
  }
}

And on the React side, there are tools to generate these scoped class names for you. Or if you’re stuck outside the kingdom of React, CSS modules will accomplish basically the same thing.

But then again, sometimes you want global styles, like this:

@import url('http://fonts.googleapis.com/css?family=Roboto:300,400');

Or this:

html, body {
  position: relative;
  height: 100%;
  min-height: 100%;
  font-family: Roboto;
}

And good luck implementing these with Inline Style.

Cascading gets in the way

There are a number of meanings of “cascading”, so let’s pick one: styles sometimes inherit their value from parent styles. For example, defining font-family: "Comic Sans MS" on body will cause most everything on your page to be cheerful and happy. Some people don’t like this, because it means that your component may end up with style which you didn’t specifically give to it. But style will still cascade, even when defined with Inline Style.

So why is Inline Style a benefit? Well, Inline Style let’s you write JavaScript helper functions to ensure that your components overwrite any inherited styles with their own styles. But seriously, let’s think about this for a moment: all you’ve really done is re-implemented cascading through JavaScript helper functions. Though at least it’s written with JavaScript now, amiright?

So let’s move onto the next meaning of cascading: if you create a selector for ul li, then your styles will be applied to ul li ul li and ul li ul li ul li too. Selectors aren’t very specific.

Easy fix: don’t use HTML elements in selectors. Instead, give your elements namespaced CSS classes which double as a way of documenting what they actually do. Your code will be clearer and more precise as a result.

Inline Style can be included directly from your component modules

This is actually a huge benefit. Nobody likes maintaining entirely separate project trees just for their CSS, or managing CSS files which live in completely separate locations to their corresponding JSX.

But now that we all have access to wonderful tools like Webpack, this benefit isn’t limited to Inline Style anymore. In fact, I place my LESS files right next to my JSX (or JS with Angular), and then include them like this:

import './DocumentForm.less'

But James – you tell me – those LESS files still depend on other LESS files which are separate to your components. And it isn’t like you can use JavaScript-loaded styles in production!

Half true. The LESS files do depend on other LESS files – but only ones included like this:

@import (reference) '~cloth-util-less/index.less';

That little (reference) ensures that no output is generated by the @import; it is just a way of importing variables and mixins. This allows each component’s CSS to be completely independent of the other components.

And with Webpack’s ExtractTextPlugin, the generated CSS is all extracted to a real CSS file. Which can be cached separately! Have fun caching your inline styles separately.

Inline Style lets you use JavaScript, so you won’t have to learn CSS

Except that you will. Seriously, what are you people smoking?! See those property names in your Inline Styles? They’re CSS.

Ok, maybe you won’t have to learn media queries and pseudo selectors. But instead, you’re going to have to learn the equivalents for whatever framework you choose. Or maybe you won’t – because if you don’t use an Inline Style framework, you’ll spend so much time re-implementing media queries and pseudo selectors that you’ll know how they work back to front.

Inline Style gives you more power

This is about the only valid point that people make. You do get more power with Inline Styling than you would with CSS, or even with CSS compilers like LESS, SCSS or PostCSS. But do you really need it?

No website is complete without a terrible car analogy, and this might be my only chance to ever write one, so here goes: CSS is a moped. It sucks, but it is what you start out with. It is dangerous, slow, and it quickly teaches you why you need more power. LESS/SCSS is a Japanese car. It is reliable, it gets you where you need to go, it won’t need fixing any time soon, and it’ll still hit the speed limit if you want it to. Inline Style is this:


Problems you would have avoided if you just used boring old CSS

You can’t use any existing tooling

Sure, CSS is a bit shit. But that is why people have made a number of amazingly useful tools which aren’t:

Maybe you don’t use any of these tools. Which would surprise me, because it would be silly to jump on this bandwagon without having at least tried the industry standard solutions first. But let’s say you haven’t, and then a brilliant new tool arrives which targets CSS. Too bad.

But tools aren’t all you’ll be missing.

You can’t use any existing CSS

So you know all those styles you’ve written over the years? You can kiss them goodbye. But maybe you don’t write many styles, so it’s all good.

Except, you know all those styles that other people have written over the years? You may as well forget they ever existed, because they’ll be incompatible with yours.

But no worries, it isn’t like you have to put all your style in Inline Style. You can just gradually move your style over, and pull in parts of the occasional CSS library when it makes sense. Except that you can’t, because:

Inline Style is infectious

So you know how you can define CSS styles with a number of priorities?

Element selectors have the lowest priority — you can override them with CSS classes. Classes can be overridden with IDs, which can in turn be overridden with !important.

And you know what overrides everything? Inline Style.

Now you may be thinking, “That’s great, because now I never have to worry about anything overriding my styles”. Which is true, but you wouldn’t have to worry about this anyway if you just namespaced your classes properly. Notice a pattern here?

But you will have to worry if you ever need to apply third-party styles, because Inline Style will kill them dead. And if you want to add some CSS to a component which defines its own Inline Styles? You’re shit out of luck. And if you want to override anything without passing in options as more Inline Styles? You just can’t.

And this might not be a problem for you. But unless your project is just a toy, you’re not the only one who counts.

Designers speak CSS

If you work on a team of anything other than the most talented people, you’ve probably already experienced this. In fact, you’re probably reading this rant for entertainment, not education. I hope you enjoyed the show, and don’t forget that sharing cat videos and JavaScript rants is caring!

But let’s say you’re a lone front-end developer experienced in both CSS and JavaScript. You’re building something which you’d like to eventually pay the bills, and scaling sounds like a problem you’d like to have. Part of scaling is that your code will at some point be handled by other people. And even if you don’t find anything in this article scary, everyone else certainly will.

But CSS still has problems too!

You’re absolutely correct. The thing is, there are better ways of solving these problems than using Inline Style. I’ve already alluded to a few of these solutions:

  • Using LESS to avoid repetitive style definitions
  • Using React to transform your CSS classes into namespaced CSS classes
  • Using Webpack to modularise your CSS

Not sure how to accomplish these? You could learn them the hard way: with Google and trial and error. Or, you could learn them the easy way: Join my Newsletter, then read the guides I’ll be sending out over the next couple weeks on namespacing and modularising CSS.

And to sweeten the deal, in return for your e-mail you’ll immediately receive three print-optimised PDF cheatsheets. One on React (see preview), another for ES6 and yet another for JavaScript promises. All for free!

I will send you useful articles, cheatsheets and code.

I won't send you useless inbox filler. No spam, ever.
Unsubscribe at any time.

One more thing – I love hearing your opinions, questions, and offers of money. If you have something to say, leave a comment or send me an e-mail at james@jamesknelson.com. I’m looking forward to hearing from you!

Read More

Related Projects

Share on Facebook33Tweet about this on TwitterShare on LinkedIn33Share on Reddit21

27 Comments Why You Shouldn’t Style React Components With JavaScript

  1. SylvainPV

    I started to use inline styles only for some layout properties (positionning and sizing), aside my classical SCSS styles that defines the graphical charter and the other styles.

    CSS specificity is really useful to define color schemes, alternative states, modifiers etc… but from my experience, it is terrible with layout. When dealing with layout, you often want to set several properties at the same time, like position-top-left-margin or display-width-height. If one of these is overridden, things quicky become complex.

    When working with a component approach, where the HTML/JS and scoped CSS are bound together, using inline styles for layout gave me good results until now. This is also an approach used by some JS UI libraries that works with layout, like Masonry or jQuery.equalize.

    Reply
    1. Alex

      I agree 70% of the time. There are times when you have some fancy component, that it totally makes sense to use the inline-styling. An example would be a calendar component. I want to be able to build 1 calendar component and it be ready to be used in all my project, without fiddling with a million different css files.

      Reply
  2. serapath

    I think styling components from javascript is the future, because it makes everything easier in the same way JSX or “inline markup” makes things easier.

    You can use inline styles and if you need the features of stylesheets, use https://github.com/jsstyles/jss

    You can even define your “jss” in “css” by using es6 template strings (which even enables you to use variables) and converting the “es6 template string css” into “jss” on the fly using https://github.com/jsstyles/jss-cli/blob/master/lib/cssToJss.js

    Honestly, all the disadvantages you mention will go away and the benefits stay.
    I agree, that maybe it’s not ready for prime-time, because it needs some more “user friendlyness” and usage examples.

    Reply
      1. serapath

        css modules are better than css but dont fix css for real.

        – css modules cannot be customized by passing in arguments, thus a “button component” cannot receive it’s “box-shadow” as an argument.

        – css modules cannot adapt styling based on real-time user interaction.

        Both features you get with javascript and thats why jss and co. are so awesome.
        In the past – databinding or “reactivity” were not important and now it’s state of the art.
        My bet is that the same will be true for styling in the near future.

        Reply
        1. uscareme

          Except that CSS is addressing these lacks through WEB STANDARDS right now.

          See these standards…

          https://www.w3.org/TR/css-variables-1/
          Not only do CSS variables (aka custom properties) bring variables a la preprocessors to CSS, variable values have the added benefit of being both scoped and live variables. Meaning CSS can adapt styling based on real-time user interaction. This has already shipped in Chrome.

          https://tabatkins.github.io/specs/css-apply-rule/
          Variables are nice for simple theming, but more complex needs are common. There are properties within themes which are inter-reliant. Or maybe a user wants to add a box shadow the default theme didn’t have and therefore a component didn’t provide a variable. (Plus, if components provided variables for EVERY theming possibility, it’d be reinventing CSS properties via variables–not possible, and a mess.) A good solution, simulate-able with Sass mixins, is a “block variable”, a variable that can contain any rule ad hoc. This proposal will bring this powerful and elegant feature to CSS–which, like the CSS variables above, will be dynamic and can respond to real-time user interaction and to scope.

          …to name two.

          No solution that requires an investment into a commercially supported framework will ever be a better option than an open web platform standard. The article http://www.sitepoint.com/importance-web-standards/ covers a brief history supporting this assertion.

          I guarantee to you: Inline CSS is a fad. React will eventually go the way of jQuery. Web standards last and are a better economic choice for businesses.

          Reply
    1. Anton Volt

      I used to think that way until I really have react a chance, but now I’m convinced everything should be grouped with the component that is using it. Separation of concerns only matters if your code isn’t very modular, but I’ve been very happy not having to open up 1 giant rats nest of a CSS file or opening up a million SASS partials, just give the react way a real shot and you’ll see why everyone is switching

      Reply
      1. serapath

        +1 :-)
        or any other javascriptish solution.

        You get all the power of pre-processors with a powerful familiar language (javascript)

        You get real-time updates based on user interaction

        Styling calculations and other things can be put into “npm modules” and easily shared and re-used

        Reply
  3. Anton Volt

    So we started rebuilding v2 of our app with react/redux and one of the devs was set on only inline styles, at first I was against it but then I started to really appreciate it.
    To counter some points you made, writing our own media queries in JS took 1 day, I made a sweet flexbox layout helper system in an hour which is the most painless Expetience I’ve had doing layouts.
    You do raise some valid points but why in the world does it only have to be all CSS or all JS, we use each where it makes sense.
    We have almost all components inline styles and pass props when needed, but we do have 2 components which is just made more sense to import a SASS file, (plus we run with 1 global CSS file for resets and basic styles).
    So why does it have to be one way or the other? I’m in love with the combination right now, it’s most fun I’ve had working in a while.

    Reply
    1. James K Nelson

      A few people have mentioned that they’ve been using both together, and the pattern of Inline Style for layout, CSS for “themeing” comes up a bit. It certainly does sound like there may be some upside to this approach which I’ve glossed over. Possibly because layout can be thought of independently to theming?

      Reply
      1. Brian

        This could potentially work, but at that point you already have separate CSS, why split things up like that? When it doesn’t look quite right you now have to look in two places to find the code to fix!

        Reply
  4. Phil Ricketts

    Agreed.
    If you find yourself wanting to add some CSS to a DOM element, don’t.

    Namespace your CSS if there’s just too much to deal with.
    If you must, write your styles to a `style` tag in the head.

    Reply
    1. James K Nelson

      Yep. That said, outside of Layout (which Inline Style seems to do a good job of), it might make sense to make separate Presentation components for both native and web – they’re different, after all.

      I’m going to be looking into the react-native conundrum a little more. Stay tuned for an update.

      Reply
  5. Jos de Jong

    I Agree with comments from Sylvainpv and Anton Volt: CSS is great for styling like fonts&colors but a huge pain for layouts.

    On the other hand, I experienced React components which did use inline styles in a restrictive way: hard-coded fonts and font sizes without a way to override them all to match your own applications fonts.

    All in all I think inline styles are very valid for layouts, and not so handy for theming.

    Reply
    1. James K Nelson

      I’m coming around to the idea that maybe Inline Style isn’t so bad for layout. You’re spot on thought with your observation of components which hard-code things like fonts and colors. They’re a perfect use case for CSS using pacomo, and it certainly doesn’t make sense to use Inline Style with them.

      Reply
    2. uscareme

      I’ve been interviewing JavaScript application developers for the last four years, and the majority of them appear to be incapable of writing viable CSS at all. Forget them having the sophistication to actually architect CSS intelligently, making appropriate choices about which rules to consider essential layout and which rules to consider optional theme.

      How do they get products to market? In most cases the answer appears to be Bootstrap or some other framework/modules of its ilk. Good luck using a pre-written CSS grid system for layout with inline CSS. Oh, but we will eventually finish reinventing the wheel for inline CSS and then everyone will see what a great idea inline CSS really is! Nevermind that whole “reinventing the wheel” requirement.

      Now, sure, I don’t personally need a CSS framework and can both write and architect good, change-tolerant CSS. I could probably use inline CSS in a very effective way. But I see downsides, too, and am aware of better standardized solutions in coming down the pipe to most of my CSS conundrums. Not to mention there’s a typical learning curve fraught with unknown unknowns (distributed across multiple people and new hires) when making such a fundamental change. Do the potential benefits outweigh this? Not for most applications.

      I’m comfortable saying that most people evangelizing inline CSS are are the last people I’d trust for CSS advice. If you only have a hammer, every problem looks like a nail, or so I hear. There’s not enough nuance in any fandom, even in tech industry cargo cults. However, I’m essentially biased against developers embracing React and its JavaScript-obsessed, HTML-and-CSS-phobic mindset in numerous fundamental ways.

      Reply
  6. Ted

    I think there is a small mistake in the article, where it says that inline styles override everything.

    Actually they don’t override !important.

    Reply
  7. Steve

    I agree with one concept – do not write inline styles.
    The rest of the article, however, has made my girlfriends blood boil.
    Scss generates css. It isnt better. Hand written css is faster to write than waiting 2 seconds for the whole compile time every change you make. Its popular but so is angular. Using it doesnt automatically make your code architecture more maintainable, scalable, performant, or speed up development. From experience it actually leads to slower development. Also namespacing classes is stupid because if you change the structure of your html, then your class .parent-child-subchild becomes wrong.

    Reply
  8. Craig McKenna

    Thanks for your articles James. Especially “Learn Raw React — no JSX, no Flux, no ES6, no Webpack…” For me, with JSX, React was very convoluted and hard for me to wrap my head around.

    I recently became very interested in web apps and so reentered the web development world after an eight (or so) year hiatus. Back then I was developing static websites on the LAMP/PHP stack. I used JavaScript mostly for form validation only. I don’t think css preprocessors existed then.

    Shifting to the modern web paradigm with JavaScript has been an arduous journey for me. However, I have found inline styles to be a joy to work with inasmuch as it affords me more maintainability and control. without needing to learn “yet another technology” like SASS or LESS or… and so far in my very limited experience with React I don’t see the need to. Then again I don’t really know any better.

    Currently I am using css only for layout and for a small amount of global styling. Time will tell whether or not this approach bites me in the ass.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *