Menu
O mnie Kontakt

Josh Comeau w swoim najnowszym filmie podzielił się swoimi doświadczeniami związanymi z rozwiązywaniem problemów z CSS. Opisał typowy scenariusz, w którym natknął się na dziwne luki w przestrzeni pod obrazkiem w kontenerze. Pomimo braku marginesów, paddingu czy obramowań w kodzie, obrazek wydawał się mieć dodatkowe 6.286 pikseli przestrzeni pod sobą. Josh przyznał, że przez długi czas próbował tylko znaleźć szybkie rozwiązania tego typu problemów, korzystając z pomocy Google lub codziennie popularnych w tym zakresie narzędzi, jak Chat GPT. Wiązało się to z szeregiem nieporozumień i braku głębszej wiedzy na temat CSS.

Zamiast bać się tych dziwnych problemów, Josh postanowił turystycznie zająć się każdym z nich, aby lepiej zrozumieć jak działają różne właściwości CSS. Zrozumiał, że obrazki są traktowane w CSS jako tekst w linii, co prowadzi do niewłaściwego wymiarowania w kontekście kontenerów. Przykład, na który zwrócił uwagę, dotyczy możliwości pozycji elementu w porównaniu do tekstu, gdzie element obrazka był postrzegany przez CSS jako część standardowego układu, co skutkowało dodatkowymi pikselami.

Josh doszedł do wniosku, że hiszpańska właściwość 'line-height' również potrafi powodować dziwne efekty, ale są pewne lepsze rozwiązania, takie jak ustawienie obrazu na wyświetlanie jako blok. Zamiast skupiać się na tym, co jest problemem, zwrócił uwagę na możliwość wprowadzenia do rozmowy 'display: flex' w kontenerze. Te doświadczenia sprawiły, że zyskał reputację specjalisty od CSS zarówno w pracy, jak i podczas prowadzenia kursów.

Zyskał reputację również podczas prowadzenia zajęć w Concordia University w Montrealu, gdzie studenci często przychodzili do niego z trudnymi przypadkami związanymi z CSS. Postanowił uczyć ludzi o CSS, co przerodziło się w tworzenie kursów online, między innymi "CSS for JavaScript Developers", który do tej pory zarejestrowało około 18,000 uczestników. W jego filmie porusza temat "Mechanizmów CSS", w którym pragnie zaadresować typowe braki w zrozumieniu CSS, budując połączenie między teorii i praktykami.

Skoncentrował się na przedstawieniu CSS jako zestawu różnych trybów rozmieszczania zamiast jako jednolity język. Wspomniał o trybie przepływu, który działa jak algorytm przetwarzania tekstu, oraz o różnych problemach związanych z elastycznymi i siatkowymi algorytmami w CSS. W szczególności, wyjaśniał, że różne interpretacje wartości właściwości, takie jak 'width', mogą znacząco wpływać na zachowanie elementów w zależności od tego, czy są one w trybie przepływu, elastycznym, czy siatkowym.

Na koniec z prawie 19,000 wyświetleniami i 1120 polubieniami tego filmu przyznał, że nie tylko zna zasady działania CSS, ale również znacząco poprawił zrozumienie tego języka u swoich uczniów oraz kolegów z pracy. Jego spostrzeżenia dotyczące Toronto w CSS wyszły poza rutynę, umożliwiając mu odkrycie gruntu na wyzwania poruszania się po tym przydatnym, ale często złożonym narzędziu.

Toggle timeline summary

  • 00:00 Wprowadzenie do powszechnego problemu CSS związanego z obrazem i jego kontenerem.
  • 00:28 Omówienie nieoczekiwanej przestrzeni pod obrazem, mimo braku marginesów, paddingów czy obramowań.
  • 01:03 Analiza wymiarów kontenera i zauważenie arbitralnej przestrzeni.
  • 01:33 Refleksja na temat przeszłych podejść prelegenta do szybkiego rozwiązywania problemów CSS.
  • 02:25 Opisanie zmiany w myśleniu w kierunku głębszego zrozumienia CSS.
  • 03:18 Decyzja o zbadaniu przyczyn problemów z CSS zamiast ich szybkiego rozwiązania.
  • 03:38 Odkrywanie, jak obrazy współdziałają z tekstem i podstawowe zasady układu.
  • 04:25 Omówienie, jak CSS traktuje obrazy jak tekst inline.
  • 04:43 Przedstawienie różnych rozwiązań CSS dla problemu przestrzeni wokół obrazu.
  • 06:02 Propozycja 'display: block' jako rozwiązanie problemów z układem obrazów w CSS.
  • 06:24 Budowanie reputacji jako ekspert CSS podczas nauczania online i w bootcampach.
  • 07:20 Wyjaśnienie celu wystąpienia: rozwiązanie powszechnych nieporozumień dotyczących CSS.
  • 07:35 Wprowadzenie pojęcia CSS jako różnych trybów układu zamiast jednego języka.
  • 08:10 Wyjaśnienie różnych trybów układu, takich jak flexbox i grid.
  • 08:43 Demonstracja wpływu trybów układu na wymiary elementów.
  • 09:54 Wyjaśnienie różnicy w zachowaniu właściwości szerokości w różnych trybach układu CSS.
  • 11:20 Opis układu przepływu jako algorytmu przetwarzania tekstu.
  • 13:12 Omówienie elementów inline i ich ograniczeń w porównaniu do elementów blokowych.
  • 14:26 Wyjaśnienie pojęcia 'display inline block' i jak to działa.
  • 16:07 Wyjaśnienie flexbox jako trybu układu do rozmieszczania elementów wzdłuż jednej osi.
  • 19:59 Zagłębianie w różnice między justify content a align items w flexbox.
  • 23:21 Badanie, jak właściwości flex, takie jak shrink, działają w układach formularzy.
  • 28:02 Wprowadzenie do układu opartego na pozycjonowaniu i jego unikalnych cech.
  • 30:01 Użycie metafory uziemionego nastolatka do wyjaśnienia pozycjonowania absolutnego.
  • 32:23 Opis pozycjonowania stałego jako elementów, które nie poruszają się podczas przewijania.
  • 38:36 Promowanie kursu online na temat CSS skierowanego do programistów JavaScript.
  • 38:57 Zakończenie wystąpienia i podziękowanie publiczności.

Transcription

So I'd like to start with a scenario that I feel like if you've been working with CSS for a while, you've probably hit. It's probably derailed some of your afternoon. Here's the scenario. I have an image which is sitting inside a container. The only CSS I'm applying is an outline to the container so that we can see sort of the box that it forms. And we notice there's like, I wonder if I can do this. Yes, I can. Cool. There's a little bit of space between the bottom of the image and the bottom of its container. And I should make this bigger. Like, usually we have an idea that there's the usual suspects for this kind of thing. Maybe there's some padding. Maybe there's some border. Maybe there's some margin. But if we use the dev tools, we see there's no margin, no border, no padding. The image is 250 by 250, which is exactly right. That's what I've told it it should be. The parent container has no margin, no border, no padding. But it is 256.286 pixels. So completely randomly, we have 6.286 pixels that is sitting underneath this image. Now, I've been writing CSS for a long time. I started maybe in like the early 2000s. I started doing it professionally in 2007. And for like the first decade of my career, my mindset with this sort of thing was to try to sprint through it as quickly as possible. Like, I wasn't interested in understanding what this was. I just wanted this problem to go away. So you'd Google it. You'd find a stack overflow thread. You'd scroll through, ignoring all the text and just looking for snippets that you can copy paste and hope that it works. These days, maybe you'd ask chat GPT. And so just for fun, I threw the question at the robot. And the robot gave me a snippet. Again, ignore all the text. I see the CSS. I'm going to copy it. I'm going to paste it. Line height zero. And it works. It solves the problem. It seems totally arbitrary. Like, I don't know why line height zero got rid of that weird space. And so, you know, for that first decade, this was my mindset. And so I would then go on to the next problem. And in a few weeks, I'd probably hit this issue again. And this is sort of the first problem with this mindset is that it requires a lot of memorization. Like, you have to memorize that, oh, yeah, when I have this weird space under the image, line height zero is the solution. And I don't have a good memory. So I'm not going to remember that. But the deeper problem, the more sinister problem is that it means that even when you spend years and years working with CSS, you never get, like, a deep understanding of it. You have a really shallow understanding of how the language works. And that means the language feels really arbitrary and really inconsistent and really frustrating. Like, you never know when some weird CSS behavior is going to derail your afternoon like this problem did for me. And so in 2017 or so, I decided that I was sick of having this relationship with CSS. And from now on, when I hit weird problems like this, I wasn't going to try to, like, rush through them. I was going to settle into them like it was a nice warm bath and just try to understand what's going on and how to fix it. And in this case, the thing that helped me figure it out was what happens if I have some text in this container alongside the image. And I should make this container a little bit bigger. We noticed something kind of interesting, right? That the image is sitting on the same sort of imaginary line that the text is. Like, it's treating the image as if it's just another word in this sentence. And if I get rid of the image, so we just have the text, well, this looks right. This is what we expect text on the web to look like. And we sort of forget that there is this 6.286 pixels of space underneath the characters. And this exists so that we can actually read the text. Like, if we had no space and there were multiple lines, imagine the characters were all squashed together. Wouldn't be easy to read. And so that's what's happening here. We have this image that we sort of, you know, when I only have the image and I don't have the text, we expect this image to be, like, part of the layout, to be a standalone thing. But CSS is treating it like part of a sentence. And that's the issue. And so the solution that chat GPT gave me, line height zero, it solves the problem by getting rid of all the space below and above the text. In fact, if I only had text, and I'll put a bunch of it here, we see that, like, this is what this actually does, which doesn't really make for readable text, especially if, like, we line wrap it. Each line of text has zero pixels of space. So the characters just stack one on top of the other and it's complete gibberish. It looks like an alien language, which is kind of cool, actually. But yeah. So the, like, solution that the robot gave us does the trick. But it's not really what I consider, like, a good solution. Another option you'll see kind of used online is we select the image and we say vertical align. And this property has a default value of baseline, which is that imaginary line that the text sits on. But we can change it to bottom. And if I finish zooming out and make this bigger. That fixes the problem, too. And this solution has the benefit of any text that also exists. Doesn't get, like, smushed down to nothing. But it still feels to me like we're treating the symptom rather than the disease. Like, the problem that's causing this issue is that the image isn't a character in a sentence, right? That's not what this image is supposed to be. And so the way I would solve this now is I would set display block, which essentially tells CSS that, hey, this image is, like, just another block on the page. Like a heading or a paragraph. We could also solve this by moving the declaration to the parent and setting display flex for reasons that will become clear by the end of this presentation. So as I started doing this, as I started deepening my understanding of CSS, I started getting a reputation at work as, like, a CSS person. Other coworkers would come to me with their weird CSS problems. I also started teaching online. And in person, actually. At Concordia University in Montreal. I had a boot camp. And there, too, I got the same reputation. So when students would go to, like, a different instructor with their unfathomable CSS behavior, I would get pulled into that conversation to try and help. And what I noticed is that, like, in a 15, 20-minute conversation, I could address so many of the gaps that are so common in all of our mental models with CSS. I also, and this was mentioned in the introduction, in 2020, I left my job to pursue education online full-time. I created a course called CSS for JavaScript Developers. To date, I think something like 18,000 students have taken this course, and then others have taken my other courses, too. Which has been really cool. And it means that I've gotten, like, hundreds and hundreds of questions in our community Discord about CSS. So suffice it to say, I've spent a lot of time understanding what people don't understand about CSS. And that's what I want to address in this talk. This talk is called The Secret Mechanisms of CSS. And I want to sort of have that one-on-one conversation with you all and just fill in a bunch of gaps that I think we all have in our mental model. So the first thing that really helped me understand CSS was to stop seeing it as, like, a big monolithic language, like a box with all of the different CSS properties where you just pluck the properties that you need. The way that I see it now is as a constellation of layout modes. Essentially, I see CSS as a bunch of mini languages that are kind of separate that exist under the CSS umbrella. These are things like flexbox, CSS grid, table layout, flow layout. There's a bunch of them, and they all sort of serve different purposes within CSS. And they all behave really differently. A perfect example of this is... And this is also something that makes CSS feel really inconsistent. I have this div class item, which is given a width of 2,000 pixels. I have these two rectangles. I know the scroll bar might be kind of hard to see, which is why I gave it this sort of gradient so you can see just how wide this element is. And check this out. I'm gonna take one of these items. They're identical. They have the same markup, the same CSS. I'm gonna take this second one, and I'm going to move it so that it sits within this other container, div class flex wrapper, which only does one thing. It sets display flex. All of a sudden now, this second item, which, again, is exactly the same as the first item, it's not 2,000 pixels. Now it has shrunk down to fit within the viewport. And I say that this is, like, one of the things that makes CSS feel really arbitrary and unintuitive, because you might reasonably say, like, I didn't change anything, right? It's the exact same CSS. The properties that I wrote are identical. When we think of CSS as a constellation of languages, though, it starts to make a little bit more sense. This first one is being rendered according to flow layout, which is the default layout mode on the web. Most HTML elements will use flow layout by default. And in flow layout, the width property is a guarantee. Like, when you say width 2,000 pixels, you're going to get something which is 2,000 pixels. Consequences be damned. Even if it has to burst through the side of the viewport like the Kool-Aid guy, that's what you're gonna get. You're gonna get a really, really wide element. When I take that exact same CSS and I hand it to flex box, which is the layout mode that we're using for this second one, well, flex box doesn't have the same implementation of the width property. In flex box, this is, like, the ideal size, right? You might say, like, in a perfect world with no other constraints acting on it, this element would be 2,000 pixels. If I set it to be 200 instead, then it does behave the same way, because in this world with, I don't know what this is, maybe 554 pixels of vertical space, we have enough space for this element. But when we pick a really big number, well, flex box takes that input and it uses it in a different way. It's going to use that as the initial value, but then it's going to consider all these other constraints, right? Flex box is flexible, so it's meant to adapt to different situations like this. The way that I explain this to JavaScript developers and really to developers that are familiar with any other programming language is that the layout algorithms are kind of like functions, and the CSS that we write are the arguments that we pass to those functions, so in this first element, the really long one, I'm taking these arguments with 2,000 pixels and handing them to flow layout, whereas in the second one, I'm taking the same arguments and passing them to a different function, which means I get different output, which is the UI that actually gets generated. So let's go through some of the different layout modes. First of all, I want to talk about flow layout, and this is sort of my own kind of term. Like, usually people will say normal flow, or they don't really think of it as a layout mode because it's the default one, but I like consistency, and so I'm going to call it flow layout just the same way I'd call it flex box layout or grid layout. The way to understand flow layout is that it's a word processing algorithm, so like Microsoft Word, right? And this is Google Sheets, but it's all the same. In this world, the layout of Microsoft Word is designed for documents, so we have limited horizontal space, our page is only 8.5 inches wide or whatever, and technically we have limited vertical space, too, like our page is only so long, but we can have infinite pages, and so this is sort of the constraint, right? We have limited horizontal space, unlimited vertical space, and the layout is constructed of blocks, so I have this heading, which is a block, it's a full-width rectangle that sits on the page, I have this paragraph, you could have lists, you could have tables, right? These are the blocks of the document, and then within those blocks, you can have a bit of bold text or a bit of red text or a link, right? This is the mental model that we should use when considering CSS on the web in flow layout, because when CSS was introduced in the late 90s, the web was just a big collection of interlinked documents, right? It's called the web because it's like a giant web of documents, so nobody was building web applications when we started, or when CSS was introduced, that's why we have additional layout modes that are built to handle different cases, and I think this explains a lot about how CSS works by default, is that we have to imagine that this is meant for styling layouts, or styling documents, rather. So, I have this HTML document, three block elements, a heading, two paragraphs, then I have some bold text sitting inside this first paragraph, and just for fun, I want to poke at this a little bit, because the thing about inline elements, as they're called, which are the little snippets that we have within a paragraph, is that they don't have access to all the same CSS that block elements do, so if I set height 100 pixels, and maybe I'll give it an outline of solid just so we can see it, this doesn't seem to do anything, right? Whether it's a really big value, or a really small value, no effect. The reason for this is that inline elements, they're non-confrontational, they're pacifist, they don't want to cause a ruckus, they don't want to make a fuss, they just want to sit sort of where they are sitting in their paragraph, in their block, and they don't want to mess things up. So if I gave it a height, it would push everything else around, and it doesn't want to do that. Padding is kind of interesting, because padding does sort of work, as I increase the value, the box does get bigger, but keep your eye on the second paragraph, the paragraph underneath the paragraph with the inline element. It doesn't matter what I change this value to, that paragraph isn't moving. The box around the element is growing, but it's not messing with the layout. One of the most confusing parts of flow layout to me was display inline block, and I don't know if this is relatable, but for me, there are just a handful of things that I have to learn them over and over and over again, and it never sticks. Time signatures is like this for me. I play the piano, and it took me years to understand the difference between 3, 4, and 6, 8. They're the same fraction. They resolve to the same thing. Why isn't it the same? My partner was an economics major, and every now and then there will be terms in the news, like quantitative tightening, but he's had to explain this to me three or four times, and don't ask me to explain it, because I'm still working on that one. Inline block is one of these things where you read the official definition, and it's just words, like the words just wash over you without meaning anything, but after a few years, I think I've gotten a bit of a handle on what this is. Here's how I would explain inline block now. I would say that it's placed on the page like an inline element, but it's not as much of a pacifist. It does have the ability to push things around in terms of the layout. This will make more sense with some experimentation. Again, I have two paragraphs with an inline element, and now the inline element has been given display inline block. The first thing that we notice is that it is sitting in the paragraph the same way it would if it was display inline, so spans this HTML element uses display inline by default. We see that when I comment it out, when we go back, and I can just actually, this will maybe be clearer, I can switch to display inline, it has no effect. It sits on the page like an inline element does, but check this out. I can say height 100 pixels, and it actually works, like it pushes the other child down, and padding works kind of the same way where, wow, that's maybe too much padding. It does affect the layout. So, this does sort of lead to the obvious question, if inline block is like inline but without any of the disadvantages, why do we even have display inline? Why don't we just have inline block? Why isn't that the way inline display inline works? Well, display inline has a little bit of a superpower of its own, and it's something that is used on just about every website, and it's something that doesn't exist in any other layout mode. You can't do it in Flexbox, you can't do it in grid, only in flow layout with display inline. Building up the suspense here. That special thing is the ability to line wrap. Here again, a span in a paragraph, I've given it display inline block, and we see that there's a bunch of dead space over here, and a bunch of dead space over here. Inline block elements will always form like a rectangle, the same way that block elements do. If I change this to display block, we see that it's the same thing in this case. If I change it to display inline, then it wraps around the different sections of this element, and it line wraps really smoothly. I like to explain this like you have a sushi roll, so it starts as a big tube, and then you chop it into pieces, and you can arrange those pieces on different lines. That's sort of the way that I imagine that, because I think it makes sense. What was I going to say about that? I guess, like, this is just coming to me now, but when we see it like this, it kind of makes sense why we can't use height, because what would it mean, right? Height, 50 pixels, is that the entire thing? Is that each piece? Right, I remember what I was going to do. Just to kind of prove that this is unique to inline, let's grab the paragraph, and let's set display flex. You might think, wait a minute, flex box can do a bunch of stuff. By default, it really doesn't do anything helpful here, but what about flex wrap? Flex wrap exists, line wrapping in flex box, but we see it doesn't work the same way. It doesn't do the inline thing of breaking the element into smaller rectangles like a chopped-up sushi roll. That's the reason for that, right? Display inline block gives us all the advantages of display block, but we can't have line wrapping, which comes in handy in a lot of different places. A lot of people like to do these fancy link effects, like giving them pseudo elements that do cool things, but you can't do that with inline elements, and then you get this kind of behaviour where a link can't fit neatly in a paragraph. Okay. Let's move on. Let's talk about flex box, or as it's more officially known, flexible box layout. The way that I would explain flex box is that it's a different layout mode, and it's concerned primarily when you have a group of things, and you want to distribute that group along one main axis, so maybe you have five or six items, and you want them to sit side by side in a row, or maybe you want them to sit one on top of the other in a column. Either way, flex box is great for that. I built this little demo just to allow us to play with some of these ideas. The special thing about flex box is that the whole system can be rotated by 90 degrees. All the properties in flex box aren't tied to horizontal and vertical. They're tied to this primary axis. So justify content, for example, it's called flex start, which is always kind of a confusing name, but it's because it's the start of the primary axis, so in a row, we go left to right, and so it goes in that direction, and start is at the start of that. If I change it to column, now we go top to bottom. Again, they're still aligned in the primary axis at the start of it, which is like grid doesn't work that way. Flow does have block and inline directions, but we can't just rotate the whole system. I should mention, by the way, this does depend on language, so I've been assuming here that we're working in English. French is the same way, but Arabic or Hebrew go the opposite way, and certain Asian languages, the whole thing is rotated, so you can rotate things in flow layout, but it's not really meant to be done for the layout. It's meant to be done for how you read text. Now, a thing that I think a lot of people get confused about is justify content and align items. I think a lot of people, you sort of just try one and see if it works, and if it doesn't work, you try the other one. It's also not clear why it's justify content and align items. Why isn't it justify items or align content? There is actually a reason for this. The reason for this is that the primary axis, and I will set it back to be a row, notice that the primary axis sort of drives a spear through all four of the children, so I can draw a straight line that intersects them all. The cross axis, which is sort of the other direction, I can't do that, right? Like, if I draw a straight vertical line, I can only ever intersect one of these children, and this affects what we can do for the layout, right? Like, let's grab this. Let's do the second item here, the word to, this item right here. If I inspect it, give ourselves a bit more space, using the align self property, I can move it to the top with start, and we see, like, this element moves up within its own container. I can set it to end, right? So align self moves the element in the cross axis, and I can do whatever I want with this specific item, because it doesn't bother any of its neighbours, but imagine trying to do that, and I will get rid of this now. Imagine trying to do that in the primary axis, like taking this first or the second item and move it to the start. Well, I can't, because there's this other element there, right? It's sandwiched in between these other items, and so when we're talking about alignment in the primary axis, we're not thinking about individual items that we can move wherever we want. We're thinking of it as content. We're thinking of it as a collection that can be distributed, which is why we have these cool options that are totally off the screen. I can choose space between, and now we're not thinking about, like, okay, the first one goes here, the second one goes 37 pixels to the left of that. No, we're thinking about the group and how we're distributing the groups of content in the same way that, like, I think I closed the document, but, like, if you use text alignment in Google Docs, you're not thinking about the alignment of individual letters or words. You're aligning the content, right? So justify content. Justify refers to the primary axis. Content refers to the fact that we're thinking of it as a group. Align items, align refers to the cross axis, and items is the fact that each item can be set individually. In fact, align items is a little bit of syntactic sugar. Like, it's a little bit of a shortcut for setting align self on each of the four items. Like, that's the actual property that gets used. Align items is like a little convenience, something we can do so we don't have to set the same property four times. So that's the idea, right? Justify content is how we actually control the alignment within the primary axis, and we're thinking of it as a group. Align items is how we shift things around in the perpendicular axis, the cross axis. Let's look at a fun situation. I have this form that is using Flexbox because I've set display flex on the parent, and there's a couple things I want to do with this. The first is that when we run out of space, notice that immediately the label sort of jumps to be two lines. Like, we've just, like, by one pixel run out of space, and the input doesn't get any smaller. Like, if I keep shrinking it, eventually the label runs out of space, and the whole thing just overflows. Let's try and do two things. First, let's say that the input should be able to shrink as much as it needs to, and that the label should not be able to shrink, that I don't want this to break upon two lines, which may or may not be the best user experience, but just to kind of understand the way the algorithm works, that's our goal. I think a lot of people think about this where, like, okay, let's grab the label, which is the first child here, and actually, no, let's do the input first. If I want to allow the input to shrink, well, there is a property called flex shrink, and the bigger the number, the more aggressively it shrinks. So let's pick, like, a really big number. Let's pick, what is that, 100,000. Well, it doesn't do anything. It doesn't seem to have any effect, no matter what this number is, like, whether it's zero or 100 or anything, it doesn't do anything. There are two important numbers in Flexbox that are used to calculate the actual size that something is. The first is, and this is what is actually called in the specification, which I think is so cool, the hypothetical size. So if I set width 1,000 pixels, and we saw this a little bit earlier, it's not 1,000 pixels. 1,000 pixels is the hypothetical size, but then there's all this other stuff that's going on, and it's not but then there's all this other stuff that we have to consider, like the fact that we don't have 1,000 pixels to fit the input in. So that's the hypothetical size, but there's another really important size, which is the minimum content size. We can see that sort of at play with the label, where the minimum content size of the label is the width of the word address. If I keep shrinking this, eventually we get to a point where the text in this container just can't shrink anymore, if I shrunk it more, the word address would overflow, and it would be hiding either in front or behind the input, and Flexbox doesn't want things to overlap. So there's this minimum content size, which is based on the content. We can solve that problem by changing the min size. So I could say min width 120 pixels, let's just say. So we see that that works. Now we're telling Flexbox, you can't shrink this thing below 120 pixels, and this doesn't quite look right, so maybe 110, but of course the problem that maybe you see with this is that if I change the label, like if the text changes, well, I just made up a number, right? I picked a number that happens to work in this situation, which doesn't really feel super maintainable. Instead, I'm going to set flex-shrink to zero. Now what this does is it says, hey, you're not allowed to shrink this thing at all. The key with flex-shrink is that it won't allow you to shrink something below its minimum content size, and so this sort of explains why this input isn't shrinking, because, and this does vary depending on the browser, in Chrome on macOS, it has decided that the minimum content size of this input is 258 pixels, and I'm zoomed in, so it's actually smaller than that, but that's just to put a number on it. That's what's happening here. The same way that if I get rid of this flex-shrink, like the label can't shrink any more than the width of the word address without overflowing. For whatever reason, the browser has decided that this is the minimum size for the input, and so we can fix that by setting min-width zero. Now this is another one of these special incantations that if you work with CSS, you've probably memorized this. It's like, hey, if the thing isn't shrinking, throw min-width zero on it. At least this is, I should speak for myself. I shouldn't assume all of you do the same thing, but for myself, for a long time, this was just like, hey, if it's not doing what I want, try this, and maybe it'll solve your problem magically. When I do that, we notice that the input does actually shrink, because now the minimum size isn't 258 or whatever that number was. It's zero. And then if I uncomment this, we see that we have achieved our goal, which is now the input is the one that shrinks and the label won't line wrap. Again, this, like, whether or not this is a good user experience is another question, but just to explain, that's how these numbers all factor in with each other. All right. I still have 17 minutes. I am ahead of schedule. Let's talk about positioned layout. Positioned layout is hard to explain, because it's not really one thing in the way that flow layout is the word processing algorithm and flex box is the distribute things in one dimension algorithm. In positioned layout, we're going to take the elements that would ordinarily be positioned according to one of the other layout modes, and then we're going to anchor it to something else, and the something else is what depends based on sort of the sub-layout mode that we're talking about. So in positioned layout, you can have position relative, position absolute, and what that property does is change what the something else is in this sentence. Let's start by looking at that same form we just saw, and we're using flex box on the parent, so both the label and the input are being laid out according to flex box, and now I'm going to select the input, and I'm going to say position relative. Now, this doesn't have any effect, because what position relative does is it opts in to positioned layout. It changes the layout mode, but it inherits whatever the calculated layout was, so it's relative to its non-positioned spot, to its default spot, which is why usually positioned relative doesn't do anything, but because we're now using positioned layout, I can do stuff like this. I can say top 32 pixels, and the thing slides down by 32 pixels, and if I didn't have positioned relative, I couldn't do that, because top is a property that is implemented in positioned layout. Now, on its own, positioned relative isn't that interesting. It's usually used in tandem with other positioned elements, so let's talk about that. Absolute positioning, I like to think of as the magazine layout. It's useful when you want to do collages and the kinds of layout you see in magazines where I have an image that I want to sit in a very particular spot. I want it to sit above or behind other things. Positioned layout is all about stacking things, and if we look at an example of this, the cute example I came up with is that we have this unruly teenager, and we've grounded the teenager and said, go to your room, but the teenager says, aha, I have this position absolute. Normally, the teenager would be stuck in its room, which is that box, but no, the teenager refuses to do that. By default, absolute positioning will take the element out of its calculated layout, which in this case would be flow layout. If I got rid of that again, room doesn't set display anything, and it's a div, so we can deduce that it uses flow layout. In flow layout, things sit at the top left corner of their containing block, which is usually their parent, but then no, no, no, we're going to add position absolute, and now we're using what they call the initial containing block, which is a rectangle the same size and shape of the viewport. Now, the thing that I think trips up a lot of developers is that it's not always the initial containing block. There are ways to change which of the elements' parents serve as the container. For example, on the room, if I say position relative, well, now the element is stuck back in the room, right? This is the ace that the parent can play and say, aha, you are stuck in your room. The way that this actually works is that when the browser is trying to figure out where to put this pink circle, it sees that it uses position absolute, and so it's going to look at its parent, in this case div class room, and it's going to see, are you also using positioned layout? And when I say using positioned layout, it means setting the position property to something other than static, which is the default value. If it sets relative, if it sets absolute, if it sets fixed, all of those things will sort of give it the check mark so that when the browser is trying to figure out where to put this pink circle, it's going to use that element. If the parent doesn't set the position property, then it goes further up the tree. In this case, I think the element on top of this would be the body tag, and it would say, hey, does the body set position anything? And if not, it goes to the HTML tag, and if that element doesn't set anything, then it uses that box the same size and shape of the viewport. And again, this is something that makes CSS feel arbitrary because the same CSS, position absolute, top zero, left zero, totally depends on an element that might be like 10 or 15 levels up, right? This is a very simple example, but in a real website, you have many, many layers of nested elements, and this is one of those things that if you don't understand it, the whole thing just feels so unreliable. Let's talk about fixed positioning, and the scenario I want us to imagine here is that we're sitting on a train and we're watching this beautiful landscape scroll by outside the window, but then, oh, no, a fly comes and lands on our window, and yes, we're going to have to use our imagination because I didn't feel like finding some clip art. That's supposed to be a fly. The way fixed positioning works is that it's not part of the document, which is scrolling by in the viewport. It's literally on the glass of the viewport, right? Every website, you have a scroll bar, and that changes what the viewport is looking at. In fixed positioning, we're taking it out of its calculated layout and sticking it to the viewport itself, which is why the element doesn't move as you scroll. Everybody's favourite property, right? Z-index. There's so many things, so many gotchas, so many foot guns with Z-index that can really mess up your day. The first one is I think the one that we all run into at some point, which is that I have this heading, H1, I have an image. The text is stuck behind the image because I have this negative margin, and we don't want that. We want the text to be legible, so I've given the H1 Z-index 10, I've given the image Z-index 1. The idea with Z-index is it's supposed to control the layer number, so bigger numbers will be stacked in front, but it doesn't seem to be doing anything here. Now, the way I would have explained this maybe a decade ago would be something like this. In order to use that index, it has a dependency on this other CSS property, that this property only works when I set position to relative, right? That was the pairing in my mind. In order to use this, you have to set that. And it's not wrong. Like, it does, it solves the problem, but it's an incomplete explanation which is honestly a little bit misleading. The way that I would explain it now is that in this situation, with this CSS, both of these elements are being laid out using flow layout, and flow layout never implemented the Z-index property, so it's the same thing as if I was saying, like, food spaghetti, right? No effect because the layer says, I don't know what that is. That doesn't mean anything to me. When I set position relative, we change the layout mode which is being used. In fact, something cool about positioned layout is that anything that uses positioned layout will automatically be in front of anything that doesn't use positioned layout. In this case, we don't actually need Z-index at all. When I review code bases, I see half of the Z-index usage I see doesn't even need to be there because you can use this little tidbit, right? Positioned elements sit in front of non-positioned elements. You can rely on the DOM order. You don't have to start the nuclear arms race of ever-increasing Z-index numbers. But to keep going with this explanation, right, positioned layout is not the only layout mode that implements Z-index. Check this out. I'm going to grab the parent which is this main tag, and on the parent, I'm going to set display grid, and just like that, the text shows up in front again, and it actually is using Z-index. If I make the image 11, 11 is bigger than 10, so the image moves in front. If I set the H1 to 12, 12 is bigger than 11, right? It's the exact same property that works the exact same way, but there is no position property in site because the grid layout mode also implements Z-index. Flexbox does too. I'm going to have to change the flex direction to a column just so that they actually overlap, but, yes, in Flexbox 2, the Z-index property is implemented. Good little thing to know. Let's look at an even more complicated situation. I have a header with this pink colour. I have a tooltip, and I want the tooltip to sit in front of the header. The header has position relative Z-index 2. The tooltip has position absolute Z-index 999. Now, both elements are using positioned layout, so the Z-index property is working. It's not that I'm forgetting to use the right layout mode. It is working as intended. This number is a heck of a lot bigger than this number, but still, the header is in front of the tooltip. The reason for this is that Z-index values are not compared globally. They are compared in something known as a stacking context. I don't have quite enough time to talk about stacking contexts, but, essentially, whenever we use Z-index, we create a little envelope that wraps around all of its children, and so the problem here is that I have this main tag, and main sets position relative Z-index 1. What that means is that, like, at the top level, at the global level, header has a Z-index of 2. This main tag has a Z-index of 1, and that means anything inside main is always going to be underneath anything inside header, because, like, the header, we've said, is in front of the main tag, right? So we have this, and there's no, like, visual indication for it, but the main tag wraps around all this stuff, and everything in that container is going to be behind that header. The way that I explain this is that it works quite a bit like semantic versioning, so, like, this Z-index 999 is doing something. It's not ignored, but we can imagine the sort of global Z-index value not as 999 but as 1.999, and so when we're comparing this element to this one, it's comparing this number to that number, so it doesn't matter how many 9s I add, right? 1.anything is always going to be smaller than 2. The solution to this problem is, well, in this contrived situation, is just not to have Z-index on this element, right? Because then, if I get rid of this 1, it's not about, like, siblings in the DOM. It doesn't matter that there's an element here. It only looks at the elements that create a stacking context, which is done by using Z-index. At least that's one of the ways that it can be done. So now, if I remove the Z-index from main, it's able to actually compare this number on the header, this 2, to all of the 9s that I've added to this element. So, good little thing to keep in mind. Now, I could keep going. Like, I have so many of these little things that I've learned about CSS. If you'd like to keep learning, I do have a course, as has been mentioned, called CSS for JavaScript Developers. Just to quickly talk about the format of the course, I built my own course platform so I can do things my own kind of way, so there's written lessons that feel like a blog post, but with interactive elements. There's a bunch of these short videos. There's even, like, some minigames, which is the fun thing about building your own course platform, is you can build little puzzle games to help you make sense of CSS. If you're interested, you can learn more at CSS4JS.dev. You can also just Google Josh CSS course and you should find it. That's my talk. Thanks so much. Bye.