Normal Document Flow in HTML, CSS, and React
In the lesson, you will learn about Normal Flow and what patterns you can use to apply the principle of Encapsulated CSS in the context of Normal Flow.
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:09] Hey everybody, Travis here with another lesson in composing layouts in React. Today we're going to learn about normal flow as composable layouts.
[00:10 - 00:16] What happens when you do nothing to style your components? It can be easy to think that there is no layout, but that would be incorrect.
[00:17 - 00:33] CSS has a default layout called normal flow, also called block inline flow, that defines how elements interact with each other on the page. In this lesson you will learn about normal flow and how it relates to compos able layouts.
[00:34 - 00:50] Normal flow is simple, block elements stack in the block direction, and inline elements stack in the inline direction. Now often we define the block in inline direction in relation to the physical screen, with block elements stacking vertically and inline elements stacking horizontally.
[00:51 - 00:59] However, this is not an accurate way to think about them. The correct way of describing them is in relation to the writing mode.
[01:00 - 01:19] Block elements flow in the same direction that paragraphs flow, and inline elements flow in the same direction that words in a sentence flow. For example, in English, the block direction is top to bottom, and inline direction is left to right.
[01:20 - 01:41] However, in vertical right to left languages, like those of in East Asia, the block direction is right to left, and the inline direction is top to bottom . For this reason, CSS Working Group has revisited the original CSS properties based on the physical properties and has added writing mode logical variations.
[01:42 - 01:59] For example, instead of using properties like March and Top, High, and Width, you can now use writing mode logical variations of margin block start, block size, and inline size. By default elements in normal flow do not position themselves.
[02:00 - 02:24] However, in normal flow, margin and sizing properties like Width and Height are set explicitly on the item, which breaks the first rule of encapsulated CSS, which are items do not set the position size or margin. What we have to do instead is use one of two appropriate channels, which are props, and the direct child selector.
[02:25 - 02:35] Now in React, we use props as input to our component, much like functions use arguments. Then our components use these props when rendering our component.
[02:36 - 02:51] Here we have exposed a label and an on click for our budding component. Now just like we expose a label or an on click prop, we can expose layout properties like March and Top or Men Width.
[02:52 - 03:12] In our component here we have exposed the Men Width property, so we can set the Men Width directly on our component. Using props in this manner works very well with one or two properties, but it becomes unwieldy very quickly as you expose more and more properties.
[03:13 - 03:27] The props of your component should also be a reflection of what your component does. Having an arbitrary margin left prop does not make sense on a calendar component, but it might make sense as a prop used for layout.
[03:28 - 03:42] A good rule of thumb is to use this pattern sparingly and only for components that specifically are used for layout. The other channel for adding styles is using the direct child selector in the parent component.
[03:43 - 03:58] Here we have a parent class, angle bracket, and then a star, which is a wild card to meet in any element. The angle bracket is the direct child selector or more accurately the direct child combinator.
[03:59 - 04:15] Now this tool allows us to select any or all of the parent's containers and immediate children and apply layout styling to it. It's important to note that there is a general child selector that looks very similar, but it should be avoided.
[04:16 - 04:25] As you notice here, the big difference is we're missing the angle bracket. It's that angle bracket that makes it be for direct children only.
[04:26 - 04:46] Unlike the direct child selector, this will select any child no matter how deep below the parent class that it is. Not only does this increase the likelihood of adding unintended styles to our children, but it also breaks the second rule of encapsulated CSS.
[04:47 - 04:57] Components style themselves and layout their immediate children only. Now let's take the following blog post component.
[04:58 - 05:19] In this blog post component, we have an article with the Class name blog post, a heading level 2 with a class name blog title, and then we are mapping over an array of paragraphs. Applying styles that follow the principles of encapsulated CSS, we could do something like this.
[05:20 - 05:34] We can have a blog post class and set the padding to be one ramp. For all the heading level 2's that are the direct children of blog post, we can set the margin bottom and max width.
[05:35 - 05:59] For all the paragraphs that are the direct children of blog post that also have a previous paragraph as a sibling, we can set the margin top to 2 ramp. And then finally our blog title, we can set the text transform font size and color directly on the blog title class.
[06:00 - 06:28] Now in the above stylesheet, the blog post and blog title classes are set their own styles, but when we need to set the layout properties, we use the direct child selector to select the appropriate children of the blog post class to set those properties. The blog post that have a direct child heading level 2 will only select the heading level 2 tags that are direct children of the blog post class.
[06:29 - 06:59] And blog post with the direct child of paragraphs plus paragraph will only select paragraphs that are the direct children of the blog post class as well, and have one paragraph that comes before it. Heading level 2 tags and paragraph tags outside of the blog post class component are not impacted by those styles and we could use those elements in any other component and none of the layout properties will follow them.
[07:00 - 07:12] It's important to note that we do not use the direct child selector to add style properties. Only layout properties. This goes back to the second principle of encapsulates CSS that elements style themselves and layout that are very important.
[07:13 - 07:34] So why bother? At this point one might ask, what's the point of going through all the ceremony of adding a separate rule for the direct children just to add a layout property? One could argue that you could write less CSS by applying the layout properties to the corresponding elements.
[07:35 - 08:00] First of all, because we didn't add any layout properties to the blog post class itself, the blog post component can safely be placed in any context and not interfere with the layout environment it is being put in. The children can also now be refactored into their own components, if needed, and it won't bring along the baggage of the layout environment it was initially created in.
[08:01 - 08:20] It also helps with debugging. One of the most significant difficulties of debugging CSS is determining where your styles are coming from. It's easier to track down styles if you have rules in place where those style properties originate.
[08:21 - 08:33] We have learned how to apply the rules of encapsulated CSS in the default normal flow layout. More recently CSS has added two other layout tools, CSS Flexbox and CSS Grid.
[08:34 - 08:40] Next we will learn how to apply the rules of encapsulated CSS to those contexts as well.
[00:00 - 00:09] Hey everybody, Travis here with another lesson in composing layouts in React. Today we're going to learn about normal flow as composable layouts.
[00:10 - 00:16] What happens when you do nothing to style your components? It can be easy to think that there is no layout, but that would be incorrect.
[00:17 - 00:33] CSS has a default layout called normal flow, also called block inline flow, that defines how elements interact with each other on the page. In this lesson you will learn about normal flow and how it relates to compos able layouts.
[00:34 - 00:50] Normal flow is simple, block elements stack in the block direction, and inline elements stack in the inline direction. Now often we define the block in inline direction in relation to the physical screen, with block elements stacking vertically and inline elements stacking horizontally.
[00:51 - 00:59] However, this is not an accurate way to think about them. The correct way of describing them is in relation to the writing mode.
[01:00 - 01:19] Block elements flow in the same direction that paragraphs flow, and inline elements flow in the same direction that words in a sentence flow. For example, in English, the block direction is top to bottom, and inline direction is left to right.
[01:20 - 01:41] However, in vertical right to left languages, like those of in East Asia, the block direction is right to left, and the inline direction is top to bottom . For this reason, CSS Working Group has revisited the original CSS properties based on the physical properties and has added writing mode logical variations.
[01:42 - 01:59] For example, instead of using properties like March and Top, High, and Width, you can now use writing mode logical variations of margin block start, block size, and inline size. By default elements in normal flow do not position themselves.
[02:00 - 02:24] However, in normal flow, margin and sizing properties like Width and Height are set explicitly on the item, which breaks the first rule of encapsulated CSS, which are items do not set the position size or margin. What we have to do instead is use one of two appropriate channels, which are props, and the direct child selector.
[02:25 - 02:35] Now in React, we use props as input to our component, much like functions use arguments. Then our components use these props when rendering our component.
[02:36 - 02:51] Here we have exposed a label and an on click for our budding component. Now just like we expose a label or an on click prop, we can expose layout properties like March and Top or Men Width.
[02:52 - 03:12] In our component here we have exposed the Men Width property, so we can set the Men Width directly on our component. Using props in this manner works very well with one or two properties, but it becomes unwieldy very quickly as you expose more and more properties.
[03:13 - 03:27] The props of your component should also be a reflection of what your component does. Having an arbitrary margin left prop does not make sense on a calendar component, but it might make sense as a prop used for layout.
[03:28 - 03:42] A good rule of thumb is to use this pattern sparingly and only for components that specifically are used for layout. The other channel for adding styles is using the direct child selector in the parent component.
[03:43 - 03:58] Here we have a parent class, angle bracket, and then a star, which is a wild card to meet in any element. The angle bracket is the direct child selector or more accurately the direct child combinator.
[03:59 - 04:15] Now this tool allows us to select any or all of the parent's containers and immediate children and apply layout styling to it. It's important to note that there is a general child selector that looks very similar, but it should be avoided.
[04:16 - 04:25] As you notice here, the big difference is we're missing the angle bracket. It's that angle bracket that makes it be for direct children only.
[04:26 - 04:46] Unlike the direct child selector, this will select any child no matter how deep below the parent class that it is. Not only does this increase the likelihood of adding unintended styles to our children, but it also breaks the second rule of encapsulated CSS.
[04:47 - 04:57] Components style themselves and layout their immediate children only. Now let's take the following blog post component.
[04:58 - 05:19] In this blog post component, we have an article with the Class name blog post, a heading level 2 with a class name blog title, and then we are mapping over an array of paragraphs. Applying styles that follow the principles of encapsulated CSS, we could do something like this.
[05:20 - 05:34] We can have a blog post class and set the padding to be one ramp. For all the heading level 2's that are the direct children of blog post, we can set the margin bottom and max width.
[05:35 - 05:59] For all the paragraphs that are the direct children of blog post that also have a previous paragraph as a sibling, we can set the margin top to 2 ramp. And then finally our blog title, we can set the text transform font size and color directly on the blog title class.
[06:00 - 06:28] Now in the above stylesheet, the blog post and blog title classes are set their own styles, but when we need to set the layout properties, we use the direct child selector to select the appropriate children of the blog post class to set those properties. The blog post that have a direct child heading level 2 will only select the heading level 2 tags that are direct children of the blog post class.
[06:29 - 06:59] And blog post with the direct child of paragraphs plus paragraph will only select paragraphs that are the direct children of the blog post class as well, and have one paragraph that comes before it. Heading level 2 tags and paragraph tags outside of the blog post class component are not impacted by those styles and we could use those elements in any other component and none of the layout properties will follow them.
[07:00 - 07:12] It's important to note that we do not use the direct child selector to add style properties. Only layout properties. This goes back to the second principle of encapsulates CSS that elements style themselves and layout that are very important.
[07:13 - 07:34] So why bother? At this point one might ask, what's the point of going through all the ceremony of adding a separate rule for the direct children just to add a layout property? One could argue that you could write less CSS by applying the layout properties to the corresponding elements.
[07:35 - 08:00] First of all, because we didn't add any layout properties to the blog post class itself, the blog post component can safely be placed in any context and not interfere with the layout environment it is being put in. The children can also now be refactored into their own components, if needed, and it won't bring along the baggage of the layout environment it was initially created in.
[08:01 - 08:20] It also helps with debugging. One of the most significant difficulties of debugging CSS is determining where your styles are coming from. It's easier to track down styles if you have rules in place where those style properties originate.
[08:21 - 08:33] We have learned how to apply the rules of encapsulated CSS in the default normal flow layout. More recently CSS has added two other layout tools, CSS Flexbox and CSS Grid.
[08:34 - 08:40] Next we will learn how to apply the rules of encapsulated CSS to those contexts as well.