 Welcome to Designing in the Browser. In this series, we explore how to take a design, build it, and then tweak it in the browser using the latest in web technology and design systems. Today, we're going to take a look at how we can extend the capabilities of vanilla CSS with pre and post processors. In many design systems like material design, we use SAS as a pre-processor to give us a ton of power and control over our code, as well as a post-processor post-CSS to make sure it works across the browser. There are a lot of benefits and different ways to do this. So let's dive in. So why would you need to extend CSS? It gives us so much styling power, but there's a bit more that we may need in order to tailor CSS to our own needs, especially with design systems. A big reason for using CSS processing tools is easier maintenance and browser support. For example, we now have dynamic variables with CSS custom properties, but we didn't have that capability a few years ago and older browsers like Internet Explorer 11 don't support some of these newer features like custom properties. With a pre-processor, we can store these variables as static values, meaning they can work across browser. We'll often see pre and post processors being used in large design systems and projects. Material Design, Google's open source UI design system, uses SAS as a pre-processor and post-CSS as a post-processor. If you're not familiar with material design, check out material.io for more information and for resources. On the web platform, using SAS allows for material to create an API for our design system and specify what you can do to extend the system while still maintaining its integrity. For example, material includes mix-ins like MDC button ink color. You may be thinking, why use a SAS mix-in instead of just writing color and the color that you want there? The reason why is because the output of the mix-in looks like this. We need to keep various states in mind without overriding each other's styles, and the way to do that is with an explicit API. Here's another example. This would output to this. So you can see that while it seems like changing the field outline color through a mix-in isn't really doing that much. It really is. Three different classes and various pieces of that element are updated through that single line of code. This actually gets more complex with some of our components as their APIs become more complex. Here's an example of a masonry image list where one of the mix-ins involved specifies how many columns to include and what the spacing should be between each image in that list within the columns. So the code for that becomes this. It affects not only the element itself, but also child elements to make sure that the spacing is correct not only horizontally, but also vertically. This image list is one place where we can really see the benefits of using SAS in our UIs. In this example, as we resize this image list to be smaller, the number of columns and the spacing between those columns decreases as the size of the screen gets smaller. And vice versa, increases as the size of the screen gets bigger. And so this is a part of that styling API. If we look at the code here, what we're doing is we're starting at the baseline. We're starting at that mobile view with the columns being 1 and the spacing between those being 0. As you start to get bigger, for example, at a screen of 500 pixels or larger, we're now going to be at two columns with 8 pixels between those items. We're getting a little bigger at 800 pixels. It goes to 3. Right here, you can see that is being included as a mix-in called MDC Image List Masonry Columns. And we're using the same mix-in throughout to then at 1,000 pixels provide 4 across and at 1,200 pixels provide the 5 across. So here, with just a couple of lines of code, we're changing the entire layout. This responsiveness is included as a part of the styling API for our components. As I mentioned earlier, MDC Web also uses post-processing for our CSS. The most popular technology to do this is called Post-CSS. We use Post-CSS to make our CSS backwards compatible for older browsers. An example of this is adding prefixes to certain properties like column count, which we just saw in the Image List example. With auto-prefixer as a part of Post-CSS, we don't need to memorize which properties do and don't need a prefix as we extend our CSS styles. And so what that looks like without the processing is this. And then when it processes applying those prefixes, it becomes this. Soon, CSS will give us the ability to natively extend it and do all sorts of things with a technology called CSS Houdini. With this technology, developers now have access to the CSS Object Model for the very first time. Houdini is a series of browser APIs that allows developers to tell the browser how they want it to read and render CSS, along with a slew of other performance boosts and really great benefits. The current APIs for Houdini include the Layout API, the Paint API, Properties and Values API, Animation Worklet, and the Typed Object Model. We'll talk about Custom Properties API in another show, but for now, I want to show you the power of the Paint API and how you can use it today to extend a system like Material in a progressively enhanced way. So in order to do this, I quickly want to talk to you about shape within Material theming. Material includes shape as a core part of its theming subsystem. Shape is an integral part of an application style language because it can be used to indicate state. It can also bring the user's focus to a specific area like a menu bar or an action item. The floating action button, for example, is round and lives in the bottom of the web page permanently as a consistent action source. The round shape contrasts the web page as most elements in a web page are rectangular in shape. To help you determine the shape for the look and feel of your application, Material provides a tool called the Material Shape Tool. You can find this on material.io and go to the Shape subsection underneath Material Foundation. So this shape customization tool allows to explore the different types of components and what they look like with various shapes. The first are small components. These are things like buttons. So you can apply various rounded shapes to the button. We even have angled corners as a shape option, which is a cut corner on each of those edges. Also medium components you could play around with. So here we have things like dialogues and cards. And then larger components are things like your menu. So you can have those be rounded and bubbly or have them be more straight across or rectangular and angular. You'll notice that in this tool we have two corner shapes, rounded and angled. While on the web angled corners are not currently possible as a part of today's browsers, this is a system that spans platforms and angled corners are possible on Android, Flutter and iOS. Angled corners have been discussed by web standards since 2012, but we have yet to see them implemented in browsers. However, with CSS Houdini, nearly anything is possible. So I made a little demo to show you how we can have angled edges on the web today. So in this example here, I'm just gonna zoom in. We have these material buttons and we have these adjusted buttons. Now they have the ripple and everything applied to them when you click. So you can see that there are the exact same sort of interactions here. We even have this button popping out for that raised material button. But these buttons on the bottom have that angled shape. So the way that I did this was with a worklet. Let's get into that. Okay, so first to understand the requirements of this demo, let's go over the types of material design buttons. The first button is a standard button that just goes on the backgrounds and when you hover over it, you can see a subtle outline of that button and when you click on it, you see it a little bit more pronounced. Then there is the outlined button. The outline button has an outline around the button which matches the color of the text within the button. The filled button has a background behind the button and then there is the raised button which has a drop shadow underneath the button which extends as you click it or as you hover over the button. So we needed to make all of these work. We needed to fill all these use cases. We also needed to make sure that this ripple effect is still working and does not extend our element. So when I made these angled corners, the first thing I thought about was using a mask because when we mask an element, we are preventing anything from going outside of that element. So here we have a mask set which is using this angled corners worklets and it's using the filled mode. So I've used a custom identifier as an argument inside of this paint worklet. So here I can mask all of these buttons, all of these buttons that have the angled class applied to them and then for the outline buttons, I'm specifying this outline mode. I'm using the exact same worklet but I'm using it as a border image. So here I'm painting it as a border image as well as using it on mask on the same exact element. So it's pretty dynamic what you can do with these custom properties. If you wanna take a look at what that code looks like, here I have a few input properties. Those input properties are corner radius, the stroke weight and the paint color. So we can adjust the radius of those buttons, the custom identifier as the input argument for the mode, the filled or outline mode. And then I'm going through, I'm looking at every single corner and I'm adjusting those corners based on the inputs. So I can make these corners uniform or I can change what those radiuses are. So here I have 12 pixels and then 0, 0, 0. But what if I wanted to make this like 20 and then 0 and then 20 and then 0? You can see it's starting to paint in. So I have the ability to every single corner adjust the angles. I have the ability to specify the type of transformation I want here, whether that be a rounded button because we can just do that in CSS, whether that be an angled button, Houdini gives us the power to do that. And I can specify how I'm using that worklet. So I can use it as an outline, I can use it as a background. I can use it as both in the example of the outline button. That's exactly what I'm doing. With the raised button, I did have to adjust the HL markup a little bit to give it a shadow container because of what WebKit Mask does, which is prevent anything from living outside of that mask, which was needed for the ripple. So I did add a little bit of markup here for the shadow container, but you get the same effect with the MDC button by applying the same kind of transformations on the shadow container. If you wanna explore this demo a little bit more, we will link this in the show notes. It is free for you to explore, it's free for you to use, it's free for you to build upon. It's a really interesting upcoming technology that will provide us so much more power with CSS. So I'm really excited for it, and I hope that you are too. CSS is such a powerful tool and we can leverage its powers to have even more control when we use extension tools such as post-processors, pre-processors, and Houdini. What do you use for your styling setup? Leave a comment down below, and we'll see you next time. Say bye Disco!