116: Styled Components and Functional CSS with Kris Van Houten
In this episode, we are joined by Kris Van Houten to chat about Functional CSS and Styled Components: pros and cons, the problems that they are trying to solve, and how to choose between one or the other.
In this episode, we are joined by Kris Van Houten to chat about Functional CSS and Styled Components: pros and cons, the problems that they are trying to solve, and how to choose between one or the other.
This show was produced by Mandy Moore, aka @therubyrep of DevReps, LLC.
DAVID: Hello, everyone. Welcome to Episode 116 of The Frontside Podcast. I'm David Keathley, a software developer here at Frontside and I'll be your host for today's episode. Joining me as a co-host is Jeffrey Cherewaty.
JEFFREY:: Hey, there.
DAVID: And we've got an amazing guest with us today, Kris Van Houten. Kris is the author of a very interesting functional CSS library called Elassus, a good friend of mine and today, we're going to be talking about how that compares with another new pattern I've been seeing everywhere recently: styled-components. Hi Kris.
KRIS: Hey, how's it going?
DAVID: Doing great. Let's just go ahead and jump into things. Kris, you want to give us a little introduction to your functional CSS library?
KRIS: Yeah, for sure. I guess, first of all about me. I've been primarily a frontend developer for about seven or eight years now. I don't know, at some point you start losing count but over the years, I worked largely within the Ember framework but I've also worked within React and Vue. Like most of developers over the years, you tend to require an affinity towards certain areas of software development and for me, those areas tend to lean towards accessibility but also, learning how to write CSS with what I call like the future in mind.
To try to keep the story as short as possible but a couple of years ago, I was working on a project and started to realize that our CSS is one of those things that just continues to grow over time along with the rest of our application but I also noticed that we tend to have a lot of areas of repetition within our CSS, like how many times are we setting text align to center, how many times are we setting the text color to the primary color or to gray or something of that nature and maybe we could create a utility library that just does all the stuff for us, similar to if you've ever worked with Bootstrap that they had utility classes that allow you to do some things like set the text alignment or the text color or font size and things of that nature.
I started thinking around it but eventually, I changed jobs and that idea kind of just went to the side but then, I'd say about a year and a half or two years ago, I came across a blog post called '15kb of CSS is all you’ll ever need' and so, immediately I was intrigued. It was actually a blog post on Medium that was talking about the benefits of using something like Tachyons or base CSS, which are two different functional CSS libraries. To explain what I mean by functional CSS, it's just a whole library, a whole arsenal of these utility classes that just do one or two things that allow you to basically take any design and implement it by composing all these classes together throughout your HTML.
I was looking at Tachyons, looking at base CSS and thinking, there's a couple of things I like to customize about this but at the time, when I was looking at it, I couldn't really figure out how to customize those values very easily and so, I did every developer does and just decided to make my own and that's where Elassus came into play, where it's a CSS library that is entirely made up of functions that generate your CSS based off of the value of variables in Sass. Everything is customizable, all the way down to how the class names look and the syntax that you use. If you hate what I'm doing, you can customize it very easily.
A lot of people might wonder why would you want to use functional CSS, what are the benefits that you get out of it and really, one of the first two things that comes to mind for me that really attracted me to it was that your CSS files start small and they stay small. For the most part, depending on the configuration and the particular library that you're using, your entire CSS payload can be anywhere from 10 to 20 kilobytes, minified and gzipped, which is in stark contrast to some other projects I've worked on, where just one of the many CSS files you're downloading are 745 kilobytes. Dramatic improvements there, so that's why it was instantly appealing to me.
But one of the other nice things you kind of get for free by default is a consistent design pattern, right out of the box. Because if you're working on a large team that has maybe multiple designers and many developers, one designer might implement something with the spacing system that's maybe based on five pixels: your padding, your margins, your widths, might be five, 10, 15, 30 pixels, 45 pixels but then maybe, another designer is implementing something based off of more material design, which is base-4 pixels, so it's like four pixels, eight pixels, 16 and so on.
Over time, little differences like this can really show up as you navigate between pages of your application and with functional CSS, you're given a limited number of options to choose from. As a result, it actually makes your application feel like it's one cohesive consistent piece of software between pages and between the features that you're navigating through. Those are really two areas that have really attracted me to functional CSS and I guess, is a tl;dr -- if that was a tl;dr in fact -- of what functional CSS is and why I like it.
DAVID: One of the things we've got here was the problem that functional CSS and styled-components are both trying to solve.
In CSS cleanup is just one of those things that often doesn't get cleaned up as often as you would like. Sometimes, that's also because we assume that a particular set of styles is probably getting used by another team, working on a completely different part of the application. As a result of just not being able to work on this problem or this issue, we likely have many, many kilobytes of orphan styles being shipped to our users at the end of day and our style sheets tend to grow over time. If there's one thing that's kind of become a mantra within software development over the last few years, it's that every kilobyte matters.
KRIS: Yeah, indeed. I remember listening to a podcast about two, maybe three years ago and they had a panel on and they were talking about there's a new thing called CSS and JS and I was like screaming in my car like, "This is the most horrible thing in the world you could possibly do. Why would someone want to do this?" and obviously over the last couple few years, the technology has definitely matured and they definitely hardened it, to where when I was working on updating my personal blog, working on moving over to Gatsby, I didn't want to have to pull an entire functional CSS library because I kind of thought that would be overkill for just a couple small pages and so I was like, "Let me try this whole styled-component thing. That way if I'm going to hate it, I can hate it from the experience point of view."
I actually found that the developer experience of working with styled-components was really nice and so, I kind of became converted over to that way of thinking about, "I'm not a hater. It's actually a really nice way to write your CSS for your blog or your applications."
JEFFREY:: I count myself still as a skeptic about this whole idea, so I'm excited that we're going to talk about it now and then, you have the opportunity to sell me on it, which should be fun. Some of the work I've been doing on lately, we've been doubling down on the idea of CSS modules, that at least fix some of the encapsulation and problems around CSS where everything is sending up in a global scope. How do these ideas of functional CSS kind of take that even farther? What advantages are there over using, just simply using say, CSS modules where we're fixing the global namespace.
KRIS: I'd say with functional CSS, again the things that kind of mine for me are you keep the file size small, you have your design patterns that you can get for free right out of the box. Your styles are pretty low specificity, meaning that if you ever have a need to where you get a really customized something because you just can't do a functional CSS, which I found to be very, very few and far between as far as the number and instances I've come across, it's very easy to overwrite if you need to go back into, I guess old fashioned way of actually writing some CSS yourself.
But then you also have the benefit of not having to come up with clever class names to describe the different states or different use cases of your component that you're working on or the future that you're trying to implement and so, I'd say those are definitely some of the pros of why I like using functional CSS at the end of the day. I will say that there are some cons -- I'll be completely honest -- and say that one of the areas where functional CSS tends to have a weak spot is in the area of browser specific issues.
In my experience, I tend to have a lot of issues with iOS Safari and it's like the bane in my system sometimes. Sometimes, worse than i11 but if you have to really target something that's exclusively for a specific browser, that's really not doable from what I've seen in functional CSS. That's where we should have to go back in and handwrite some CSS for that kind of situation.
But also, one of the cons is that sometimes, depending on the element or the component you're trying to style, I think the example is if you have a nav bar that can toggle between being a sidebar but also a top nav bar, that's a completely different set of styles and to achieve those few layouts at the end the day, you have to have a completely different collection of class names that you have to toggle between based off of the state of that component or that feature that you're working on. While that's doable, especially with something like a frontend framework like Vue, React or Ember, it's just a little pain point that sometimes you have to work around but I say, those are the pros and admittedly some of the cons of using something like functional CSS to tackle your styling needs.
JEFFREY:: My favorite thing that you mentioned there was how hard naming is. I think everyone can agree, very strong of it, just naming things is the hardest thing. What has been your experience in learning these? They're almost new domain languages for like we want to padding of this amount. Have you found that pretty easy to get up to speed and get fluent in or have you run into some blocks in kind of learning these new languages that some of these CSS tools have presented.
KRIS: That's a really good question. When I first started digging into Tachyons -- that was the first functional CSS library I started working with -- there is definitely, I'd say a small learning curve of maybe, I was trying to implement it just to see how it worked and it took me, maybe a couple of hours, if that, to kind of get a feel for how they write their classes and how the classes are put together to do certain things. But once you kind of get through that little initial pain point, it's pretty easy.
In one of the things that when I was working on my own implementation of it, I wanted to make sure that no matter what you're doing, all the class names are consistent, that the patterns that you use to your class naming is consistent and I guess, because I wrote it, then it wasn't so hard for me but I also understand that that's not the case for everybody. When I wrote Elassus, one of the things I did is I actually was able to create a compiled JSON version of all the CSS and actually, use that to create like a little React search tool. If you're looking for padding or margin, you can just enter that in a search bar and it'll tell you all the options in the classes that are associated with that and that's one thing I did to kind of help with that barrier but it definitely can be a bit of a learning curve but like I said, it's maybe an hour or two of your time to really get familiar with it.
JEFFREY:: That is not bad.
KRIS: No, not at all. I was actually really surprised at how fast I got up and running with it.
DAVID: That actually ties into something that I was kind of curious about myself. Whenever I went through the coding bootcamp that I did a couple years ago, after we finished going over raw CSS and how that works and the basics of that, they introduced us to Bootstrap as our first real CSS library to play with. That was fairly achievable for someone brand new to frontend work in general. What I was curious about is would you see these functional CSS libraries as equally accessible or maybe, more advanced than something like Bootstrap or Foundation.
KRIS: I never thought about that before. I think I kind of see it like as the next step. I've worked on several products over the years where Bootstrap was what they started with. As we went on to build out the feature set of the product, we started to find ourselves battling with the various styles that we get at from Bootstrap for free. I think one of the things about working on a website, where actually using Bootstrap is that sometimes you can just kind of tell that it's a Bootstrap based website. I don't know if I'm making any sense to you guys --
DAVID: Oh, yeah. Definitely.
KRIS: That was another reason why I wanted to have something... That had basically forced me to decide how my navigation bar looked. It forced me to think more about how my sidebar is looked or what my spacing scale -- it's the term I like to use -- based on what you're using for your pure margins, your paddings or what's your heights, things like that. It make me think about what those values should be and that's how you kind of break out of the box of having everything look like it was built in the same framework.
I would say it's more of a next step if you're talking about your experience as a developer. Yeah, learn CSS. I think it's still incredibly valuable to know CSS and for me, like you David, I kind of got started and learned about this thing called Bootstrap and you can quote me. Back in the day, I said, "This is like the jQuery for CSS. It's amazing," but quickly, I kind of ran into some of those issues that I mentioned earlier and kind of force me think about, "Maybe, I don't want to use Bootstrap. Maybe, I want to handle my own thing," and so, I say functional CSS, as far as like again your education level, it's more or less that step of if you think about how do you want to solve certain problems in our design.
DAVID: Okay. We've gone over functional CSS with some and styled-components, how would you choose between the two?
KRIS: This is actually really hard because I actually like both approaches. I'm not one of those guys that's like, "That one sucks. I don't want to use it." I actually think both have their place and so, I know I kind of sound like the typical 'this versus that' blog post in technology right now but I will say that there's a few questions you should ask yourself and ask your team if you're considering changing up your approach to CSS. One of those is what is the preferred developer experience of your team. That's something we've been talking about a lot at the company.
Again like I said, one thing I love is that both approaches remove the developer's burden from having to come up with clever class names for all the different use cases or states of your components. I think you're going to get a win-win either way there. However, if you're using React, we already have a ton going on in our JSX and so, if adding a series of class names to determine your design tips is overwhelming for you, then maybe give styled-component a try because it can definitely simplify your JSX output a little bit.
With both of those scenarios, easy theming in patterns is possible in both. It's just one is harder in one than the other. With styled-components, there are implementations of it in Vue and Ember but they don't seem to be very widely used yet, so I'd say use at your own risk or contribute to open source to make them better. I'd say for right now, if you don't mind being locked into using React, then styled-components is pretty cool. It also allows you to transfer your styled-components from one project to another without having to worry about. [inaudible] all the CSS because that's a big deal but I would ask myself those kind of questions to determine what solution I would choose.
JEFFREY:: I am interested in the performance implications of these tools. You touch earlier on by using tools like this, you can definitely shrink your CSS payload by a lot, so what is the actual output of using these tools? What will it look like? Do you end up with still an external CSS file or is it a scenario where you're kind of getting some CSS injected into your markup?
JEFFREY:: Yeah, I agree with the ergonomics do feel weird but you'll get some benefits out of doing that. In the styled-components where it'd bring on the fly, I'm happy to kind of figured out the performance like runtime implications with that but it seems to me that now you no longer have a cache CSS and that you're having to get that all the time on the fly. Maybe for some systems, that is okay but that's definitely something that I would miss having -- the idea that CSS actually can be a little heavier because it will always be cached.
KRIS: That is totally a valid point. I think one thing I do kind of like about the styled-component approach is that when you delete a component, all the styles go with it, so you no longer have orphaned styles just hanging out there that are getting shipped down to your user. I agree that the caching is definitely a concern but I just kind of start to weigh the pros and cons and again, you have to decide for your product, for your team what works best for you. Also, one of the pros that I would bring up is that you don't have any orphan CSS hanging out in your application anymore, which is definitely one of the key contributors to growing bloat in your files over time.
JEFFREY:: That is very nice.
DAVID: That ties into a question that I was kind of wondering. As your projects get larger and larger and more complex, your style sheets tend to grow along with that and one of the issues that you might have as time goes along is visual regressions like styling bugs. How does using functional CSS or styled-components sort of deal with that or prevent that?
KRIS: With functional CSS, like I said, you have those patterns kind of built in out of the box. As long as you don't change the value of what a particular class renders out of, maybe someone goes in and without thinking of it, they change the second value of your spacing scale to a lot of pixels just because they felt they needed to. You're not going to have visual regression that happen over time because the whole premise of functional CSS, those values don't change. Those are basically meant to be seen as immutable values, immutable classes. You shouldn't have style regressions that pop up over time as people continue to work on your application.
With styled-components you still have that risk unless you are setting all those same values and your theme properties that you can use within styled-components. Unless you're setting all your different spacing values, you have a tendency to potentially run the same issue. But actually, now that I think about it, maybe not because with styled-components, every component is unique. Every components styles are completely unique, so again, unless you're changing those core values of your themes, you should not have visual regression that happen in a totally separate part of your application when you're working on say, the home page. I would say both handle that pretty well, now that I'm thinking of it.
DAVID: That's cool.
KRIS: This reminds me, I'm working on a particular piece of software at a particular feature of my work and we don't use functional CSS or styled-components yet. I'm trying to get them to move over so again, this is all stuff I do on my free time but I'm working on editing a component and I had to make some pretty drastic changes to it and I was like, "How is this going to break on some other page that I'm not aware of yet," and so, this requires a lot more going back and checking all the various uses of this particular component. We used it in 10 or 11 different places on different pages and so, we have to go back to each and every single one of those use cases to make sure I didn't break something. Whereas if I was using one of these two approaches, it wouldn't be something that I would have to be concerned about. This is what I'm trying to push through on my own job as well.
DAVID: Yeah, it really eat up your time.
JEFFREY:: I want to talk for a few minutes about media queries because, I think that the situation is kind of handled. It's definitely something I've run into: CSS variables and with post-CSS tooling. I'm interested in kind of how does the media query story is handled with the setup.
KRIS: With functional CSS, you tend to have, basically say, I have a class that sets a margin on the top of 16 pixels, for example. Let's say that that class name is MT-3... I don't know, meaning for like the third position in your spacing scale, 'MT' stands for margin top. If you wanted to only use that style for perhaps, like your medium break point, then different libraries have a different way to approach this, basically, you're 'MT-3--medium' or '--desktop.' It's the additional characters that you append to the class name to target that specific media query.
Also, depending on the framework that you're using, you can also target pseudo states, whether or not this element is focused or on hover, maybe you want the background code to change. There's variations of those classes that allow you to target those specific states, which is really nice in functional CSS. Again, just by looking at the classes that you're adding to your DOM, you don't have to scroll through your style sidebar to figure out like what styles are associated with this class name and why it's being overwritten by these 10 other things that we have going on. Again, you can just look at the HTML and see what's happening and what should happen if you hover over an element.
With styled-components, you can still use media queries and all that stuff right out of the box. In order to keep your media queries consistent, that way not everybody is having a handroll, at least by every single time that you need to use them. You can actually store your media queries in a separate JS files and it's kind of import them as you need them, which again, kind of feels like a weird developer ergonomic for your CSS but definitely, it comes in handy and definitely keeps your styling consistent the more you break out the various pieces into small pieces or small components like that. That's how to handle things like media queries and things like that.
JEFFREY:: It's interesting how these approaches are kind of pushing the web towards, I'm feeling a lot more like native development, where you build your style and your visual look in conjunction with your component code and those things are not really ever separate. I think, there's some interesting influences coming in there from some made up things.
KRIS: One thing I think about a lot, especially when I'm thinking about functional CSS is I'm reminded of this image I saw kind of posted on Twitter somewhere in the interwebs. It was a picture of the Super Mario Brothers start screen and the entire Super Mario Brothers video game was something like 23 kilobytes. This screen that you're looking at, which was like the start screen was like 345 kilobytes or something. My numbers are probably off but it was something drastic like that and this makes me think about, if you were to go back through, there's a couple of documentaries about how the loops that developers had to jump through in order to make old video games for Nintendo Entertainment System back in the late-80s -- I'm probably dating myself right now -- but the things they had to go through and to think about in order to make those games work the way they did is insane and I kind of feel like over the last... I don't know, maybe 10 or 15 years, because we've gotten such fast computers and such fast mobile devices and so on and so forth, we've kind of gotten crazy.
I look at video games now and they're 100 gigabytes sometimes and I kind of feel like they didn't need to be 100 gigabyte video game and I think --
DAVID: But it's so much cooler because it is.
KRIS: I'm not saying it's not cool but I'm think like if they really took the time to pay attention to some of these details, we probably could automate this a little better. Maybe, I'm just being biased but I think about we're kind of starting to do the same thing and talk about the same kind of problems in web development. Again, just because we can have a 745 kilobytes of CSS file and thought the world falling over, it doesn't mean we should, so maybe, let's take into consideration that not everybody is using a cinema display on a super-fast MacBook to view your application, what about the person who's using an outdated Android device that hasn't been updated in three or four years? How's your product going to work on their device?
I'm really glad that people actually started to take that kind of thing into consideration and it even reminds me a little bit of another area that I think a lot about is the area of accessibility: how do people with various impairments or disabilities use your software and how can they use your software but also, outside of that, how do people, who maybe don't have the money to have a fancy mobile device like you have, use your product along those same veins. It kind of dips into the same vein of accessibility when we're talking about how do we optimize our products to make them usable by everyone despite their income level or their ability to have a fancy, nice desktop or a latest iPhone.
DAVID: Yeah. Definitely, you think about who are the majority of users on the internet these days and really, it's an emerging market with underpowered devices and the internet is becoming much more and more accessible for people to get on and browse, so you really got to keep those people in mind.
KRIS: Definitely, especially if you're creating software that you want people across around the world to be using, a lot of people don't have access to crazy high speed internet like we do here in the States, so we should probably be taking more time to consider what it looks like for those people to use our product. At my company, what we've been talking about is like we should be testing and basically, starting mobile first with all of our development to see how does this work on our mobile device.
I'm a remote developer so we're trying to figure out how to get me mobile devices that I can actually test on our VPN but it's something that we're trying to move towards at my company as well.
DAVID: Okay, that about wraps up Episode 116, our final episode of 2018. Man, the year has gone by fast. We are the Frontside. We're the frontend specialists who make your largescale application projects run smoothly by helping your team assemble the right tools and implement the right automated processes. We can ensure your projects can move forward on time and without regressions while preserving quality and long term maintainability.
If that's something you're interested in, please get in touch with us at @TheFrontside on Twitter or Contact@Frontside.io via email. Do send us any questions you might have, any topics you'd like to hear about in the future. We look forward to hearing from you. Thanks again to the wonderful Mandy Moore for producing today's podcast. You can find her on Twitter at @RubyRep and that's it.