 Hey there, I'm James Steinbach and I'm really excited to be speaking with you today about an EmberDos guide to CSS Grid. CSS Grid is a really awesome, cool, and powerful block of CSS. It gives us a lot of powerful tools we've never had in any CSS layout method until now. This combination has not existed until today. And by today I mean 2017 when all the major browsers shipped full grid support. Grid gives us a responsive CSS only layout method. It only needs grid styles, floats, clear fixes, don't need that, inline block, white space problems, don't have to hack those. Only grid styles, it allows precise control of columns, rows, and gaps in our grid and allows us to position children anywhere we need to. However, as a Spider-Man said, with great power comes great responsibility, with grid, with great power comes great complexity. And this slide is full of little words, not because I want you to read them all, but I'm not very thoughtful about legibility, no, because I don't need you to read them all, I just want us to collectively feel the weight of this wall of text, right, it's a lot. And especially if you're not a CSS specialist or expert, if your day to day is consumed with a lot of normal JavaScript things, working on frameworks, release updates for Ember, refactoring a bunch of components to use Glimmer, getting all octane-ified in your projects. Great, great, great, great. If you don't have time probably to focus on 30 new CSS properties, and not all of them are new, some are from Flexbox, but if you've got sharp eyes and you're paying attention, the Flexbox properties are all the same ones that you always have to look up on CSS tricks every time with that cool little visualization that you've got bookmarked there. It's not the easy Flexbox, it's the tricky ones. So this is like trying to drive to the horizon down this road, and we're not going to do that. I want to get to the end of the road, but I don't want anybody, you know, to get motion sick. So we're going to trim it down, we're going to learn seven things today, and these seven things you see on your screen now are going to give us the vast majority of the power we need, and I'm going to make a big promise to build almost any grid you need in real life. That's a big promise, but I think it's going to hold true. So let's look at this optimized road, let's hit the horizon on that path. So without further ado, the short, happy path to grid. We'll look at code first, and then we'll break it down and learn what all these lines mean. Display grid is a starting point. Just like display flex, it's the right way to tell the browser, hey, use grid layout algorithm on this component or element to lay out all of its children. Not grandchildren, just immediate children. We're going to provide some measurements for the columns, and I'll show you what FR means in a moment. We're going to define some areas, we're going to name the spaces where we can put an element. There are four names, header, content, sidebar, and footer. Remember those, because we're going to see them on the very next slide, and we're going to put gaps between rows and columns, and you think that's a lot of complexity on the parent. What are we going to do to the children? Actually, grid moves the complexity. With CSS grid, all the measurements, all the layouts, all the rules, all the constraints live on the parent, and all the children need to do is get told which area to fit themselves in, and all the words in grid area here are part of grid template areas on the previous slide. Also really powerful stuff, you don't have to define a ton of math and a ton of measurements and a ton of margins and percent-based width and all that on the children. We're moving all that complexity off of the children onto the parent, the grid itself, which is really awesome. It makes our code so much cleaner, because we're not searching through three or four different selector blocks defined with and measurements. We're scanning four different selector blocks to find a named area. All the measurements, all the complexity is defined on the grid itself, and children just are told where to go. Very cool method here. So, let's look at these properties we put into a grid container. See what we got. Well, grid template columns is the first thing. Display grid is a given. We've already mentioned that. But let's look at how to measure columns. Columns set the proportions for tracks along the inline axis of the grid container. And you think, why wouldn't you just say horizontal, James? Or just say columns. There's too many fancy words. Just say columns. I respect that. And I'll show you in a second why I'm calling it an inline axis. It's a new evolution in CSS that is actually going to be very powerful once it's widely supported. But this gives us our column measurements and the value we use is any valid length values in a space separated series. For example, you can do 30% and 150 pixels and 30%. And unlike Flexbox, if you don't use up all your grid space and you define your columns, grid's like, that's cool. I don't mind empty space. I'm not afraid of the silence. Flexbox is like, no silence. I'm going to stretch things unless you tell me not to. And so grid is different from Flexbox in that regard. Your precision stands without being artificially stretched or squished. However, if you want to use up your empty space, fractional units are a really cool way to do that. Behold our next code, grid template columns, one fraction, 12Ms, 8Ms, and a fraction. 12 and 8 are fixed measurements that are relative to the font size, but they're fixed in that grid. And after they're used up, grid goes, OK, in the parent, is there still empty space? Are 12 and 8Ms leaving room? Cool. If I've got a fraction at the beginning and a fraction at the end, that's two fractions, I've got to divide all the remaining space in. I give one out of two here and one out of two here or split into halves. And what we've got here is a self-centering layout. The 12M and 8M columns are always going to be put together centered in the middle of the grid. Pretty cool stuff. Grid template rows works essentially the same way, but whereas columns operate along the inline axis, rows operate along the block axis. And again, in a second, I'll show you why I'm saying inline and block, and not top, bottom, left, right, those kind of words. Same value. And look at examples. We could do a fraction and then two fractions here. The top row is tall enough for its content, and the second row is twice as tall, one and two. Here we've got a repeat function, which is a cool new trick. Our top row is 50 pixels tall, and all the rows that follow are 100 pixels tall. Neat little way to do something like a table layout if you're building an editor or an admin interface for something. All your titles would go in that little 50 pixels column, and then each of your rows with a whole bunch more data would be taller below it. But having shown you pixels on that screen, I'm going to now turn around and say, oh, go easy on the pixels, though, OK? So I want to give you a warning about fixed heights. Fixed heights really easily cause overflow. If your content is longer than whatever 100 pixels makes room for, it's going to flow through the margin, least bad problem, flow down into the next row, not into the element, but covering up or obscuring part of the next row. Next decentest option, worst option, get covered up by the next row or obscured by an overflow hidden property on its own row. Accessibility is not just something we do for people who have what we perceive from our privileged spot as lowered ability. Accessibility is for everybody. Fixed heights on grid rows creates accessibility problems for users of 2020 vision. It's not a matter of limitation on them. If we program things wrong, we create legibility and accessibility problems. So accessibility is for everyone, not in us versus them, kindness of our heart, aren't we special, give ourselves a star proposition. It's just building the web for people. Grid is going to automatically protect your content unless you put a fixed height on. That's an awesome part of the web. So use flexible values for your row heights like auto and min content and max content, fractional units are pretty decent too. Logical properties, quick sidebar. The reason I've set inline and block is because we've got a new way of thinking about where things are located and what directions things go in CSS. This is an evolution of the spec. For a long time, everything we've positioned, we've described with physical properties. These are related to the viewport, the device itself. Top, right, bottom, left. Those break down really quickly, right? What if you build a website and you start translating it and you cover most of Europe with your languages like French and German and Dutch and the handful of others and it's all left to right. You got English and all those European languages and you're pretty covered, right? And then marketing and biz dev decide, hey, we're expanding our market into the Middle East as well and we're going to have users who read in Hebrew and Arabic and now we need to be able to support the same site but our layout has to be right to left. Well, suddenly our physical property words right and left no longer make sense. They no longer accurately describe where content is and we have to find a way to reverse all our margin rights and border rights and all those things because we need them all on the left now. One more complexity, not all languages are horizontal. All of our left to right languages which probably cover the majority of people in the room. Today, all of our right to left languages as well, it's all horizontal. So inline is a start to end of a line of text inside of an element that's horizontal. Those are horizontal languages and block is a start to the end of a block of text like a full paragraph for it. If you decide to continue expanding your market in this hypothetical app we're talking about and now you're bringing in further East countries and you're expanding all the way out into China and Korea and Japan and you've introduced a handful of dialects now that have column text. Their writing mode is a vertical. Now the start to the end of a line of text is a vertical line, not a horizontal one. And the start to the end of a block of text is a horizontal line, not a vertical one. Grid automatically responds. In the slides that follow I am not going to change the CSS at all. I promise I'm only going to put different attributes in one case, the CSS property on a wrapper element. I'm not going to change the grid code at all. Here's direction left to right. Here's direction right to left. I didn't change the grid code at all. It automatically turned it all around. Whoa, how sweet, right to left support for free? Yes. And now one more, writing mode vertical, left, right. You can see the browser rotated the text automatically even though the characters are still English characters. All Latin characters. It rotated the text and the entire layout. I did not change the grid CSS at all. I just put this property on a wrapper. Amazing, that's all we did. Grid gives you so much responsiveness for free. This is amazing. So we've made rows, we've made columns. Back to grid, let's name those intersections. When we use white space that's cool and I'll show you why white space is cool on the next slide. And if you need to create a blank cell in a grid template you can use a period for that. So here we are, same thing we saw back at the beginning. Header is one grid area that spans four columns and fills one row. We've got a gap and a gap in between them, body and sidebar. And then we've got footer, much like header spanning four rows. One area though, one element will be assigned to footer, one element assigned to header. And notice what I said about white space. I've got a couple of spaces after that third header and the third footer, a few extra spaces after body and a whole bunch of extra spaces after each period. Why did I do that? It's cool that grid doesn't mind how many spaces you use because you can not just program your grid, you can draw your grid directly in grid template areas and the outcome will look like the CSS. That's powerful. If you are a visual learner or identifier of things this is gonna rock your world. This is super duper. Look at your CSS. That's what the page is gonna look like. It's right there. Love it. You can go a little more ASCII art-ish and use Emoji but I don't recommend that. It's harder to read. You're running the problems with contrast and most text editors between light and dark mode and your zero or sync monospace fonts don't apply anymore with emojis. And you might even run into a browser implementation issue with Unicode mapping. But a couple limitations on grid template areas. A named area can only be one rectangle. It can't be an L shape. It can't be like a stair step kind of try to make a fake diagonal. All the cells have to be adjacent. You can't start a named area here, continue it here and then put a little more down here and expect content to kind of flow between them in those breaks. What you're describing is a whole different CSS spec. It's real though. It's called CSS regions and it doesn't exist in browsers yet. It's been under discussion forever. Yeah, sorry. And grid template areas, their names have to be strings that start with letters, not numbers. If you start a grid template area name with a number like 1A, that's not gonna work. A1 is good. And when we look at the children, we'll see why we can't use a number for a named area as the first character. But for now, just trust me, don't do it. Okay, a bonus. Sorry, I said there are seven. Here's a bonus. Grid template is just a shorthand though. So it's essentially summing up what we've already learned. You can put grid template columns, grid template rows and grid template areas, those three properties, all in one shorthand. It's kind of like background containing background color, background image, background position, background size and a couple others. All three properties you can put into one property and now what have we done? This is amazing. I just love this so much. This is where I start when I write CSS grid. You can not only look at your code and see exactly how your layout is going to turn out, disclaimer, your editor is not going to highlight with orange and blue. That would be a really cool VS code extension if somebody could make it though. That would be really nifty. Your code editor is not going to highlight like that. But not only can you visualize the entire grid layout that the browser is going to render, every row ends with its height. Every column ends with its width. All the relevant information to rows, columns and their proportions is right there in one chunk of CSS. That is amazing. That is boiling down a lot of complicated stuff to a very readable, identifiable, manageable chunk of CSS that visually matches the end result on your browser window. I love this so much. I'm so excited. This is how I love grid. This is what I do. And you can make gaps too. Gaps are a space that exists between columns or between rows. Used to be called grid gap. You might remember that if you've seen tutorials for a year or two. But grid gap has been deprecated and air quotes is a name. It's CSS, nothing ever gets deprecated for real. But it's now just called gap because Flexbox is going to be supporting gap between children. Firefox already has that support. Chromium and WebKit are hopefully, hopefully not far behind. It's a shorthand for the row gap, 20 pixels and then the column gap 30 pixels. But like margin, it's also a self-expanding shorthand. So if you just say gap 10 pixels, you'll get 10 between rows and between columns. That's it. That's all the new properties you need to know to build a grid container. I showed you a couple new values on the way in those slides. So let's dig into those two now. Fraction and repeat. Fraction is one fraction of the grid's free space. What is free space? It's whatever pixels are left after all the non-fractional units, column measurements or row measurements have been used up. So after you calculate your gaps, after you calculate all of your pixel and viewport width and M and rem and percent based column widths, anything left in the parent grid is available as free space for fractional units to divvy up. Based on the total number of fractional units you've put in your grid row or grid template row, grid template column property, grid is going to divide the free space into that many units and then portion it out appropriately. Words are great, but let's look at code instead. Here's 300 pixels in the first column and then one fraction, it's super greedy. It just gobbles up the rest of the empty space. If we put this in a container that was only 300 pixels wide, one fraction would effectively be zero pixels wide because there is no pixels left to divvy up. Here's our self-centering layout. Once again, 12Ms and 8Ms are non-fractional units. They and the gaps are divided out first and then everything left gets divided into half a chunk here and half a chunk there. You can even do a column layout that's all based on fractions. Here the browser says you've given me six units to divide up, one plus two plus three. So all the space is free except for a couple of gaps. I'm gonna divide the rest of that pixel value into six, one for the first column, two sixths for the second column and three sixths for the final column. Very much simpler way, I think, to program proportional grids without having to get into percentages and decimals and complicated math, especially division by three related stuff. So let's walk through that all in one shot. Let's build a grid from scratch. Here's a blank grid. It's got four columns all squished together on the edge. They're just barely wide enough to have a little bit of color. So let's add gaps. Cool, thank you, browser. You put gaps in, I love it. Let's give the second and third column better width. It's a 50% of the parent for the first column or the wider column and 25% of the parent for the narrow column. Awesome, columns one and four still empty. Let's change them from zero to one fraction and now the layout self centers. And we can go ahead and add in some rows. So we've got a header and a footer and this is the code we've been looking at like all day long, more or less. Only with some fixed rows just to give it space in the demo. We've just built a non-trivial layout. You may say, this is really simple. That's like every blog, like most WordPress themes, am I right? Ha, ha, ha, let's make better WordPress too. No, we won't do that. But this is actually a specific layout from CSS lore, if you will. It's called the holy grail of CSS layout and for like a decade, CSS blogs and tutorials have walked through different layout options and techniques and said, how well can that layout technique accomplish this thing? Full with header and footer, centered layout with a wide content and a narrow sidebar and the content and sidebar the same height so the background colors can extend all the way from top to bottom. We just learned how to do it in a grid in about 15 minutes of looking at code and 30 seconds of walking through an animation. I hesitate to use the word easy, but it would be hard to see how grid could make that simpler. This is very manageable and a really powerful thing we can do with not a ton of syntax and not a lot of code written. I love grid. We also saw a repeat earlier. As you might have guessed, it repeats a certain length, certain number of times. So repeat 12 times, one fraction. Anyway, 12 equal columns. Let's pretend there's a 20 pixel gap too is bootstrap. This is a really neat way you can basically migrate grids off of bootstrap and into pure CSS if you need to. So grid child properties, everything we've just looked at, all of those things, properties and couple values, that's all for the parent. What do we put on the child however? Buckle up. I've got a whole slide in this section. Grid area, that's all. What value do we use? A grid template areas name that we already set on the parent. Now, here's a quick caveat. Here's why we can't use numbers as the first character of a named area. Grid template area accepts a different kind of value, which is up to four integers separated by slashes, and those are manual row, column, start and end values. If you start a grid area with the number two, oops, browser's gonna be like, oh, two, are we doing our row start? And if you do like two dash A, it will actually say no, that's actually invalid syntax. It needs to be a letter prefixed string. And you can't just say two because the browser's gonna go, oh, row start two, let's do it, man. So yeah, please don't. But grid area, all you need, and you need a named area string from your grid template areas property. Now, it's all we have to do with the children. That's all we have to do with the children. So congrats everybody, y'all know grid. I'm proud of you. Give yourselves a round of applause, okay? It sounds really feeble, just me standing in my basement clapping, sorry. But if you're all clapping at home too, then we'll just have a huge amount of clapping in the world and it will be beautiful. So before we go, let's dig into a couple of practical examples. Everybody wants to know, how do you center a grid in CSS? Ha ha ha, stack overflow joke, Peter Griffin meme, moving along, three lines of code in grid. Also, incidentally, same three lines of code in Flexbox, but you start with display flex. You just put these three properties on the parent and one element inside of it will automatically be centered as long as the parent is taller and wider than it. Cool, it's not a joke anymore. It's actually really manageable. Cool, ha ha, let's do something non-trivial though. Back to the idea of we've got an admin interface, maybe we're letting people edit blog posts or some other kind of published content. Here we've got a grid. We can not set up our rows and columns on the wrapper element that contains all these rows and then get children of each row element to respect the columns. That's like, that's grandchildren kind of generations and we can't do that with grid yet. Subgrid is coming, it's in Firefox and Chromium, I think, behind a flag in one or both browsers and hopefully WebKit eventually, hopefully quickly, really. And once we have subgrid, we will be able to do that. But for now, what we're gonna do is we're gonna make each row in this table, I use table and air quotes, it's not an actual table element. Each row is going to be displayed grid on its own. We've got two rows, title and date, actions and status. That's pretty self-explanatory. Each of their heights is auto, whatever it needs for the words. Then we've got a fraction as the width of the title and action column and then the date and the status tag are maxcontent. And maxcontent is a cool new keyword in grid. Essentially what maxcontent says is I want the maximum width this content could be if we don't create any line breaks or hyphenation. Don't go wider than that, don't go wider than the maxcontent, just how wide will it be if we don't artificially break any lines or words. So if we had May 1st as a publication date, the word published would not be hyphenated even if we had a really narrow viewport or a really wide element in the next column pushing it over. We'll never line break between February and 19th without property. Instead, if our post title gets really long, it will line break. And that's a more legible way to go for things. Let the post title have the break and don't force your date to wrap. And then we've got a half a gap, half a rem gap between everything. Let's get a little more complicated. Let's take a responsive component, for example. Some of you are saying, wait, wait a second, don't you take grid, this is columns. James, this is only columns. You put a wrapper around photo and bio. You put a wrapper, a div around the header, which contains name, title, and contact. And awards, those four elements. Two wrappers, one for each pair of elements. Boom, you're done. You don't need a grid for this. You just need a flex box. You can even float that. Get out of here with a grid talk, okay? Aw, I'm sad. But actually, I'm gonna fool you for a second. This is all laid out with grid without wrapper divs. And the reason for wrapper divs will become apparent in a couple of slides. But here's what the grid looks like. There actually are rows. Photo and awards are allowed to overlap and share that second row with each other so we don't see a single full-width row gap dividing the entire layout. We're kind of smushing past each other and creating the illusion of there not being rows. The column with photo and bio in it is gonna be 30% of the parent and then everything else, the fraction of what belongs to the header and awards. So here's what this looks like actually in the grid. Got some nice blue boxes to help us see how things are put together. We've got six cells in the grid. The picture is allowed to adjacent cells labeled photo. The awards is allowed to adjacent cells marked awards and header and bio are just in their own individual cells. Now again, why wouldn't we wrap divs around this and just do it all with float? Well, because grid is simpler and because responsive, now your designer comes back to you because again, there's just delays in things and it's a week later and they say, cool, here's the middle of the road, medium-width breakpoint version of that component. And now you're like, oh, I put a wrapper div around the photo and the bio and another one about around the header and the awards and now I'm in trouble. Now you gotta refactor your markup and figure out something from scratch. But if you had used grid and all four children, photo, header, bio and awards, were just children of grid and using grid to lay them out, all you've gotta do for this is change grid template. Just stick this in a media query for the right min and max for that medium zone and photo and header share a row, bio and awards, each become a full row. The photo will only be 150 pixels wide and header gets the rest of the space. And we've reduced our gap. So now it's one ram both directions instead of one between rows and three between columns. And now we're perfectly set up to go one smaller because you've got your mobile comp as well and now we're dropping all the text and so we're gonna do this with our grid template much, much shorter. Photo and header are the only areas we need. Notice however, we have to explicitly hide awards and bio. Grid will not hide them automatically simply because there's no longer a grid template area that they match. Grid is actually very, very content friendly. It wants people to read your website, okay? So what it will do is it will create a bonus row underneath header and throw the bio in there and then it'll create another bonus row underneath the bio and throw the awards in there. Grid will just make up two bonus rows even though you didn't define them in grid template and it will preserve your content. So if you need them invisible, you have to do that manually with CSS. You have to do it on purpose. Grid loves your content and it's not gonna hide it unless you tell it to. We can also do a fun thing with like image layout. It's kind of like masonry-ish but this is all manual. I one is a two by two, I three is tall, four is tall, six is tall, eight is wide and wouldn't you know our grid template looks just like the output. I one is a square, three is tall, four is tall, six is tall, eight is wide and everything is evenly sized. This is the power and the beauty of grid. When you make a grid template, it looks just like your output. And when you use grid template with the row heights down the edge and the column widths across the bottom, it's all legible and manageable in one chunk of text. Your CSS looks like your layout and it's all in one block. I love this. So last thing I wanna cover for you is a couple of gotchas, some tips and tricks I've discovered on the way. Images assigned to a grid area will obey the grid cell size and maybe end up stretched or squished or something not in their intrinsic aspect ratio. So either wrap the image in a container element like a div that's an okay place for a div wrapper that means nothing semantically. It's just there to help with the image's sizing or cool trick, you can make the image object fit cover in your CSS. That will tell the image, go ahead and fill the entire grid area, but behave like you're a background image using background image size, your background size cover. And every browser that supports grid supports object fit. So win, win. Animating grids, can you do that? Some browsers can animate between grid template columns and rows values if there's a same number. You can't go from three columns to four. That's not an animatable way to do it. And you can't animate between different units. For example, your first column can't animate from 10 pixels to one fraction. Those are just impossible things. Gap is a little easier to animate. You'll get more browser support for that. And no, you can't animate an element between two different grid areas. That would be super cool. Not gonna happen, because there's too much layout complexity. And IE 11, gotta say a word for IE 11. Some of you might still support it if we were all in the same conference room. I would say raise your hands if you're still supporting it. I'm really grateful we recently dropped it on the current projects I've been working on for the last couple of years. But yet just recently dropped and got to refactor and let go of a lot of code. Fun fact, IE 11 was a first browser to support grid. Not fun fact, the grid spec wasn't finalized yet. So IE 11 implemented its own non-standard version of grid spec. And Auto Prefixer, if you configure it to grid true in its options, can help. It can emulate some of the things that IE 11 doesn't support like named grid areas. It cannot backfill or polyfill gap. IE 11 won't support gap full stop. You can't hack that with Auto Prefixer either. So it actually recommend is not using Auto Prefixer to do grid, but rather use a fallback layout for CSS. Like something like Flex or Floats or whatever. It is the worst best for your team for IE 11. And here's what you do. The layout you give IE 11 users is usable. Nothing is broken or hidden. You use an older code, that's fine. It's a boring layout. It might always be one column or two columns. Cool. Everything is going to be accessible, legible, interactive. You're not going to hide or break anything. But you're also not going to use grid and get all the nuance and cleverness of grid layout. And if you've got a strong IE 11 user base, sadly but true, IE 11 users are at this point largely used to significant chunks of the web not working for them at all. That's bad. We don't want to alienate people just because of an old browser they're probably locked into by an enterprise workplace or some environmental constraint. If you give them readable, usable content that's in one boring column or some simplified layout, you've given them a working website and we're doing better than I could name some big tech companies that don't support IE 11 at all. So if you still have to support IE 11 because of numbers, please give them fallback CSS. I wouldn't try to use Auto Prefixer because you're going into too many issues with GAP. But give them fallback CSS, it still looks usable and is good to go. And that's all. I'm James, I work at Dockyard. I love to talk about grid and other CSS things. So I'll be in Discord today, chat with me there. I'm on Twitter at JD Steinbach and you can find my code at github and my blog at dot com all in the same handle. But I like James, not JD. Anyway, y'all have been a great audience. I assume I'll give you the benefit of the doubt. I'm sure you're a great audience. Thanks so much for tuning in today. Have a great day and stay well, everyone.