Modern CSS Layout - Decking Zombies with Style
Apocalyptic Ebb and Flow
In the beginning, there was the flow (i.e., the natural flow a website took, with one element right after another in endless succession). It was like putting the human resistance army into one long, single-file line. It worked okay, but it wasn’t pretty or efficient, and readability was terrible on wide screens.
Next came tables. They were far better at laying out content and, with some software tools to write the complex code for you, you could build interesting and vibrant layouts. They were exact, pixel perfect, and worked well across browsers. However, even with only a handful of screen sizes, they struggled under their inflexibility. You could make them look great at one size, but if a visitor’s screen was a different size, the site was too small or, worse, too big. Without the responsive techniques we have today, too big meant a lot of scrolling to find what you were looking for. Tables also failed to separate style and content. Keeping style and content separate, in theory, allows us to keep the same HTML and change the look and feel of a page (a la csszengarden.com). When the layout is built into the HTML, you have to rewrite the HTML whenever you want to change the layout.
Then along came CSS, with two properties you could use for layouts—float and position. We looked at them in an earlier book Beginner CSS: Like Putting Lipstick on a Zombie. Each of them had its strengths and weaknesses and, in a responsive design world, the weaknesses showed through—badly. Floats were great for two-column displays, but it is difficult to create anything much more complex than that, and it is even harder to maintain, particularly when you have to account for multiple screen sizes.
Positioning allowed you to be very precise with where you put pieces of content, but it’s also rigid and doesn’t respond well to the screen-size ecosystem that web designers and developers must deal with today. It is too rigid for complex layouts in a responsive world. While usable, it’s difficult to adapt between phone, tablet, and desktop screens.
Also, neither floats nor positioning could handle centering easily, especially vertical centering. Thus, the human resistance deities that are the people who write the CSS specifications created new layout forms. First came CSS columns, then flexbox, and then grid. All are excellent tools for creating complex layouts, and you can even use them in combination. All have their strengths and weaknesses to consider.
And, like a baseball bat to a rogue zombie or an airstrike to an oncoming horde, using the right tool for the job will make your post-apocalyptic life much longer and more enjoyable. Let’s see how these methods stack up against each other.
Zombie Inline Block Heads
Before we look at any particular layout method, we need to discuss a few concepts.
Two important notions that come out of normal flow affect how we understand layout: block and inline. Some elements are, by default, block display and start a new line every time we come to them. Thus, for English pages, we could say that the block direction is vertical or downward, because each block element moves us further down the page.
Inline elements flow in a perpendicular direction to block flow. In English, inline elements flow from left to right.
It’s important to remember that many languages don’t flow in the same direction as English. Some flow right to left, and some flow vertically. If a page you designed in English is translated into one of these languages, the content may no longer flow in the same inline and block directions, and, thus, your layout may look like zombie barf instead of the zombie surface-to-air missile you set out to create.
Therefore, keeping your designs agnostic of their writing direction can increase the reach (and, therefore, zombie-stomping potential) of your web page. Now I’m not saying that you have to design the layout perfectly in every language direction (unless your audience is global and you want to speak to them individually), nor am I saying that you can’t or shouldn’t make tweaks specific to a particular language direction. I’m saying that if you can do the work once and have it look good in most language direction contexts, that’s better than having to restart from scratch with every new language or language direction.
Zombie Width and Height
One problem with being language-direction agnostic is that many of the dimensional properties we have are stuck in an English/left-to-right context. Width is only ever horizontal, and height is only ever vertical, but if you’re translating to a vertical language, you’d want width and height to switch along with the writing direction. That’s where the inline and block direction we discussed earlier comes in. These properties work in all modern browsers—which is to say, not in IE, but if you don’t need IE support, have at them.
Note
While there is good support for the properties discussed below (sometimes called "logical" properties while width/height are called "physical" properties), there's quite a few more properties (e.g., positioning) and concepts (e.g., vertical responsive design flow) needed to make CSS fully direction agnostic. For more on this take a look at Elad Shechter's 2020 article Why CSS Logical Properties Aren’t Ready for Use!
Inline-size:
size of an element along the inline direction. (Inline-size is the writing-direction-agnostic version of width.)
Block-size:
size of an element along the block direction. (Block-size is the writing-direction-agnostic version of height.)
.direction-agnostic-zombie { inline-size: 5em; block-size: 2em;}
Night of the Living Tip:
To test this out, we’ll be using the writing-direction property. If the writing direction changes, then the inline and block directions should change as well.
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/001-direction-agnostic-zombies.html
Padding-inline-start:
size of the padding at the start of the inline direction. (This is the writing-direction-agnostic version of padding-left.)
Padding-inline-end:
size of the padding at the end of the inline direction. (This is the writing-direction-agnostic version of padding-right.)
Padding-block-start:
size of the padding at the start of the block direction. (This is the writing-direction-agnostic version of padding-top.)
Padding-block-end:
size of the padding at the end of the block direction. (This is the writing-direction-agnostic version of padding-bottom.)
.padding-direction-agnostic-zombies { padding-inline-start: 1em; padding-inline-end: 1em; padding-block-start: 0.5em; padding-block-end: 0.5em;}
Margin-inline-start:
size of the margin at the start of the inline direction (writing-direction-agnostic version of margin-left).
Margin-inline-end:
size of the margin at the end of the inline direction (writing-direction-agnostic version of margin-right).
Margin-block-start:
size of the at the start of the block direction (writing-direction-agnostic version of margin-top).
Margin-block-end:
size of the margin at the end of the block direction (writing-direction-agnostic version of margin-bottom).
.margin-direction-agnostic-zombies { margin-inline-start: 2em; margin-inline-end: 2em; margin-block-start: 1em; margin-block-end: 1em;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/002-padding-marginal-direction-agnostic-zombies.html
Border-inline-start:
border properties for the start of the inline direction (writingdirection-agnostic version of border-left).
Border-inline-end:
border properties for the end of the inline direction (writing-direction-agnostic version of border-right).
Border-block-start:
border properties for the start of the block direction (writing-direction-agnostic version of border-top).
Border-block-end:
border properties for the end of the block direction (writing-direction-agnostic version of border-bottom).
.bordering-direction-agnostic-zombies { border-inline-start: 5px solid #960B0B; border-inline-end: 5px solid blue; border-block-start: 5px solid green; border-block-end: 5px solid purple;}
Border-inline-start-width:
border size for the start of the inline direction (writing-direction-agnostic version of border-left-width).
Border-inline-end-width:
border size for the end of the inline direction (writing-direction-agnostic version of border-right-width).
Border-block-start-width:
border size for the start of the block direction (writing-direction-agnostic version of border-top-width).
Border-block-end-width:
border size for the end of the block direction (writing-direction-agnostic version of border-bottom-width).
Border-inline-start-style:
border style for the start of the inline direction (writing-direction-agnostic version of border-left-style).
Border-inline-end-style:
border style for the end of the inline direction (writing-direction-agnostic version of border-right-style).
Border-block-start-style:
border style for the start of the block direction (writing-direction-agnostic version of border-top-style).
Border-block-end-style:
border style for the end of the block direction (writing-direction-agnostic version of border-bottom-style).
Border-inline-start-color:
border color for the start of the inline direction (writing-direction-agnostic version of border-left-color).
Border-inline-end-color:
border color for the end of the inline direction (writing-direction-agnostic version of border-right-color).
Border-block-start-color:
border color for the start of the block direction (writing-direction-agnostic version of border-top-color).
Border-block-end-color
border color for the end of the block direction (writing-direction-agnostic version of border-bottom-color).
.bordering-direction-agnostic-zombies { /* Left Border */ border-inline-start-width: 5px; border-inline-start-style: solid; border-inline-start-color: #960B0B; /* Top Border */ border-inline-end-width: 5px; border-inline-end-style: solid; border-inline-end-color: blue; /* Right Border */ border-block-start-width: 5px; border-block-start-style: solid; border-block-start-color: green; /* Bottom Border */ border-block-end-width: 5px; border-block-end-style: solid; border-block-end-color: purple;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/003-borderline-direction-agnostic-zombies.html
Dividing the Horde (into Columns)
CSS columns are a simple way to add flexible text columns to your pages. This is useful when using responsive design because the width of your container element can change. Manual solutions require that the text be a certain length and stay in one element, artificially splitting the text into multiple tags, based on spacing rather than on content. CSS columns allow you to split content into multiple columns without worrying about where the column splits happen, making them more flexible and responsive.
Column-count:
sets the number of desired columns. While use cases will vary, I’d recommend sticking to a max of three columns unless you have a super-wide screen or a compelling reason. Shorter line lengths often make reading easier, but if you go too short, your eye jumps too much between lines, tiring the reader. Too many columns also increases visual distractions, making it more difficult for the reader to focus on the content.
.horde-layout-columns { column-count: 3;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/004-apocalyptic-columns.html
Column-gap:
sets the gap between columns. Be sure to include a large enough gap that readers aren’t distracted by the columns they aren’t reading. Distracted readers let the zombies win.
.horde-layout-columns { column-gap: 1em;}
Column-rule:
sets a style between columns in a way that is similar to a border. Like borders, it takes three values: a rule color, a rule style, and a rule width. You can set each of these individually with column-rule-color, column-rule-style, and column-rule-width. Available rule styles are the same as those available for borders. While you can go super fancy with these, minimal and clean is almost always the right choice. Super-fancy rules make content harder to read, and, of course, let the zombies win.
.horde-layout-columns { column-rule: #0DEAD0 3px solid;}
Column-span:
allows an element to span more than one column (though it’s either across all columns or none). This is useful for letting an image, heading, diagram, table, or zombie-defying figure tag span the columns, creating a new section and/or providing clarity of subject and visual weight to the image/heading/diagram/table/figure/thingy.
.undead-column-item { column-span: all;}
Night of the Living Tip:
There is one egregious issue when using column-span in Safari. It sometimes duplicates the content above and below the span, so a paragraph or heading that exists in the code after the spanning element may appear both above and below the spanning element. Honestly, sometimes I think the browser makers want the zombies to win!
Column-width:
sets the minimum width of multiple columns. The browser will try to fit as many columns as possible that are at least as wide as the set width and will distribute any additional space across the existing columns.
.horde-layout-columns { column-width: 5em;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/005-undead-span-width-gap-rules.html
Columns is the shortcut property for column-count and column-width.
.horde-layout-columns { columns: 3 400px;}
Orphans:
This property sets the minimum number of lines that need to be shown at the bottom of a page, region, or column. In other words, if you set it to two and only one line of the next paragraph will fit into the last part of that page, region, or column, then that line will be pushed to the next page, region, or column.
.horde-layout-columns { orphans: 2;}
Widows:
is similar to orphans, but from the other direction. If the last line (or lines) of a paragraph go on to the next page, region, or column, it’s called a widow. If the widow property is set to two, then there must be at least two lines transferred to the next page, region, or column.
.horde-layout-columns { widows: 2;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/007-zombie-orphans-and-undead-widows.html
Night of the Living Tip:
While both orphans and widows have wide support, neither works in Firefox, If you’re testing in Firefox, and they aren’t working, that’s why. That said, they shouldn’t cause any issues in Firefox if you include them.
Break-after:
instructs the browser whether to break a page, region, or column after an element. If you’re familiar with page-break-after, this has the same functionality, but they changed the name to generalize it since it works on more than just pages. Values:
Auto: allows—but doesn’t require—breaks after the element this appears on.
Avoid: avoids any break (column, page, or region) after the element.
Page: forces a page break after the element.
Avoid-page: avoids a page break after the element.
Break-before:
This is the same as break-after, but it works before the element in question. It takes the same values as break-after. Similar to the above this more generalized property name replaces page-break-before.
Break-inside:
is the same as break-after and break-before (and takes the same values, except for “page”), but it governs whether or not a page break can happen inside an element.
.i-break-for-zombies-before { break-before: page;}
.i-break-for-zombies-inside { break-inside: avoid;}
.i-break-for-zombies-after { break-after: avoid-page;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/008-break-those-zombies-down.html
Now let’s move on to Flexbox which is more complicated, but also more powerful.
Weird Flexbox, but Okay, Zombie
Flexbox does a superb job of centering multiple items and is also great at spacing items of different sizes. It’s not, however, very good at lining up rows and columns or keeping items in a structured grid format.
Columns, as we saw earlier, excel at making text columns, but can be unruly and difficult when laying out things other than text.
Flexbox came along before CSS grid and has better browser support (although CSS grid still has excellent browser support). Flexbox shines when doing single rows/columns or for multiple rows when fine-grained control isn’t required or with objects of varying size. If you need pixel-perfect control over where elements are, Flexbox will make you tear your hair out, but if your layout needs are more approximate or you have varying-sized items, Flexbox is an excellent weapon of choice.
Display: flex:
This goes on the container element, which is the parent element of the items you want to organize. If you don’t have a container element, you need to create one.
.undead-parent { display: flex;}
Flex-direction:
This sets how the elements are laid out, either as columns or rows, and sets the axes you’ll be using. Since it can change which direction acts as the block or inline direction, when working with Flexbox, it’s best to call them the main-axis and the cross-axis. When flex-direction defines rows, the main-axis/direction is the inline direction. But when you change the flex-direction to columns, you change the main-axis to the block direction, while elements and text within your flex items still follow the default inline and block directions.
Since this can get more confusing than a zombie at a midnight showing of Night of the Living Dead, we’ll stick with main-axis and cross-axis. Just remember that they can flip, depending on what you choose for the flex-direction. Also, for simplicity, we’ll assume that you’re using a left-to-right language such as English, making your inline direction left to right and your block direction up and down. If you’re using a different language or a different writing-direction, the directions will change.
Night of the Living Tip:
Switching things around on-screen (rows vs columns etc.) will not change the order in the source code; thus, screen readers and search engines will read things in the code order. If the order of items affects how the content is understood, it’s best to change the source code/content, not just the visual display.
.undead-parent { flex-direction: column;}
Column: displays items vertically, starting with the first element at the top.
Column-reverse: displays items vertically, starting with the first element at the bottom.
Row: displays items horizontally, starting with the first element at the left.
Row-reverse: displays items horizontally, starting with the first element at the right.
Flex-wrap:
controls whether all items appear in a single row or column or wrap to multiple rows.
.undead-parent { flex-wrap: wrap;}
Wrap: Flexed items wrap to multiple rows and or columns.
Nowrap: All items remain on one row or column, even if that squishes them (“squishes” being the technical term).
Wrap-reverse: Reverse the direction of how items wrap.
Flex-flow:
This is a shortcut property that combines flex-direction and flex-wrap.
.undead-parent { flex-flow: column wrap-reverse;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/009-weird-flexbox-but-okay-zombie.html
Justify-content:
determines how the content is distributed across the main-axis you’ve chosen (horizontal for rows, vertical for columns).
.undead-parent { justify-content: center;}
Center: puts the items in the center of the row or column.
Flex-start: bunches the items at the left or top.
Flex-end: bunches the items at the right or bottom.
Space-around: makes sure there’s equal space on the right and left (or top and bottom) of each item. It includes some space on the ends between the flexed item and the sides of the flex container.
Space-between: maximizes space between the items. It leaves no space between the items and the edges of the container.
Space-evenly: sets the same amount of space between items as there is between items and the container’s edges.
Stretch: stretches the rows/columns to fill the container. (This is the default.)
Align-items:
works in the direction perpendicular to justify-content, the cross-axis (i.e., it affects the vertical spacing of items in a row when flex-direction is rows and affects the horizontal spacing of items in a column when flex-direction is columns).
.undead-parent { align-items: center;}
Center: vertically centers the items in a row or horizontally centers the items in a column.
Flex-start: aligns the flexed items of a row toward the top or toward the left of a column.
Flex-end: aligns the flexed items of a row toward the bottom or toward the right of a column.
Stretch: stretches items to fill the container. (This is the default.)
Baseline: aligns the text baselines of items.
Align-content:
works just like justify-content but in the perpendicular direction, the cross-axis, meaning either the placement and spacing between and around rows or the placement and spacing between and around columns. Note: it has no effect when there’s only one row or column.
.undead-parent { align-content: center;}
Center: centers the rows vertically or the columns horizontally.
Flex-start: bunches rows at the top or columns at the left.
Flex-end: bunches rows at the bottom or columns at the right.
Space-around: maximizes the space at the top and bottom of rows or to the left and right of columns, including between flexed rows/columns and the edges of the container.
Space-between: maximizes the space between rows or columns.
Space-evenly: Sets the same amount of space between items as between items and the container’s edges.
Stretch: stretches the rows or columns to fill the whole container.
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/010-just-try-and-justify-the-apocalypse.html
Order:
used on individual flexed elements. It sets or changes the order of those items in the flexed layout. It’s important to know that if order has not been set, then order defaults to 0. The lowest order number appears in the left-most/top-most position, depending on flex-direction. If items have the same order numbers, they go in source order. Note: This does not change the source order and can thus hurt accessibility if reordering could cause confusion.
.zombie-item { order: 1;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/011-an-orderly-apocalypse.html
Flex-grow:
lets you set a growth factor that allows items to grow to fill the space (either horizontally or vertically, depending on flex direction). The growth factor is a positive, rational number and is not a direct multiplier for the width/height. Rather, when the flex algorithm looks at the remaining space available in a row or column, it calculates how to apportion space based on the flex-grow factors. A higher value means that that item is likely to get more space than those with a lower value. Default is 0, meaning the item won’t grow at all. Negative numbers are invalid.
.zombie-item { flex-grow: 1.5;}
Flex-shrink:
lets you set a shrink factor for when flex items are too wide or tall for their containers (depending on the flex direction that was set). Like the flex-grow factor, a higher value means that the item is more likely to shrink. The flex algorithm will see if it needs to slim some items to fit the available space and will take more space from elements with a higher flex-shrink. Default is 0, meaning no space will be taken from the item. Negative numbers are invalid.
.zombie-item { flex-shrink: 3.5;}
Flex-basis:
sets the basic size value (width or height, depending on flex-direction) of a flexed item and helps determine when, how. and if a flexed item grows or shrinks. This can be set with any dimensional unit (i.e., pixels, ems, percentage. etc.), but flex-basis also has keyword options: content and auto. There are a few more, but they aren’t widely supported yet. It defaults to auto.
Content: allows the flex-basis to be determined by the item's content. Due to a back and forth in the spec, the content keyword isn’t supported everywhere yet. However, we can produce the same results with flex-basis: auto plus a width or height (depending on flex-direction).
.zombie-item { flex-basis: 100px;}.zombie-item2 { flex-basis: content; flex-basis: auto 100px;}
Flex:
shorthand property for the flex-grow, flex-shrink, and flex-basis properties. It can be used with one, two, or three values.
One value: a unitless number will be assumed to be flex-grow, and a valid width value will be assumed to be flex-basis. If flex-shrink isn’t specified, it’s assumed to be 1.
.zombie-item { flex: 2;}
Two values: can be two unitless numbers. The first is flex-grow, and the second is flex-shrink. It could also be a unitless number and a width/height for a flex-grow and flex-basis.
.zombie-item { flex: 2 100px;}
Three values: the first is flex-grow, the second is flex-shrink, and the last is flex-basis.
.zombie-item { flex: 1.5 2 100px;}
You can also use some keywords: initial, auto, and none. The initial is equivalent to flex: 0 1 auto. Auto is equivalent to flex: 1 1 auto, and none equates to flex: 0 0 auto.
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/012-honey-i-shrunk-and-grew-the-zombies.html
Align-self:
allows you to override the align-items property on a particular item/element. Kind of like having one zombie in a horde going the opposite way of every other zombie.
.zombie-item { align-self: center;}
Center: centers the content item on the cross-axis.
Flex-start: aligns to the beginning edge of the flex box.
Flex-end: aligns to the end edge of the flex box.
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/013-align-yourself-with-the-human-resistance.html
CSS Gridiron Zombies
CSS grid approaches layout differently. It, as the name implies, allows you to lay things out in a grid. While Flexbox is loosey-goosey (zombly-wombly?) about where it places items and is rather flexible in its placement of those items (sometimes annoyingly so), grid allows you both more precise control over where and how an element will be displayed and the flexibility necessary to make responsive design easy. It is, by far, the most powerful layout weapon available for dispatching zombies, but with its increase in power comes an equal increase in complexity.
Fractioning Zombies: A Special Unit for Grid
The fr unit represents a fraction of the remaining space in a grid. Your layout may have leftover space for a variety of reasons. You might want a few columns that are fixed in size, and one that flexes with screen size or a row that flexes with the content that is put into it. You can also do things such as proportional widths—for example, having a column that’s three times the size of another column: 3fr to 1fr. The fr unit, in short, helps you knock out the horde of screen-size problems a responsive site runs into. It gives you the flexibility to have rigidly lined-up content whose layout doesn’t break at the first sign of an unusual screen size or an irregular length of content.
Display: grid:
like Flexbox, it starts with setting the display of the parent to grid.
.undead-parent { display: grid;}
Display: inline-grid:
You can also create an inline grid that works in almost the same way as grid except that the grid parent element stays inline like a phrase element.
Grid-template-columns:
This sets the size of the columns used in the grid. It can take many different dimensions and units.
.undead-parent { grid-template-columns: 300px 13em 1fr 2fr 30%;}
Grid-template-rows:
This sets the size of the rows used in the grid. It can take many different dimensions.
.undead-parent { grid-template-rows: 15em 200px 3fr 10% 2fr;}
Grid-template:
shortcut property that allows you to set grid-template-rows and grid-template-columns in one property. Rows come first, and you separate them from the columns with a forward slash /.
.undead-parent { grid-template: 15em 200px 3fr 10% 2fr / 300px 13em 1fr 2fr 30%;}
Column-gap:
sets the gap between two columns.
.undead-parent { column-gap: 1em;}
Row-gap:
sets the gap between two rows
.undead-parent { row-gap: 1.5em;}
Gap:
This is a shorthand property for setting the gap between columns and the gap between rows in one fell zombie-smashing swoop.
.undead-parent { grid-gap: 1em 1.5em;}
You can also use some functions and special keywords to create grid columns and rows. Note: Examples will show grid-template-columns, but these will work with grid-template-row as well.
Max-content:
seeks the maximum size that the column or row can use. It’s greedy and takes as much space as it can. For instance, if the content is text and no width/height constraints have been put on it by its parent element, it will be as wide as the entire length of text. It won’t wrap the text unless it has to.
.undead-parent { grid-template-columns: 1fr max-content 14em;}
Min-content:
seeks the minimum size a column or row can use without the element’s children overflowing. It takes only as much space as it needs to show off its content and won’t take a pixel more.
.undead-parent { grid-template-columns: 3em min-content 12em;}
Repeat():
allows you to repeat columns/rows in either a single column/row or a multi-column/row pattern. It’s like finding the zombie weapon that fits you best and using it again and again and again.
.undead-parent { grid-template-columns: repeat( 5, 1fr );}
Minmax():
takes two values: a minimum and maximum size that the column or row can be.
.undead-parent { grid-template-columns: 13em minmax(100px, 1fr) 1fr 1fr;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/015-mini-max-zombie-repeat.html
Placing Content in Your Post-apocalyptic Grid
Grid-column-start:
sets the column name or number where the element should start.
Grid-column-end:
sets the column name or number where the element should end.
Grid-row-start:
sets the row name or number where the element should start.
Grid-row-end:
sets the row name or number where the element should end.
.zombie-item { grid-column-start: 2;grid-column-end: 4; grid-row-start: 3;grid-row-end: 6;}
Grid-column:
shorthand property for setting the column start and end.
Grid-row:
shorthand property for setting the row start and end.
Note: add a slash between the start value and the end value.
.zombie-item { grid-column: 2 / 4;grid-row: 3 / 6;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/016-gridpocalypse-the-start-and-end.html
Grid-area:
tells an item where it should live visually in the grid. It’s a shortcut property for grid-row-start, grid-column-start, grid-row-end, and grid-column-end.
.zombie-item { grid-area: 3 / 2 / 6 / 4; /* The grid-area declaration above is equivalent to this grid-column/grid-row declaration */ grid-column: 2 / 4; grid-row: 3 / 6; /* And to this grid-column-start/grid-row-start/grid-column-end/grid-row-end declaration */ grid-column-start: 2; grid-row-start: 3; grid-column-end: 4; grid-row-end: 6;}
Rather than specifying an end column, you can also set how many rows or columns to spread across with the span keyword. The example below is equivalent to the one above.
.zombie-item { grid-area: 2 / 3 / span 2 / span 3;}
Last, you can use an area name (a section of the grid) to specify where the item should go.
.zombie-item { grid-area: zombie;}
Grid-template-areas:
Use this the property to create the areas, using a space-separated list of area names in columns, and rows are designated by quotation marks.
Night of the Living Tip:
The period below marks an “empty” area, but that doesn’t mean it will be unused. Once you place items in the areas, any leftover items will auto fill into whatever areas remain.
.undead-parent { grid-template-areas: "head head head head" "head head head head" "undead zombie zombie sidebar" "undead zombie zombie sidebar" "undead zombie zombie sidebar" ". foot foot sidebar"; }
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/017-zombie-area-offense.html
Grid-auto-rows:
gives you control over the rows the system creates automatically when you place an item outside the explicitly created rows or when there’s more content than what will fit in the explicitly created rows. Grid-auto-rows can take any of the size parameters you would use in an explicitly created row, including length, percentage, min-content/max-content, repeat(), minmax(), and fractions of horde.
Grid-auto-columns:
the same as grid-auto-rows, but for zombies…errr…I mean…columns.
Grid-auto-flow:
When you’ve finished placing all the items you want to place in your grid, you may have items left over whose exact placement isn’t as important. You can use different algorithms to auto place these items. Grid-auto-flow is how you tell the browser which algorithm to use.
Row: prioritizes rows, meaning it fills out a row, and then moves to the next column.
Column: prioritizes columns, meaning it fills out a column, and then moves to the next row.
Dense: prioritizes fit over order, meaning items can be placed out of order so that the grid can be as densely populated as possible.
Row dense: combines row priority and a dense packing algorithm.
Column dense: combines column priority and a dense packing algorithm.
Tip
Again, be careful that this doesn’t inhibit accessibility. A screen reader or keyboard user will move through the content in source order (how they exist in the file), and not how they appear on the screen.
Justify-content
and align-content:
work the same in grid as they do in flexbox.
Place-content:
a shortcut property for setting both align-content and justify-content. Align-content is the first value, followed by the justify-content value. It does not work in Edge yet.
.undead-parent { place-content: center space-evenly;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/019-justifying-a-zombies-place.html
Justify-items:
allows you to adjust the inline/horizontal spacing of elements within their columns. This is useful when you have items that are thinner than their columns.
Start: aligns the item with the start of the column. In left-to-right languages, that’s the left.
Flex-start: In grid, this is the same as start.
Self-start: functionally, equivalent to start in most cases.
Left: works like start, except it always goes left, even if the axis has been changed.
End: aligns the item with the end of the column. In left-to-right languages, that’s the right.
Flex-end: In grid, this is the same as end.
Self-end: functionally, equivalent to end in most cases.
Right: works like end, except it always goes right, even if the axis has been changed.
Center: centers the item within the column.
Stretch: stretches the item to fill the width of the column .
Safe: used only in combination with any of the above keywords (except stretch). It governs how an item that overflows its column is handled. When safe is used, any item that overflows its column is treated the same as start. In left-to-right languages, that means it’s aligned on the left side.
Unsafe: similar to safe. Unsafe's a modifier and governs overflowing items. Unsafe uses whatever was set on the item.
.undead-parent { justify-items: center;}
Align-items:
works the same as it does in flexbox.
.undead-parent { align-items: space-evenly;}
Place-items:
allows you to set align-items and justify-items in one handy property. Align-items is the first included value. Justify items is the second.
.undead-parent { place-items: space-evenly center;}
Try it Out:
Codepen Demo:
HTML Demo: https://undead.institute/files/decking/020-just-try-and-justify-yourself-apocalypse.html
Justify-self:
lets you set how an item is aligned within its context—its column. The properties we’ve discussed are like genetic zombie contagions—set on the parent—while this and the other “self” properties are set within the item itself.
Night of the Living Tip:
This property is ignored in Flexbox and table layouts, but it has some use within block-level elements.
Start: aligns the item with the start of the column it is in. In left-to-right languages, that’s the left.
End: Aligns the item with the end of the column it is in. In left-to-right languages, that’s the right.
Center: centers the item within the column.
Stretch: stretches the item to fill the width of the column.
.zombie-item { justify-self: stretch;}
Align-self:
same as in flexbox and similar to justify-self (except it works on the opposite axis from justify-self).
Start: aligns the item with the start of the row it is in. In left-to-right languages, that’s the top.
End: aligns the item with the end of the row it is in. In left-to-right languages, that’s the bottom.
Center: centers the item within the row.
Stretch: stretches the item to fill the height of the row.
.zombie-item { align-self: start;}
Place-self:
shorthand property that allows you to set both align-self and justify-self in one property. Align-self’s value comes first.
.zombie-item { place-self: start stretch;}
Try it Out:
HTML Demo: https://undead.institute/files/decking/021-dont-you-self-justify-zombie.html
Finding the Right Zombie Thrashing Tool
Tables
Complexity level:
low to high, depending on implementation.
Great at:
Rigid and even complex layouts if you can get away with a single size screen and can build for that (which is unlikely in today’s multi-screen environment).
Terrible at:
anything responsive (also, there is no separation of content and visual structure).
Positioning
Complexity level:
low.
Great at:
small number of design/content elements placed in odd locations or only slightly offset from regular flow.
Terrible at:
any complex layout.
Floating
Complexity level:
low.
Great at:
allowing content to wrap around an image or other visual element; two columns or even three columns as long as the content in each column is separate from the others.
Terrible at:
any complex layout.
Columns:
Complexity level:
medium-low.
Great at:
separating large swaths of text into connected columns.
Terrible at:
complex layouts that contain more than text.
Flexbox
Complexity level:
medium.
Great at:
lining items up either horizontally or vertically; being flexible to multiple screen sizes.
Terrible at:
lining things up in more than one direction at a time; keeping things aligned.
Grid
Complexity level:
high.
Great at:
complex layouts’ keeping things aligned in two directions at the same time.
Terrible at:
minor layouts (too complex for quick needs; shines at page wide/section wide layout).
Laying It All Out on the Zombie Deck
Lay out the following HTML in three columns using the layout methods you've learned. You must use at least floats, columns, flexbox, and grid. Try to modify the HTML as little as possible
Codepen
Starter Codepen:
Starter HTML File: https://undead.institute/files/decking/022-lay-it-all-out.html
Example Answers:
These are example answers and may or may not look like what you came up with. Don't worry if your answer looks different or does things differently. As long as it does what you set out to do, you're the head of the zombie decking class.
Float:
Column:
Flexbox:
Grid:
Got Questions?
Join the Undead Institute Facebook group and get answers. https://www.facebook.com/groups/490540551375786/
You Know what else kills Zombies?
Honest reviews. Please consider leaving one to help the fight against the apocalypse.
I’d also love to see where and how you’re reading or using the book. Twit me a pic at @storykaboom and/or use the hashtag #GetBraaains