!= From CSS Preprocessors to Styled Components - Sessions by Pusher

From CSS Preprocessors to Styled Components

Max Stoiber speaking at Reactivate London in March, 2017
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

In this lightning talk we'll speak about moving from CSS preprocessors to styled components, and how you can achieve more maintainable styling in your React project today.


I'm Max, if you don't know me. You can follow me on Twitter. My Twitter handle is @mxstbr, which sounds extremely complicated, but it's actually just my name without vowels. So if you remember my name, you will remember my Twitter handle. I'm here today to talk to you about styled-components. So, CSS. Right? Cascading Style Sheets, we've all heard of that. CSS sucks. CSS absolutely sucks for building component-based user interfaces. All right? CSS was made in an era where the web consisted of documents, right? In 1993, the web was created for scientific documents, and [inaudible] want to introduce something to style those documents. Because if you think about it, a scientist shouldn't have to spend days trying to figure out how to style their scientific paper, they just have to be able to write it, and the browser should take care of that. Right? But in the end, the web wasn't used for scientific documents, so they relented and created CSS. And it was still made for documents. Right? The web mostly consisted of documents. Nowadays, we're building rich, interactive, user-facing applications, client-side applications, and CCS just wasn't really made for that. Right? How can we make CSS better? That's the question I've been asking myself for the past... I'm trying not to step on this train here. There's a train here, if you tweet about this meet-up, this train starts moving, which is really freaking cool. So, start tweeting about the thing, and I'll try not to step on it. So, how can we make CSS better? Especially in React, there's been a lot of experimentation about making it work for component-based systems. And especially recently, lots of people have started releasing libraries and thinking about this. And the first thing that most people do is they colocate and isolate the style. Because if you have an encapsulated component, that styling that affects that component shouldn't affect anything else. Right? If you change the styling of your button, that shouldn't break the way your header looks. That doesn't make any sense. The styling of the button should affect the button, and then you reuse that button component throughout your entire application and that's it. The second step that we've done with styled-components, where we were one of the first ones to do, is that we removed the mapping between styles and components. If you think about it, if you have an encapsulated component like a button, and that has a button class name inside of it, and you reuse that button class name throughout your entire application, the class name is like a mapping front of a fragment of styles, of a piece of CSS, right, to a HTML DOM node, in our case a button node. But if we only ever use that button class once, right, if we only ever associate that piece of styling with this one DOM node, why do we have a mapping there at all? Right? There's no need to have a mapping there if you only ever associate one piece of styling with one HTML DOM node and then just reuse that component throughout your entire application. So those are the core ideas behind styled-components. Making CSS work for building component-based user interfaces. It's made by myself and Glen Maddern. Glen is in Australia. He's one of the co- reators of CSS Modules. That's where you might know him from. And when we sat down, we started thinking about this whole CSS and React thing, and this is where we ended up. So this is what styled- omponents looks like. Admittedly, it looks really weird. When Glen showed me the first prototype of what was going to become styled-components, I looked at it and went, "What the fuck, man? What did you smoke? What is this?" I'm not even kidding. But then he encouraged me to give it a try, and I used it for 15 minutes for something, I can't remember what I built, like a tiny Hello World application, and I loved it. It's so nice to use. It's absolutely incredible. So, let's walk through this. Right? The first thing we do is we import styles from styled-components, nothing fancy going on there. But then it starts getting weird, we say, const Title, notice the uppercase T, equals style.h1. Now, this style.h1 thing is a function.Right? And we call that function, and what it creates is a React component, that returns a React component which renders an h1 DOM element, an h1 HTML tag. So our Title variable here is now a React component which renders an h1 HTML tag. And then, with that style.h1 code, we associate some styling. So in this case, the font size is 1.5 em, the text-align is center, and the color is palevioletred. Now, this is just CSS. Right? This is your standard CSS that you write, in what is called a tagged template literal. So this weird backtick thing there is called a tagged template literal. It's an ES 2015 feature, it's a standard in JavaScript. Style.h1 is a function, and you can now call functions with back ticks rather than parentheses. Okay? So there's some slight differences that I won't get into, you can read the spec if you really want to. But essentially, this is just calling style.h1 as a function, with those styles as an argument. Right? So now our Title variable here is a React component that renders an h1 HTML tag, with a font size of 1.5 em, text-align in the center, and the color of palevioletred. Our second variable here, the wrapper, renders an HTML section. Right? Styled.section renders an HTML tag of section that also has a color of palevioletred, has some padding of 4em, and width and height of 100%, and a background of papayawhip. Now, Title and Wrapper are just React components. Right? You can use them like any other React component throughout your entire application. So if we try to render these two, just like any other React component that you've ever seen, what you see in the browser is a section with a papayawhip background, and a title that is aligned in the center and has a palevioletred color, surprisingly. So that's kind of what styled-components does and what it looks like. Now, the thing that's a bit weird about it is that it lets you write actual CSS. Right? Contrary to some other explorations before us, a big goal of ours was to let you write actual CSS in JavaScript, not just styles with JavaScript objects, for the simple reason that not everybody can write style like JavaScript. Right? My designer has no idea how JavaScript works. He doesn't want to learn JavaScript to write CSS in objects. Right? He knows CSS already, why should he have to learn another language just to style it with the exact same thing? It doesn't make any sense. So styled-components not only lets you write actual CSS, but it lets you support all of CSS. It's what I call CSS...or what we call CSS in JS. Right? So we take that CSS fragment and we inject it into the head of the DOM SS style tag, which means it's just CSS. Whatever feature of CSS you want to use just works. Right? So here we have some, you know, we have the ColorChanger component, which renders the section again, and we use some nesting in here, where any h2 within that component will have the color of palevioletred. And then, we have a media query. Media queries are just CSS, so we can use them. Right? Nothing fancy going on here. If we look at this in a browser and we start resizing this, the color of this will change from palevioletred to mediumseagreen. Right? There's nothing fancy going on here, there's nothing special going on, it's just the CSS media query. But it's to show that whatever you want to use in CSS, any pseudo selector, any media query, anything you can come up with just works because it's just CSS. Now, when we think about React components, something that comes up very often is adapting based on props. Right? Let's say you have a button component, and very often with a button, you have a primary variant of that button, which is bigger and more important. Right? So with React, we have this thing where we pass a primary property to our button component or any other property. And with styled- omponents, you can adapt to the properties of your component from your CSS, so you can interpolate the function and we pass the properties that the components gets passed as an argument to that interpolated function. Which means, right here, we're basically saying the background should be palevioletred if the if the primary prop is set and white if the primary prop isn't set, and the color should be the inverted one, so if the primary prop is set, the color should be white, and if the primary prop isn't set, the color should be palevioletred. Right? Again, this is just JavaScript. There's nothing fancy going on here. We execute these functions and pass in the properties that your component gets passed. So if you render two buttons, one normal and one primary, and we look at those in the browser, we have a normal button and a primary button. Surprisingly. Now, many languages before us did many of the similar things that styled-components also did, but one thing that almost nobody had was theming. When you have a component-based system that's very encapsulated, where all your behavior's encapsulated within tiny components, there is some things within the styles that you want to adapt, and want to be consistent across your entire application. Right? Think about your brand colors, you don't want to use a different shade of blue on every single page, you just want to use the same blue that your designer gave you. Right? You don't want to have to figure out which one it is every single time. So with styled-components, we added theming support, which looks like this. We have this ThemeProvider component that you can just import, and then define anything that you want. So in our case, we're just going to set the primary color of our entire application to palevioletred. Right? And then, we wrap parts or the entire application in a ThemeProvider. Any styled-components within a ThemeProvider will get that theme provided to it. Which is why it's called the ThemeProvider. Right? Captain Obvious. So, if you take a look at our styled-component now, we have this props.theme variable, which is magically injected by styled-components, and you can adapt your button styling based on the theme of the ThemeProvider that it's within. What that means is essentially, right now, with just a single ThemeProvider, we'll have a palevioletred button. Right? But we could just as well have a red theme and a green theme and we could render different parts of our application in the red theme and in the green theme. And what's important to note here is that nothing changes about the button itself. Right? We don't set any property on the button, we just render them within different contexts within our app. And what happens is that we have a red button and a green button, because it dynamically responds to the context that it's in, to the theme that it's in. This theming uses the React context feature, so it's literally context. Which means it works as many DOM nodes or components as you want themed. Right? No matter how many levels of components and DOM nodes are in between your ThemeProvider and in your styled-components, they will get the theme. Now, when we finished building styled-components, we used it, and we loved it, basically. I didn't want to... When Glen finished the first prototype, I told him, "I never want to use anything else anymore." Right? This is the best... Like, this feels the best way of styling my applications I've ever tried, and I've tried every single freaking library out there. Right? It just feels really good. But then, I had to write a ReactNative application and was back to square one because I suddenly had to write CSS and fake CSS in JavaScript objects again. And I really didn't like that, so styled-components, we also added full ReactNative support, which looks exactly the same, apart from one tiny difference. You import style from styled-component/native, and then you get access to the native primitives. So here we say that our wrapper is a style.view. Right? A view, for those of you who don't use ReactNative probably, is kind of like a div, except for ReactNative. Right? And then we associate that style.view with some styling again. Same thing for the title, we just say style.text, rather than as style.h1, what it would be on the web, and associate some styling with it. And when we render those, just like any other React components in our ReactNative application, we get a ReactNative application that styles with styled-components. Now, I can stand here all day...I can't because it's a lightning talk, but I could stand here all day and talk to you about how awesome styled-components is, but I can also let other people do that. This is Sebastian McKenzie, whom you might know because he made Babel, and now works at Facebook and lives in London. And he wrote, "I fucking love styled-components. So good. Thank you so much for making my life easier." Then we have Griffin, who apparently works at Reddit, who loves styled- omponents, and they're going to use styled-components for their new architecture, probably, which is awesome. There is a person who wrote, "Using styled-components is so pleasant that I migrated some SaaS to it as a therapeutic exercise." Now, I'm not a doctor, I'm not advising you to do this if you're stressed, but it could be worth trying. Right? If you're stressed, just migrate some SaaS to styled-components, and apparently, it's a therapeutic exercise. There is Max, who wrote, "I started using styled-components and I love it." Again, I'm not a doctor, if you're in love with a library, maybe consider going to, you know, therapy, but not the styled- components one. And there's a ton of other people that also write a bunch of really great stuff about styled-components. The reason for that is, I think, that it's just really nice to use. Right? It looks really weird, but the development experience of using styled-components, it just fits my mental model of writing React applications really, really well. Thank you. And if you come find me around the meet-up, I have some stickers.