Transcription
[Applause]
Chen Hui Jing: Great, so hello, everyone. First, I want to have a feel of how the audience is. May I know how many of us here identify as developers? Lovely. I was thinking if most of you are not developers and maybe just not really technical and you’re here for all the other amazing talks, I’ll distract you with cute pictures of boxes you’ll see real soon.
Today’s talk is all about boxes, so you must expect to hear the word “boxes” a lot. Now, if you for some reason do not like boxes, I can’t help you there. I mean why not? I think boxes are great.
But anyway, let me turn this on. My name is Hui Jing. I am from Malaysia, and I used to play basketball full time. I fell into working on the Web because of it. If that’s kind of interesting to you, you could talk to me a bit later about this.
I also have a blog full of CSS posts among other things. Like Marc mentioned, I am a Mozilla tech speaker, which is an initiative by Mozilla to support technical evangelists in regional communities around the world by providing resources and funding. If this sounds like something you might be interested in, applications for the winter cohort are now open at this website.
I’m currently a developer advocate at Nexmo, which is a completely new role for me, so we’ll see how this pans out. But out of curiosity, does anybody even know what Nexmo is or does?
Exactly. Nobody. This is a very common occurrence.
Nexmo is actually a platform which makes it easier for developers to integrate communications into their applications by providing APIs for messaging, voice, and authentication. If you’d like to find out more, feel free to have a chat with me. I also have stickers.
[Laughter]
Hui Jing: I mean that’s just something that, apparently, it’s part of the job. I just learned this.
Now, I visited Berlin for the first time in my life earlier this year at CSSconf EU, and there I met an amazing person called Lara Schenck who said this in her talk that “CSS developers are programmers of boxes.” Now, I found this a really good description of what we do.
The visual Web is made up of boxes, many different kinds of boxes. We’ve got boxes nested within other boxes and all these different boxes happen to behave differently. In order to make sense of how to arrange these boxes, align them, we must first try to understand these boxes.
Where do these boxes come from anyway? Well, they are generated by CSS. CSS has come a long way since 1996, starting out as a simple stylesheet mechanism allowing authors and readers to attach style to HTML documents. Now, today, CSS still does that. It is a language that describes the rendering of HTML in various media, but the vocabulary of CSS is significantly larger.
Now, I’m around the same age as the Web. So, by the time I got around to using it, CSS had been around for a few years. The first browser I ever used was a little thing called Netscape Navigator 4. Now, I remember a lot of tile, story backgrounds, blinking, and rainbow text because those were really, really big back then. But I am very glad that CSS was invented and has evolved to what it is today and that it is not this giant fax machine.
Now, before we can talk about box alignment, we need to talk about the boxes themselves. Out of curiosity, does anybody here actually read CSS specifications?
Hello! Excellent. All of you are my peoples.
Now, this is a screenshot of Section 4 of the CSS 1 recommendation published in ’96. First of all, can I say that I just love the ASCII diagrams in this document? We don’t have that anymore, and this textured background is classy.
[Laughter]
Hui Jing: Now, the box model has been around since the earliest days of CSS, grouping all rendered elements into two categories of boxes: block-level or inline - just two.
Fun fact: Upon further perusal of this document, I discovered that, at the time, CSS was not meant for doing layout. Just a little something to think about when you’re frustrated with CSS.
That leads us to expand it, the visual formatting model, which is what we now know as the visual formatting model. This model determines how user agents process the documentary for visual media. One particular sentence in this specification really stood out to me because it reads, “In the visual formatting model, each element in the documentary generates zero or more boxes, according to the box model.”
How do you generate zero boxes? Hmm. That sentence, out of context, seems somewhat bizarre. So, in order to make sense of it, I actually dug a bit into how browsers work to render things.
Rendering engines parse the source document into objects that browsers can understand. But before it can actually render anything, an intermediary structure called a box tree is generated. This is a representation of the formatting structure of the document. CSS will assign a computed value for each CSS property to every element and text note in the source tree.
One of the CSS properties is displayed, which tells the browser what type of box to generate. Usually, it’s a one-element, one-box situation, but some values can generate more than one box. Like if you set it to this item, you’ll get a principal box and an additional marker box for the bullet.
Now, if you do something like display none, the element will not generate any boxes at all, and so that’s why they said you can generate zero boxes in the spec. It makes perfect sense now.
Now, after the browser generates these boxes, it’ll have to lay them out. The layout of these boxes are dependent on a couple of factors. We’ve got the box dimensions in type, the positioning scheme used, the relationships between the elements and the document tree, and also some external information like viewport size, intrinsic dimensions, et cetera.
Now, positioning schemes. To be honest, until I read the specification, I didn’t know this was a thing, but it’s important because there’s some terminology introduced here that pretty much sets up the remainder of this talk. We actually have three positioning schemes. We have normal flow, we have floats, and we have absolute positioning.
Now, boxes in a normal flow belong to a formatting context. Right now, we have quite a number of those, which I will be covering. Relatively positioned boxes remain part of this normal flow.
When we float a box, it is first laid out in normal flow; then taken out of it and shifted as far left or right as possible. When a box is absolutely positioned, it’s removed from normal flow altogether and given a position with respect to its containing box.
A formatting context is the environment in which a set of related boxes are laid out. Different formatting contexts have different rules for how they lay out the boxes within them. Boxes can generate new formatting contexts and create a new environment where the layout of its children is mostly not affected by the rules and contents of the environment outside itself.
Now, I say mostly because certain formatting contexts can allow interaction between their contexts. For example, line boxes within an inline formatting context can interact with floats belonging to the block formatting context containing all of them.
Our next very important property to cover is the display property. The CSS display module level three is meant to replace and extend the display property from CSS too. Some of the things that I mentioned here may not be implemented in browsers yet but do paint a picture of CSS to come.
Now, it used to be that the single keyword syntax for display was enough because we had inline boxes, we had block boxes and table boxes. That’s it. They could pretty much exist in the world on their own.
Now, flexbox was the first module to introduce the concept of a parent/child relationship between a box and its children. Grid uses this model as well.
In display level three, the single keyword syntax is still very much valid, but each of these values have a longer full version that indicates how the box itself behaves and how its children behave. We have the inner display type, which determines the kind of formatting context the box generates, and this affects the child boxes within it. We have the outer display type, which dictates how the box itself participates in flow layout.
Now, this table is directly lifted from the specification. It fills up two slides and, if you pay attention to the full column, notice that the outer display is either block or inline. Now, I’m glossing over run-in for now because its implementation status has been iffy for a very long time.
Moving on.
There’s a part of the specification that is relevant for browser vendors, probably not so much for Web developers like you and I, but it does explain how certain layout effects require the blockification or inlinification of box types to ensure a box is matched to its context. Now, don’t you just love invented words? If you’re a spec writer, I get to invent words. It’s probably part of the perks of being one of them.
As far as I know, the multi-value syntax is not supported in any browser. I’ve only managed to find an entry for it in Firefox’s bug tracker and none of the other browsers. But if someone can verify this for me, I’d greatly appreciate it.
Now, out of this long list of values, though, only flow root is a brand new value. When a box has its display set to flow root, it generates a block level, block container that establishes a new block formatting context.
I had to practice saying that multiple times.
A block formatting context, which I will abbreviate to BFC just to make my life easier, is the context that block-level boxes participate in. Now, boxes are laid out one after another in the block flow direction, which is determined by a box’s writing mode. Margins along the block flow direction between boxes within the same BFC will collapse. This is otherwise known as the infamous collapsing margins phenomenon.
Now, earlier I mentioned that when a new formatting context is established, boxes within this new context are largely shielded from their outside environment, which can come in pretty handy at times, so there are a number of ways that we can establish new BFCs. You could float a box. You could position it absolutely. If you make a box an inline-block, a table cell, or a table caption, that can give you a new BFC. You could set a block box’s overflow value to anything but its initial value of visible; that also generates a new BFC. Lastly, the newest way to do it, we do display flow root.
What good is a new BFC? I’m so glad you asked. Remember that I mentioned a new formatting context will generally contain the boxes within it. Now, if collapsing margins isn’t your thing, then this demo here might help. Here, both the green and orange boxes have a margin of 0.5 set on them.
Let me just locate my cursor. Okay, here we go.
Now, the top margin of the first box and the bottom margin of the second box have collapsed in their parent, which a pink background, right? Making the parent a new BFC is going to solve this problem and any of the methods that I mentioned earlier will work, so let’s try a commonly used one, which is like overflow hidden.
Right now, you can see that the parent margins are no longer collapsed. But at this moment, the green and orange boxes are block boxes in the same BFC, so their margins have collapsed with each other. But if I do something like, say, apply a display--
Oh, let’s do this properly. All right. Here we go.
Display inline-block to the green blocks, it now has established a new formatting context and its margins are no longer collapsed. If collapsing margins are a problem for you, this is something to keep in mind.
Now, this next example is exactly the situation I described earlier where contents within two different formatting contexts sort of end up interacting. Now, to prevent the line boxes from poking into the space below the floated box, we can make the P element wrapping the text a BFC.
Let’s try another technique, which is overflow auto. What this does is that it’s now a new BFC and the text stays in its own lane. Now, it’s probably not the most semantic thing to do, but if you set display to table cell, yeah, that works too. It’s just, meh, a bit icky because we’ve essentially made the float and the text belongs to separate formatting contexts, so now their contents are contained within their own environments.
Lastly, and this might be the most common use case for establishing a BFC, which is as a technique for containing floats, or sometimes we use the term “cleaning floats.” This situation happens quite often when all the items in a container are floated. The parent container ends up with no height, so you just see that the parent container ends up being this purple line across the top. It has no height. This is because the floats themselves, they are not in the normal float and they no longer affect the height of the parent.
Establishing a new BFC lets the parent contain the floats. This time, let’s try the latest and greatest. We’re going to use display float. Now, the parent box wraps its children very nicely. Applying a float to the parent box or setting display to inline-block will also work. But if we do that, what happens is that the width of the parent will shrink to fit its contents. I think, depending on the end result that you’re looking for, these different techniques have different end results and you might want to think about the type of end result that you actually want.
If block-level boxes do block formatting contexts then, naturally, inline-level boxes will participate in an inline formatting context, which I will also abbreviate to IFC. Now, the rectangular area that contains the boxes which form a line is referred to as a line box. Now, you can think of a paragraph as a stack of line boxes.
Now, line boxes can be a little bit tricky because we can’t directly see them from the source. They are generated based on how the content needs to be laid out. An example would be a good way to show this. This is an example of a block box that contains five inline boxes. The block box, in this case, is the P element.
Right now, there is enough room that all five boxes can fit in a single line box. But when there isn’t enough room, inline boxes can be split across multiple line boxes. So, if I make this bigger, now it has to be split across multiple line boxes.
If you notice, there is an italic text that is both on the first and the second line. Splitting an inline box is like slicing a Snickers bar. The cut part will not have any chocolate coating on it. Margins, paddings, and borders don’t actually apply to the split part of the box. It’ll be easier to see this if I put a background color onto this, so line three.
As you can see, if I add some padding to the M element, it surrounds the M element, but not where the box has to split to the next line. Even though padding is applied all around, notice that the distance between the line boxes does not change.
Let’s toggle. You can see that the movement is actually in an inline axis. Right?
Now, personally, I’m not too sure what you can do with it, but I think there are some interesting things from a design perspective that might work here. For example, if I apply a background color here, then I give it some padding, what do we have? We have things like blend mode that could -- I don’t know. It’s something, from a design perspective. Any designers in the house? I’m just here to provide inspiration and possibilities.
Audience member: Woo!
Hui Jing: Right?
[Applause]
Hui Jing: Thank you. [Laughs]
Now that we’re about, I think, almost halfway into the talk, it’s a good time to move onto the alignment part of box alignment. Aligning boxes along the inline axis is actually a reasonably straightforward affair because we can use text-align, which has been around forever. The values of left, right, center, and justified are very well supported. Just note that there has to be an access space within the line box for those to work. Also, text-align comes into play only after all the required boxes have been generated and the inline boxes have been laid out accordingly.
Now, a line box will always be tall enough to contain all the boxes within it. It can even be taller than the tallest box it contains. Now, shorter inline boxes can be aligned along the block access with the vertical aligned property.
Now, vertical-align; it’s one of those properties that really trips up people who are just starting out with CSS because it’s actually only applicable to inline level and table cell elements. But come on. There’s no way you would know that if you just read it at face value, right? It says, “Vertical align.” You’d expect it to vertical align everything. But no.
Anyway, it’s key to remember that vertical-align controls the alignment of inline boxes within the line box and not the alignment of the line boxes themselves. There is a slight distinction.
Now, the height property does not apply to inline boxes. The height of an inline box is determined by their font and their line height. Here’s where the spec gets a bit laissez-faire about things because user agents are free to decide if they want to use the M box or the maximum ascender and descender of the font to calculate this value.
Now, you can use absolute length values like Ms or pixels to set the height of an inline box, but we can also use unitless numbers which the browser will multiply by the element’s font size to get a computed value. If you use a percentage, it will also be multiplied by the element’s font size and not the height of the parent element, which is a more typical resolution for a percentage value. So, this is something that I like to highlight because I myself have been confused by this for the longest time.
Let’s have an illustrative example. Now, before flexbox became widely adopted, there were a number of techniques for centering things along the block access. One of them was this inline-block technique I first discovered from a CSS-Tricks article by Chris Coyier called Centering in the Unknown.
It involves aligning the target block with a pseudo-element that is as tall as the parent container. Now, an inline-block is an inline-level box also known as atomic inline because it participates in an IFC as a single opaque box. Setting both the pseudo-element and the child box to inline-block means they are both in an IFC. Because the pseudo-element is as tall as the wrapper, the vertical aligned property can be used with this block of text.
If you can see what the pseudo-element looks like, you’d probably have a better idea of what is actually going on behind this trick. I’ll give it a width. That green line is actually the pseudo-element that you don’t see. It’s not visible unless you do something explicit like this, but it helps center the block of text.
Now, we’ll move on to another formatting context, which is the flex formatting context, so a different formatting context, different set of layout rules. Now, some of the highlights of the flex layout model include the fact that flex containers’ margins will not collapse with those of its children. I think that’s a plus. Float and clear do not apply to flex items. It’s also good to know. Vertical-align, no effect on flex items either. Now, flex items can still be taken out of flow with absolute positioning, and flex items are flex level boxes, not block-level boxes.
Now, I’ve been using the terms block direction and inline direction for the entirety of the talk so far. I’m going to introduce a new type of direction called the flex direction. Think of the flex direction as the direction which flex items flow. I think flex layout can be quite fun because the flex items can flow in any physical direction depending on the interplay between the flex flow, flex wrap, and in writing values of the flex container.
Now, the main axis is the primary axis, flex items are laid out, and the cross axis is always perpendicular to it. Flex items are laid out within flex lines. These containers are a bit similar to line boxes in that you cannot see them in the source, but they are used for the positioning and alignment of flex items. We can have single line containers or multiline containers based on the flex wrap property.
Now, a single line flex container will lay out all its children in one line, even if it means overflow. This is the default flex container behavior if you don’t explicitly set a flex wrap value. But if you do set it to wrap, it will cause flex items to break across multiple flex lines and additional lines are stacked along the cross access and the direction of the stacking is affected by the flex wrap property as well.
Combinations of the writing mode property, flex direction, and flex wrap property will determine how your flex items flow. For example, I’m first just going to set the container to have a height in this.
Various permutations and combinations, these are currently the default values that we have. But if you do something like row reverse, you’ll see that now the flow goes from right to left. Okay. Not too bad.
Of course, we also have the column direction. If it’s column reverse, you’ll see that the number one actually starts from the bottom up. I find this really interesting because, in Web design, or in design in general, we don’t really see things flowing from bottom up. It could be simply that we couldn’t do it without hacking with maybe JavaScript -- I don’t know. But now, it’s a possibility, so I’m waiting to see if anybody takes this and runs with it.
Wrap also has a reverse, so you can sort of reverse things around, and you can see that there are a lot of different combinations because, once we do writing mode, there are all sorts of directions that you can flow your items. Many, many possibilities, if I don’t say so myself.
I also wanted to point out that there are right to left languages. Just multiple everything by 2 and, voila, you have 64 potential combinations. So, I don’t know. Now, it’s supposed to be cold and gloomy even though it’s sunny outside. If you’re stuck at home, you have nothing better to do, it’s a lazy Sunday, you don’t want to go out, you could take the time to try all of these combinations. Don’t worry. You won’t get 64 different results because I think some of these combinations do end up giving you the same result, but it’s probably a good way to spend an hour of your time, maybe. I don’t know.
All right. It’s time to actually align some boxes, so let’s start with something that is somewhat direction agnostic. Now, for flex layouts, margins are distributed before alignment properties kick in, so we’re going to talk about margins first.
Any positive free space will be distributed to auto-margins in their respective dimensions. For example, if I set a margin left on boxie here, it ends up on the other side of the container. If I do something like a margin top, boxie gets sent all the way down. If we don’t specify a dimension at all, then any free space will be equally distributed on either side of the flex item.
Now, I love showing this particular example to people who have just started out in CSS and have ran into a wall when you try to center anything because you set a margin auto and, boom, a one-line solution to all your centering problems. A small caveat is that this trick works best if you only have one flex child, so something to note.
Anyway, this is one of my all-time favorite talks by Elika Etamad, a.k.a. fantasai, at CSS Day three years ago. She works on CSS specifications and is one of the few people in the world that can answer any question you could possibly have about CSS specifications. This is a talk that is definitely worth watching.
Now, a major evolution in Web layout is the ability to position and align content in both the inline and block direction. Alignment along the inline axis, as I’ve covered extensively previously, has been well supported from the get-go, especially for languages that were read horizontally from top to bottom.
“Moving text or blocks of content horizontally wasn’t a complicated affair. Right? But vertical alignment required a lot of workarounds, a lot of hacks, a lot of frustration. Luckily, CSS is not a fixed technology. Changes were introduced, improvements were made, and now we have a suite of tools for two-dimensional alignment and layout.”
Back to the flex formatting context. For the most part, we are going to have multiple flex items within our flex container and box alignment gives us four properties to align and/or distribute these flex items. Justified content helps distribute free space left over after flexible length and auto-margins are resolved, so I have this awkward free space right here on the right that is not really quite five Ms, so an initial value would be flex start, but we have the option to position our content with center. We have flex end. There are also these space distribution values that we can use. We have space around. You can do space between, and you can also do space evenly, which is a relatively newer addition.
These are just some illustrations to show how these various values work.
The next thing is to align along the cross axis. Here we have flex children of varying heights. They’re spaced within the flex line for them to be aligned. The property here is align items, and align items sets the default alignment for all the flex children at once.
Again, the initial value is flex start, but it’s the same as what we saw in the previous example. We have the option of flex end, we have the option of center, but we also have something called stretch, which is actually the default value. If I don’t put anything there, your flex items will always take up the space that your flex line -- the height of your flex line, so to speak.
One value that I find people don’t really talk about is this value called baseline, which aligns the baseline for the content in every flex item so that the text line can align up rather neatly. Now, I have a personal explanation for why a design like this is sort of a jagged alignment is not common on the Web. I reckon that it’s because, if you do something like that, your text lines sort of go up and down, and it’s probably not good for readability. But because we have this, we have this property called baseline that sort of aligns all your text.
You can kind of read everything neatly and still maintain such a jagged look, so I think this is a possibility that we should introduce to the Web. I find neat rows and columns kind of boring. I mean it’s boxes, but can’t we be creative with these boxes. You know, just a thought.
Now, if you want to tweak the position of individual flex items, not all at once, you can make use of align self, which does the same thing, but for a single flex item. Okay, maybe we do it for this one. Now, I have a baseline. I could just say flex start, so you can adjust individual flex items if that's what your design calls for.
Another bunch of illustrations to show how things work. I really didn’t know what to do about the baseline value, so this is it. Sorry.
This header was directly lifted from the specification because I couldn’t think of anything better: packing flex lines. If a flex container has more space along the cross axis than necessary to contain all these flex children, the flex lines kind of stretch to fill up all the space. It’s the flex lines that stretch, not the flex children. You have this kind of annoying white space between lines, which sometimes you don’t want.
The property that controls this would be align content. Only multiline flex containers will ever have this free space along the cross axis for us to do alignment stuff because flex lines in single line containers just stretch to take up all the space. If you don’t want the default value of stretch, which is causing some unwanted behavior, we can peck the flex lines and position them with the same values as we’ve done in the previous examples. You can start to pack them to the top, pack them to the bottom, and all the space distribution properties are available for use as well. So, there’s quite a lot of things we can do to align boxes in this context.
Now, I’d be remiss if I gave a talk about box alignment without mentioning how it works for grid. Now, the layout rules for a grid formatting context are somewhat similar to that of a flex formatting context. The grid container’s margins also do not collapse with the margins of its children. Float and clear don’t really do anything to a grid item. Neither does vertical align, and gridlines form the boundaries of each grid item’s containing block.
These are the terms used whenever we discuss CSS grid. We have grid lines that are referred to by their numerical index that start from one and not zero - something to take note of. You can also use negative index, or you can name grid lines if that’s what you want. By default, grid items take up the space of one grid cell. A collection of grid cells is called a grid area. Grid rows and grid columns are called grid trucks. Just a bunch of terminology, right?
Now, eventually, the CSS working group decided that it made more sense to come up with a cohesive and common box alignment model that could be shared across all different formatting contexts. That is why we have this CSS box alignment module level three. In it, it defines the six properties that control the alignment of boxes within other boxes.
When using grid, all six properties are relevant. However, when using flexbox, self-alignment along the main axis is just not applicable. Justify self and justify items have no effect in a flex formatting context because there’s more than one item in the main axis. Now, in the future, these box alignment properties will be applicable to block formatting context as well, making alignment a much more straightforward process than what we have today.
Now, how many people have trouble remembering which value affects which axis? Okay, I see quite a few hands. Great.
Is there anyone here who has not used Microsoft Word or any word processing software? Okay, so I’m going to make the bold assumption that you’ve all seen these four lovely icons before and you know that they are used to justify text. That is, to move your text along the inline access.
Since there are only two values for two axes, if justify is along this direction then, logically, by process of elimination, align must be along this axis. This is a personal trick that I use to remember. I don’t know if it’ll help you. But if it does, excellent.
With justify content and align content, properties are known as content distribution properties, as we’ve seen. This table is a summary of the values we’ve covered thus far for content distribution.
Now, the values that we covered for flexbox, again, are applicable for grid as well, except that instead of flex start, we use start instead without the flex. If you do end up using any flex prefixed values, however, in a non-flex formatting context like this one, the browser is pretty smart. The browser will resolve away the prefix, so let’s just verify that this is true and I’m not just nonsensing.
I will say flex end. Okay, so it works.
What the browser does is that it recognizes what flex end is supposed to do and it just kills the prefix. I think, if you look at this whole setup in your dev tools, you’ll see that the computed value actually resolves the end, which is great. You’re free to use start and end for flexbox, though, because the flex prefix is going to be sort of a legacy value and, because of the standardization that box alignment is going to bring about, it’s going to be a prefix--just start, center, and end--making things more straightforward.
Now that we sorted out the align versus justify situation, I want to bring your attention to the shorthand for setting both values in a single declaration. The shorthand uses the word “place.” In this example for content distribution, it will end up being -- I’m just going to get rid of this. What we’re using is place content.
The first value sets the align content and the second value sets justify content. If I did something like, say, center end, it’s center along the block axis and end along the inline axis. If you only enter a single value, then justify content, which is the second value, will resolve to the same value as the first, so center or end. That’s the shorthand if somehow you don’t want to have two lines worth of alignment properties.
The justify-self and align-self properties are known as self-alignment properties. These properties allow us to control how content of each grid item is aligned within the grid area it’s been allocated to. The default state is actually stretch like in item A. The content will actually stretch to fit the entire grid area. We can adjust the alignment of content within the grid item with start, center, and end. Once we apply any of these values, you’ll notice that the grid item actually shrinks to fit its contents along the respective axis of alignment.
In B, I’ve sort of triggered justify self, so it’s now, I would say, along the inline axis that’s the amount of space that it needs. For item D, I’ve done an align-self center, so the height of the grid item ends up taking as much space as the letter D. If you wanted to, the place-self shorthand is also available here.
Finally, we have the align items and justify items properties, which essentially set the default align-self and justify-self behavior for all your grid items within the grid, so similar to flexbox. Here, you can also use the baseline value to make the text within your grid items to line up neatly. This occurs -- this is more evident if you have content that is different in terms of maybe different font sizes, maybe different content lengths and, if you do a baseline, you’ll see that -- sorry. Wrong axis. If you do a baseline, then you will see that, regardless of the font size, the baseline will always align across all your different grid items. Now, the place items property is also available if you very much prefer a single item declaration.
Finally, the alignment keywords or values that we use in these various alignment properties can broadly be classified into four categories. We’ve covered a lot of them. We’ve covered distributed alignment. We’ve touched on baseline alignment. We’ve gone through positional alignment.
Now, there’s also a keyword for managing overflow. What I mean is that if contents within the container are larger than the container itself, as you can see here, overflow occurs. That’s when we get scrollbars, depending on the value of the overflow property. But there might also be instances like this one where an alignment mode sends part of the box just out of the viewport start edge, and you can’t even scroll. If you can see, I have a scroll bar but, nope, you can’t scroll. You can’t even scroll to get to the content on the top.
To exercise some semblance of control over such behavior, we can make use of the safe and unsafe keywords. If I set safe keyboard here, it will override the alignment mode and make it behave like start in an overflow situation. If I just use unsafe here, you’re explicitly telling the browser, “It’s okay that my audience cannot scroll to the content on the top.” It’s on you if you use the unsafe property explicitly.
With all these additional tools that we now have in our CSS toolbox, the standard of graphic design we can now achieve on the Web, I’d say, has vastly improved. I’ll attempt to back up this claim with an example. This is a page from Laszlo Moholy-Nagy’s book “Malerei, Photographie, Film.” I just butchered the pronunciation. I’m sorry.
When I first saw this poster, I thought to myself, “This looks really gridable.” It is a striking design, these really strong black borders, and the content is aligned in different configurations. Here’s where all the alignment properties that we’ve covered at length today really come in handy.
This is a replica in CSS. The code shown here has been abridged to show just the layout code, but even the gear and the arrow is made with pure CSS.
Now, at first glance it might be tempting to reach for self-alignment properties, apply them to the grid items, call it a day, but that approach won’t work for this case because, in order to align the internal content of each grid child without disrupting the rendering of those thick black borders right there, you’ll need to make each grid child a flex item.
When people ask you the question of, “Is it flexbox or grid?” it is not. It is flexbox and grid because, by default, the value of a grid item’s alignment is stretch where it fills up the entire space of a grid cell. But once an alignment is applied to the grid item’s contents, it will shrink to fit the content like we’ve seen earlier. Making each grid item a flex container allows us to use box alignment properties to position the grid items’ contents while keeping the borders at the edge of the grid cell like so.
The first time I ever gave this talk, I wasn’t really sure how much I could talk about boxes and box alignment, but this is because I hadn’t really dug into what box alignment was all about. The more that I dug, the more that I realized that--hang on--I’d been using all these techniques without really understanding how they work.
I don’t know about you, but the whole process of researching this talk has been a great experience for me, but I do hope that you find some of the things that I covered useful and that you enjoyed this talk as much as I enjoyed giving it, so some resources.
Audience members: Woo!
[Applause]
Hui Jing: And I thank you all for your kind attention.
[Applause]