From CSS Preprocessors to CSS in JS

Phil PlĂĽckthun speaking at The JS Roundabout in May, 2017
Great talks, fired to your inbox đź‘Ś
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

Styling in CSS sucks: it's outdated, and not meant for web apps. CSS evolved, and preprocessors like Jest came around, then components. Phil will illustrate which problems have been solved with CSS in JavaScript and React, and more advantages to using Styled Components.


- Hello, I'm Phil. -Hi, Phil. - I'm one of the Styled Components Core Contributors since December, actually, and I'm here from Formidable apps. So to start from the beginning I'd just like to talk a bit about the history of Styled Components and fear not, it's not gonna be too long, but just to give you a bit of context. Styling in CSS, it really sucks. It's from 1996. It's not meant to do what we do today. It's not meant for web apps, and CSS has evolved and is kind of catching up to what we're doing today, and this all comes from really that time when CSS one came out and was meant for single documents because someone discovered we have all these publishing sites, all these news articles, all these documents and we now just want to style them so that they basically show up in the same way on every single user's browser. And later on CSS evolved to fit more, more needs that arised, so preprocessors like Jest came around with nice features like nesting, variables, and some other things like mix ins, and the basics of that were actually totally fine and new methodologies like BEM enabled us to use CSS and use it in the same way for a really long time and the only thing that we had to do was follow some simple instructions, like if we had a button with a class button we had, BEM gave us just this methodology to name another state of the button. So this, in this case, success, button state success. So really this carries over to kind of the React Jest age of components as well. You could use that no problem. So actual components and CSS still works with BEM, but actual components are obviously different from a component methodology. Components in itself can provide us a more strong subset of styling solutions and this is how I basically wanted to start with Styled Components. So, basically the, the beginnings of CSS in JS and React all started with Christopher here who works for Facebook and when React came out most people were using it with the normal methodologies like BEM, writing SAS code, writing normal CSS code, or even writing in line styling, which is what Christopher wanted everyone to do which is what no one wanted to do before with normal web apps, because in line styling, why would you write your styling in HTML? But when you look at the problems of CSS at scale Christopher laid out some really good points, like all classes are in a global name space, so every time you write a button, you risk that someone else writes another class called button, and then overrides your styles, or you can't really define dependencies between styles. Every time you wanna use another class you just have to use it and know about it. There are all these little points like DAT code elimination. No one knows if a class is actually in use. No one knows where, where it's in use, and constants, if you're just using CSS, variables and constants aren't even a thing. I mean, small spoiler, they're gonna be a thing in CSS now, but obviously at the time no one was thinking about that. And all these things kind of led into this community of styling in React and a lot of libraries were created around these ideas. So, once you basically write your styles in JavaScript you can actually use all the tools of JavaScript to make it really easy to eliminate these problems. If you just write your styles like you write your JavaScript code, once you compile it, everything you don't use is gonna be gone. All the styles are only in a single place. If you wanna use it, if you depend on other styles, you explicitly have to compose them, and there are a couple of really famous libraries like Radium, Aphrodite, Fela, and so on. Some are newer, some are older, and a lot of people I know are still using in line styles or CSS modules and for a long time they were still fine. The whole idea of all these problems, solving all these problems like minification, DAT code elimination, and so on, all these problems are actually solved already today. So with this context, you might be asking yourself so why, why are you talking to me about that? Why are you telling me about problems that are already solved? And this is actually, I mean, a very good question. So if we have styles and we define them like our style sheets, so for example, we just create an object with a container and text class, so sub properties there, we can already replace our classes, and that works pretty much fine. What this doesn't include is dynamic styles. So once you basically just use these objects, they stay like that until we change them, which sounds pretty much fine. So once, once you basically try to change these styles and compose them with others, so if you wanna, for example, make this header have a primary type, you have to write that in your structural code. So if you wanna make a hello world that has a different colour and you wanna make that a separate class, in in line styles you'd probably create a new property on that object, and you'd write some piece of code that injects that every time someone passes a prop, every time someone wants a different style, for whatever reason. So, while all these problems are solved, and while you can use in line styles to basically get rid of most of these concerns, dynamic styles are still a problem in CSS in JS, and this problem is basically amplifying itself as our web apps become more complex, and as we're trying to scale them and fit more use cases, and Styled Components is trying to hook onto that. Styled Components is trying to make it even easier, and it's trying to basically scale this problem to bigger apps, to apps that are more complex, that have more different styles and basically more classes for every single element. So, how do we solve this problem? The first idea of Styled Components is basically to completely rethink how we'd have even style sheets run. So, the first thing that Glenn and Max did when they invented this was they removed the mapping between styles and components. So in this case, you just have some simple CSS code in here which defines our title, which you've just seen before, and you're just writing plain CSS code, and in this case you can see the tag here. You're creating an H1 tag, and that is just a function in this syntax where we haven't invented that syntax, so that syntax is not special to Styled Components. It's actually a new ES next feature. So these back ticks here, they call H1 as a function. So H1 is gonna receive this CSS here as a string, and what this does is it actually calls this function, and receives a component. So by passing an actual CSS string into the Styled Components function you're gonna receive a component that already has these styles. So basically, this gets rid of having both structural code and your styling separately, and then binding them together. So what this actual means to our example before is instead we now have two components title and wrapper and we attach our CSS code to them, and we just render them like before. Instead now we have two components here, instead of just two elements, and those are automatically gonna have the styles that we defined in them. So in this case, it's actually not making a big difference, but in bigger projects, there's so way to separate these styles from their use case. They're already named. They're already going to be in a specific place and when you wanna use them they already come with their styles. If you wanna go a step further and come back to that problem I mentioned, dynamic styles, we can actually look at this example of two buttons, and we have a normal button, and a primary button, and like before, we're just passing some CSS code into that template string, and that CSS code now has a different colour and a different background, depending on the props. What we're doing is we have that special syntax where, which are called interpolations, and those are just functions, and we're basically passing the component props into them, and they're receiving a value. So, by doing that the same components that already have the CSS also have their different variations, their different alternatives. So in this case, we're just attaching to the primary prop and we're rendering it differently. So again, there's no kind of explicit dependency. There's no way to separate that variation out into a separate style sheet. It's just that. It's just a single component and it's all bundled up together so that removes a lot of overhead that you might have to think about once you scale your style sheets or your, your styles to a bigger level where you have a lot of components and a lot of style sheets. So if you compare that to the BEM example I showed you before, it, instead of just having two classes that you could attach however you want, you just have one, and that sounds ridiculous, because I'm clearly comparing two different things here, but if you think about writing that no one can make a mistake with these classes. They don't have to come from somewhere they're just there. Your logic is just in a component. So you don't have to think about where you're importing it from. You don't have to get the style sheet. You're just using a component like in the rest of your application. So that means that this component, this Styled Component as we're calling them is just a presentational component. It doesn't contain any kind of element structure. It doesn't contain any extra logic than just a styling. It just basically contains CSS with functions that change that CSS. And if you now use this component, you're probably gonna separate them into structural components and style components. So once you have all these little, little components that have their CSS attached to it, you can now assemble it instead of the elements and it's gonna create more expressive code, and it's gonna bundle them together without a separate style sheet that exists just for a single structural component. You're breaking down, when you're breaking your component down into smaller atomic style components that are not all in one place just because one component is using styles that happen to be attached to that structural component. So, a couple more patterns. A lot of other libraries come with composition and mix ins. So the best comparison for mix ins are probably SAS' mix ins. You just have a set of rules, and you wanna inject them into your template string. So you just an interpolation again, you pass it, a static variable. So in this case I just made this stoiberify mix in. So you just have a set of CSS rules, and obviously it's using papaya whip and pale violet red, and if you pass that into that component, text is just gonna apply these rules to itself as well. So, Styled Components still allows you to basically write small mix ins, small collections of rules that you wanna re use across components as well, if, if you choose to do so, but in a contained manner. And inheritance and extending components works as well. So, we have our primitives for that. In this case we have .extend, and with .extend you're just passing new rules, and you're basically extending the previous style sheet. So it's still very much familiar to how you'd basically inherit in other languages, or extend something in style sheets. So in this case the tomato button just changes rules that were already in the button before, and just overrides these rules. So it's just basically like concatenating the two CSS strings. You can apply that same pattern to your own components as well. So if you have for example a React router link, any kind of link, your own components, your old components, you can just pass them into the style function and it's gonna magically receive a new class name, and that doesn't make any difference to the pattern before. That doesn't make any difference to .extend, except that you gotta have two class names if you apply it to styled components as well. Funny little thing is that extend is only gonna be added in style components version two. But right now you always pass your component into the style function in version one. So using the styled function creates one set of styles every time right now. So, this basically sounds a bit abstract, and I hope not, not too stupid, but I don't wanna go through the entire story of Styled Components right now. But I only wanna leave you with a couple of ideas and a couple of, the couple of ideas of Styled Components and those are basically getting out of your way. So Styled Components is just CSS, and we wanna encourage people to just use CSS. What in line styles were introduced, a lot of people were complaining that the syntax changed, and that you're now writing JavaScript updates to declare your CSS properties and lots of people were saying that doesn't make any sense, and the truth is it's probably a preference. But on the other hand if people wanna write just CSS then our idea is to just let them. On the other hand we're enforcing best practises. So the only way to create styles and styled components is to create a component. Everything must be an atomic component, which you can compose, but never can you reuse styles in a way that is similar to the style sheet. You're never going to apply a set of styles to a component directly, but they're always gonna be connected together. So by enforcing this single rule, you're basically going to have a clear structure in your project, a clear rule. So we're just enforcing what was, what BEM was basically telling everyone to do for years. And the last point is very simple. So the last point is just supporting you as users. So Styled Components is very much focused on the developer experience, and this is all to work, while you write CSS, just CSS and styled components, but on the other hand, we're very much looking into creating plugins for your favourite editor. We're looking into making auto completion work as much as possible. We're looking into making it faster, so you don't have to worry about it being too slow. We're basically putting these in a position where you don't have to worry about when to use it, when not to use, or how to use it. So, if you haven't used it yet, and if you're just interested in looking into it then I can happily tell you that the community has been growing over the last half year, and we now have 8,000 downloads a day, and we are the biggest CSS and JS library. So it's just some random numbers, but on the other hand, if a lot of people are using it happily, then I think we're doing something right, and I hope that you will agree. There's a repo called awesome styled components. Just like any other awesome repo it has a lot of libraries and websites in it which are building stuff on top of styled components. It's random collections of nice things. If you happen to use Styled Components in one of your projects feel free to open the PR and add yourself to the list or check out what other cool stuff people are building. And the third thing of this section is there's a lot of similar projects to Styled Components which are looking at bringing it to different frameworks, different communities, and different languages. So we have a version for Elm Lang. Glamorous is a project by PayPal Ken C. Dots, and he's looking into making Styled Components work with just Glamour and without the CSS syntax. So if you prefer to write your styles with objects, you can do that now. Polished is a project that is like Low Dash but for styles. So way before you had your big library of mix ins was SAS with clear fixes or stuff like that. You now have that in a JavaScript library for every CSS in Jest library, and there is a new styled project for Vue. So if you're using that you can use something like styled components. I mentioned styled components version two before really briefly and I just wanted to tell you it's coming out very soon, which we have been saying for like three months, but on the other hand, it's luckily gonna be smaller and faster and we're gonna have pre processing, which was a big complaint by a lot of users. Styled Component is based on its run time and it runs in the run time OND. So that means once you, under, in your project, once you open your browser, it's going to take all your CSS and it's going to chuck them into the head of your document. We can make that more efficient and faster by just pre processing that CSS at compile time in Babel. So we're working on that to again bring some performance boost, plus we're also working on CSS extraction that's unfortunately looking like that's going to do version three, and third thing's just we're introducing some new APIs. We're introducing service at rendering. We're basically cleaning out our closet, and there's a new documentation website, which is also going to be released soon with version. So if you're looking into getting into Styled Components or seeing what it's all about, that's going to be released in hopefully a few weeks. And that's it, thanks.