At work we’re building our latest software product using ReactJS, and have chosen to do the frontend styles a little differently to what I’m used to, using “local styles” which is a way to modularise your CSS.
So instead of having all styles in one place and separated from the markup, this builds “components”, which is markup and styles all together. I have mixed feelings about this, the strongest that all the markup is kept in JavaScript, which I find horrible. Just horrible, to work with.
But I’m on the fence about local styles (if you’re not sure what I mean, here’s an article explaining the methodology).
Sometimes doing it that way is useful, but sometimes time consuming for not much benefit. So here’s a few opinions now I’ve had some time to work with it for a good few weeks.
Good things about local styles in ReactJS
- You can copy a component from one project to another and it’ll have all the styles that’s associated with it. Not that I think this is something we’ll ever do, because every project will probably have a new design.
- Forces you to put all styles associated with the component in the same place. This includes media queries, including print styles. Although this might get a bit cumbersome when styling other ways a component is displayed, like different coloured themeing, or when exported for PDF.
- The classnames will be abstracted when the project is built, so they’ll be super small. Not bulky long BEM names like “header-wrapper__options-wrapper”. For example that’ll probably be compiled to “jk34a” or something even tinier, but still have the correct styles applied.
- It frees up the global namespace. So you can use classnames like “options” or “list” without fear you’ll inherit styles from elsewhere.
- You can use SCSS. Everyone should be using SCSS though, because it’s awesome.
- CSS is inserted inline at the top of the document which saves the user having to download separate files. It’s messy, but reducing the number of files to download is great for speed.
Bad things about local styles in ReactJS
- It takes longer to do stuff. This might be debatable, so I’ll say it takes ME longer to do stuff. Because the markup is split up into different files and distributed all over the place, it can be really difficult to chase down the bit you need (which might be a component in a component in a component), and work out quite how it works. Because the HTML is inside JavaScript, it won’t always be in the correct order either.
- Difficult to bake Bootstrap into the project. I like to work by @extending parts of bootstrap into styles, to save having to write things over and over. It makes it much more DRY. But the way our project works (and this could just be down to our implementation) I can’t easily extend Bootstrap’s useful classes, instead having to recreate them, which is annoying and less DRY.
- You have to import everything. Each component has a list of files it imports at the top, which is great to be specific, but also dead time-consuming when you have to do it over and over and over. Using relative paths too, which takes waaay too long to find where you need to import from the current file’s location. Also that makes me really worried for if we ever need to change something’s path.
- You have to write “className=” instead of “class=”. This isn’t much of a problem but really irritates me and warps my brain. I’ve started writing “className” in other projects accidentally!
- Some react components use global styles, and that ruins our attempt to keep it local. We use the react-bootstrap library which does everything with global styles. Which means we have to write :global in a local style. Seems to defeat the purpose!
- Because the css is inserted inline, it’s difficult to find and look at the generated styles. SCSS is great, but sometimes you need to look at what it’s doing to make sure it’s not generating something incredibly long. At jQuery conf, @MDO said he accidentally generated an unnecessary 1000 lines of css just through making 1 change in the SCSS, and I want to make sure I don’t do the same!
- Impossible to use descriptive BEM notation because JavaScript doesn’t like the “–“, although this could just be our implementation. This means I find the markup slightly less clear to understand. Although some people might like it.
- I need the help of the programmers much more. Because the components are all created in JavaScript, it can be difficult to do something really simple like just add a class where I need to without asking who coded it, and how it works.
- The CSS isn’t cascading, or a sheet, so we should rename it from css to just “s”. So because of the way local styles work, they’re all individual blocks of styles, so don’t cascade. And because it’s all inserted inline, it’s not a sheet either.
One of my biggest struggles is keeping it DRY, even though everything is modularised. You can do this by @extending common shared styles. For example we have 2 separate components that need a circular green icon with an arrow. What I’d normally do in this case is create base styles for it, and extend it in both components. Local styles still allows us to do this, but it defeats one of the main purposes, which is to keep all styles for a component contained within.