Encapsulated CSS - How to Apply CSS in a Composable Way
Knowing where to place your styles is critical to understanding composable layouts. Using the Principles of Encapsulated CSS you will know exactly how to apply your layout styles in your components.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
Lesson Transcript
[00:00 - 00:08] What's up guys? Travis here with another lesson in composing layouts in React. Today we're going to learn about encapsulated CSS.
[00:09 - 00:24] Now that we understand the power of composition when working with layouts, the next obvious question is how do we apply this in practice? One of the more important parts of building composable layouts is knowing at which level of your component tree you should be applying your styles.
[00:25 - 00:39] This is why I have compiled some important principles I like to call encaps ulated CSS. encapsulated CSS is a term I use to summarize the rules of how to apply CSS styles in a composable way.
[00:40 - 00:50] It's based on the programming principle of encapsulation. Now here's my best attempt to define encapsulation in a language agnostic way.
[00:51 - 01:06] encapsulation involves grouping related things and restricting access to those things except through appropriate channels. For example, many languages utilize a module system which follows the principle of encapsulation.
[01:07 - 01:21] When you import a module like React, you get a group of functions that help you build a React application. Here we have create element, use state, use effect. All of these are part of the React namespace.
[01:22 - 01:39] However, you don't have access to the actual internals that make the React application work. Those internals are encapsulated inside of the React namespace, and only through the exposed functions can you access the React internals.
[01:40 - 01:57] In object oriented programming, one often implements encapsulation via private properties and methods like this. Here we have a person class with two private properties called first name and last name that are marked private with that hashtag at the beginning of each of them.
[01:58 - 02:15] And then we have a constructor that takes an object with the first name and last name and assigns those values to those private properties. Finally, we have a method that returns the last name and first name in a string .
[02:16 - 02:29] We can create a new person like Robert Smith. We can get the name, as you can see, where we call get name and it returns Smith comma Robert.
[02:30 - 02:50] But we can't change the actual private property because that is a private property that is not available outside of that constructor when we first knew up the person class. Functional programming would probably use closures to achieve something similar .
[02:51 - 03:07] Here we have a function called the person name factory that once again takes an object with first name and last name. And it returns another function that when it's called will return that same full name string.
[03:08 - 03:21] So we can call that person name factory with Robert Smith and get a function that we can call get Robert Smith's full name. And when we call it, we get Robert Smith's full name.
[03:22 - 03:36] Once again, we still we don't have access to those values inside of that function, the person name factory. We only have access to call the function that is returned.
[03:37 - 03:49] Both of these examples, you have values that are grouped together and you access them through a restricted function. A restricted or appropriate channel.
[03:50 - 04:10] encapsulate CSS is based on that same principle is a methodology that helps you group together related styles at the correct component level and only applying styles through appropriate channels. Why is it encapsulate CSS the key to building composable layouts?
[04:11 - 04:23] Well, the biggest enemy to composing layouts is when components already have built in opinions on how they should be laid out. Have you ever had an element or a component that wouldn't lay out on the page the way you thought it should?
[04:24 - 04:39] Only to find out that it had some built in margin or width that was interfering with what you were trying to do. The rules of encapsulate CSS help you avoid this by showing you where to apply your styles in a way that won't conflict with the environments that are being used in.
[04:40 - 04:54] So the question is how do you apply the principles of encapsulation to CSS? I'd like to take a step back and revisit the CSS box model.
[04:55 - 05:04] In the box model, an element is comprised of multiple layers of boxes. These boxes are wrapped around the content of our element, kind of like an onion.
[05:05 - 05:13] The first layer around the content is the padding box. Next we have the border box and then finally the margin box.
[05:14 - 05:30] If I were to ask you at which layer or layers are considered part of the element, at which layers are considered outside of the element, what would you say? An excellent start would be to think how elements are sized.
[05:31 - 05:55] By default, an element size is calculated based on its content plus the padding box plus the border box. For example, if you had a border of one pixel and a padding of one pixel, then the contents in line size would be 14 pixels wide if you had a 10 pixel content .
[05:56 - 06:16] That means we have one pixel on each side for the border, one pixel on each side for the padding and 10 pixels for the actual content, meaning 14 pixels wide in total. Now what happens if we add 10 pixels?
[06:17 - 06:30] The elements in line size or its width would still be 14 pixels. This is because margin describes how much an element pushes away from other elements, but doesn't contribute to the element's actual size.
[06:31 - 06:51] In other words, the margin layer is considered outside of the element. For further confirmation, the box sizing property, which is used to determine how the element size is calculated, can accept three properties, the content box, padding box, or border box.
[06:52 - 07:12] There is no margin box property, so it's pretty safe to say that the border box is the boundary of our components encapsulation. So with that background knowledge, there are two essential principles of encaps ulation access to consider.
[07:13 - 07:30] The first principle is components do not lay themselves out. The properties responsible for the layout of a component like its position, size, or margin are not the responsibility of the component itself and should not be applied at this level.
[07:31 - 08:00] So setting a display to inline a width to 100 pixels, a margin top to two rims, or setting even the position to being relative, that is not the job of the component itself and should not be set on the component or element itself. The second principle is components style themselves and layout only their immediate children.
[08:01 - 08:15] Properties then involve the border box and in order are considered part of the component. And those should be applied at the component level itself, as should the layout environment of the components immediate children.
[08:16 - 08:37] Therefore, is the parents responsibility to set the position, size, and margin of its direct children? So things like setting the border, color, padding, or font family, those are appropriate to set at the component level.
[08:38 - 08:52] So today we have learned the principles of capsulade CSS, the foundation of compositional layout. In the remaining lessons of this module, we're going to learn how to use in capsulade CSS in differently out context, starting with normal flow.
[00:00 - 00:08] What's up guys? Travis here with another lesson in composing layouts in React. Today we're going to learn about encapsulated CSS.
[00:09 - 00:24] Now that we understand the power of composition when working with layouts, the next obvious question is how do we apply this in practice? One of the more important parts of building composable layouts is knowing at which level of your component tree you should be applying your styles.
[00:25 - 00:39] This is why I have compiled some important principles I like to call encaps ulated CSS. encapsulated CSS is a term I use to summarize the rules of how to apply CSS styles in a composable way.
[00:40 - 00:50] It's based on the programming principle of encapsulation. Now here's my best attempt to define encapsulation in a language agnostic way.
[00:51 - 01:06] encapsulation involves grouping related things and restricting access to those things except through appropriate channels. For example, many languages utilize a module system which follows the principle of encapsulation.
[01:07 - 01:21] When you import a module like React, you get a group of functions that help you build a React application. Here we have create element, use state, use effect. All of these are part of the React namespace.
[01:22 - 01:39] However, you don't have access to the actual internals that make the React application work. Those internals are encapsulated inside of the React namespace, and only through the exposed functions can you access the React internals.
[01:40 - 01:57] In object oriented programming, one often implements encapsulation via private properties and methods like this. Here we have a person class with two private properties called first name and last name that are marked private with that hashtag at the beginning of each of them.
[01:58 - 02:15] And then we have a constructor that takes an object with the first name and last name and assigns those values to those private properties. Finally, we have a method that returns the last name and first name in a string .
[02:16 - 02:29] We can create a new person like Robert Smith. We can get the name, as you can see, where we call get name and it returns Smith comma Robert.
[02:30 - 02:50] But we can't change the actual private property because that is a private property that is not available outside of that constructor when we first knew up the person class. Functional programming would probably use closures to achieve something similar .
[02:51 - 03:07] Here we have a function called the person name factory that once again takes an object with first name and last name. And it returns another function that when it's called will return that same full name string.
[03:08 - 03:21] So we can call that person name factory with Robert Smith and get a function that we can call get Robert Smith's full name. And when we call it, we get Robert Smith's full name.
[03:22 - 03:36] Once again, we still we don't have access to those values inside of that function, the person name factory. We only have access to call the function that is returned.
[03:37 - 03:49] Both of these examples, you have values that are grouped together and you access them through a restricted function. A restricted or appropriate channel.
[03:50 - 04:10] encapsulate CSS is based on that same principle is a methodology that helps you group together related styles at the correct component level and only applying styles through appropriate channels. Why is it encapsulate CSS the key to building composable layouts?
[04:11 - 04:23] Well, the biggest enemy to composing layouts is when components already have built in opinions on how they should be laid out. Have you ever had an element or a component that wouldn't lay out on the page the way you thought it should?
[04:24 - 04:39] Only to find out that it had some built in margin or width that was interfering with what you were trying to do. The rules of encapsulate CSS help you avoid this by showing you where to apply your styles in a way that won't conflict with the environments that are being used in.
[04:40 - 04:54] So the question is how do you apply the principles of encapsulation to CSS? I'd like to take a step back and revisit the CSS box model.
[04:55 - 05:04] In the box model, an element is comprised of multiple layers of boxes. These boxes are wrapped around the content of our element, kind of like an onion.
[05:05 - 05:13] The first layer around the content is the padding box. Next we have the border box and then finally the margin box.
[05:14 - 05:30] If I were to ask you at which layer or layers are considered part of the element, at which layers are considered outside of the element, what would you say? An excellent start would be to think how elements are sized.
[05:31 - 05:55] By default, an element size is calculated based on its content plus the padding box plus the border box. For example, if you had a border of one pixel and a padding of one pixel, then the contents in line size would be 14 pixels wide if you had a 10 pixel content .
[05:56 - 06:16] That means we have one pixel on each side for the border, one pixel on each side for the padding and 10 pixels for the actual content, meaning 14 pixels wide in total. Now what happens if we add 10 pixels?
[06:17 - 06:30] The elements in line size or its width would still be 14 pixels. This is because margin describes how much an element pushes away from other elements, but doesn't contribute to the element's actual size.
[06:31 - 06:51] In other words, the margin layer is considered outside of the element. For further confirmation, the box sizing property, which is used to determine how the element size is calculated, can accept three properties, the content box, padding box, or border box.
[06:52 - 07:12] There is no margin box property, so it's pretty safe to say that the border box is the boundary of our components encapsulation. So with that background knowledge, there are two essential principles of encaps ulation access to consider.
[07:13 - 07:30] The first principle is components do not lay themselves out. The properties responsible for the layout of a component like its position, size, or margin are not the responsibility of the component itself and should not be applied at this level.
[07:31 - 08:00] So setting a display to inline a width to 100 pixels, a margin top to two rims, or setting even the position to being relative, that is not the job of the component itself and should not be set on the component or element itself. The second principle is components style themselves and layout only their immediate children.
[08:01 - 08:15] Properties then involve the border box and in order are considered part of the component. And those should be applied at the component level itself, as should the layout environment of the components immediate children.
[08:16 - 08:37] Therefore, is the parents responsibility to set the position, size, and margin of its direct children? So things like setting the border, color, padding, or font family, those are appropriate to set at the component level.
[08:38 - 08:52] So today we have learned the principles of capsulade CSS, the foundation of compositional layout. In the remaining lessons of this module, we're going to learn how to use in capsulade CSS in differently out context, starting with normal flow.