Good day, friends!
Here's a complete visual cheat-sheet guide to all the properties of Flexbox and Grid CSS Modules.
Key sources: A Complete Guide to Flexbox , A Complete Guide to Grid .
At the end of the article, you will find a short tutorial on creating a Flexbox simulator.
Without further preface.
Flexbox (Flex, hereinafter referred to as Flex)
Terminology
Flex is not a separate property, but a whole module that includes a set of properties. Some of these properties are added to the container (the parent element, known as the flex container), others to the child elements (known as flex items, hereinafter - elements)).
The "regular" layout is based on flow of block and inline elements, while the flex layout is based on flex-flow directions. Take a look at this image from the spec to showcase the key ideas behind flex layout.
Elements are positioned along the main axis (from main-start to main-end) or along the cross axis (from cross-start to cross-end).
- — , , . ; «flex-direction» (, . )
- main-start | main-end — main-start main-end
- (main size) — (main dimension),
- — , .
- cross-start | cross-end — , cross-end cross-start
- (cross size) —
-
display
This property defines a flex container; block or line depending on the assigned value. It includes the "flex context" for all direct children of the container.
.container {
display: flex; /* inline-flex */
}
Note that the CSS column properties in the container do not work.
flex-direction
This property defines the main axis, the direction along which items are placed in the container. Flex itself (without the wrappers extending its functionality) implements the concept of a unidirectional layout. Therefore, elements are placed either in horizontal lines or in vertical columns.
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
- row (default): items are laid out from left to right in ltr or right to left in rtl
- row-reverse: reverse row order of items - right to left in ltr or left to right in rtl
- column: similar to row, but from top to bottom
- column-reverse: similar to row-reverse, but from bottom to top
flex-wrap (wrap, transition, split)
By default, all items are placed on one line. With this property, you can let the elements move to the next line as needed.
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
- nowrap (default): all items are on one line
- wrap: elements can span multiple lines from top to bottom
- wrap-reverse: elements can span multiple lines from bottom to top
flex-flow (flow)
This property is shorthand for flex-direction and flex-wrap, which define the main and cross axes of the container. The default is row nowrap.
.container {
flex-flow: column wrap;
}
justify-content (align content on one line)
This property determines the alignment of elements along the main axis. It allows you to distribute the free space left by unused elements with a fixed size or flex elements that have reached their maximum size. It also allows you to control the alignment of overflowing items.
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}
- flex-start (default): items are moved to the start of the container along the main axis
- flex-end: items are pushed to the end of the container
- start: the elements are moved to the beginning of the container, determined by the value of the "writing-mode" property
- end: elements are shifted to the end of the container, determined by the value of the "writing-mode" property
- left: items are pushed to the left edge of the container; without flex-direction, the behavior is similar to start
- right: items are squeezed to the right edge of the container; without flex-direction, the behavior is the same as start
- center:
- space-between: , , — ,
- space-around: . , ; , . , ,
- space-evenly: ,
Note that support for the listed properties differs across browsers. The safest are flex-start, flex-end and center.
As for the additional keywords "safe" and "unsafe", using safe allows you to avoid drawing elements outside of the page, regardless of positioning, which, in turn, eliminates the possibility of scrolling.
align-items (align items)
This property determines how elements are positioned along the transverse axis. It can be compared to justify-content for the transverse axis (perpendicular to the main axis).
.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}
- stretch (default): elements stretch to fill the entire container (depends on their min-width / max-width)
- flex-start / start / self-start: items are offset to the start of the cross axis. The differences between the above properties are not significant and depend on flex-direction or writing-mode
- flex-end / end / self-end: items are offset to the end of the cross axis. The differences between the above properties are not significant and depend on flex-direction or writing-mode
- center: elements are centered
- baseline: elements are aligned along their baseline
The modifier keywords "safe" and "unsafe" can be used as additional settings to avoid alignment of elements that would make the content inaccessible (inaccessible, outside the page).
align-content (align content across multiple lines)
This property determines the alignment of the container lines when there is free space along the transverse axis. It is similar to justify-content, which distributes space between individual elements along the main axis.
Note that the property in question only applies to container content spanning multiple lines when the flex-wrap property is set to wrap or wrap-reverse. For a one-liner (when the "flex-wrap" property is set to "no-wrap") applying align-content will have no effect.
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}
- normal (default): lines are in normal positions
- flex-start / start: lines are moved to the beginning of the container. flex-start depends on flex-direction and start depends on writing-mode
- flex-end / end: lines are pushed to the end of the container. flex-end depends on flex-direction and end depends on writing-mode
- center: lines are centered
- space-between: lines are positioned so that the first line is at the beginning of the container, the last at the end, and the remaining lines are evenly spaced
- space-around: lines are spaced with equal space between them
- space-evenly: lines are spaced with equal space around each of them
- stretch: lines stretch to fill all available space
The modifier keywords "safe" and "unsafe" can be used as additional settings to avoid alignment of elements that would make the content inaccessible (inaccessible, outside the page).
Flex element properties
order (order)
By default, elements are arranged in the container in the order in which they are listed in the markup. This property allows you to control this.
.item {
order: 5; /* 0 */
}
flex-grow (growth, expansion)
This property determines the ability of an element to expand when needed. It takes an integer value that acts as a proportion. Proportion determines how much of the available space in the container an item can occupy.
If all items have a flex-grow of 1, then the available space is evenly distributed between them. If one of the items has a flex-grow of 2, that item will take up double the space of the other items (or at least try to do so).
.item {
flex-grow: 4; /* 0 */
}
Negative values are not valid.
flex-shrink (shrink, shrink)
This property determines the ability of an element to compress when needed.
.item {
flex-shrink: 3; /* 1 */
}
Negative values are not valid.
flex-basis
This property defines the default size of the element before allocating the remaining space. This size can be a length (for example, 20%, 5rem, etc.) or a keyword. The auto keyword means using the value of the element's "width" or "height" property (previously, main-size was used instead of auto). The "content" keyword means accounting for the content of the element. The keyword mentioned is not well supported yet, so it is difficult to tell the difference between min-content, max-content and fit-content.
.item {
flex-basis: | auto; /* auto */
}
If the value of this property is 0, the space surrounding the element is not taken into account. If the value is "auto", the available space is allocated according to the value of the "flex-grow" property.
flex
This property is shorthand for flex-grow, flex-shrink, and flex-basis. The second and third parameters (flex-shrink and flex-basis) are optional. The default is 0 1 auto, and auto can be omitted.
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
It is recommended that you use this shorthand instead of defining each property so that property values are automatically determined in the correct order.
align-self (single element alignment)
This property allows you to overwrite the default or align-self alignment of an individual element.
See align-items explanation for available values.
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
Note that float, clear, and vertical-align have no effect on a flex element.
Examples of
Let's start with a very simple example - solving the problem of aligning an element to the center.
.parent {
display: flex;
height: 300px; /* */
}
.child {
width: 100px; /* */
height: 100px; /* */
margin: auto; /* ! */
}
This works thanks to the fact that the "margin" property set to "auto" consumes all the available space of the flex container. Therefore, setting the value of the vertical margins to auto results in perfect centering of the element on both axes.
Now let's try using more properties. We have 6 fixed-size elements that can resize depending on the screen width without involving media queries. We want the available space of the main axis to be evenly distributed among the elements.
.flex-container {
/* - */
display: flex;
/* ,
* :
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* , , */
justify-content: space-around;
}
Done. It remains to style a little:
Let's try something else. Suppose we have a right-aligned navigation menu in the header of our site, and we want it to be centered on medium screens and lined up in one column on small screens. Easy peasy.
/* */
.navigation {
display: flex;
flex-flow: row wrap;
/* */
justify-content: flex-end;
}
/* */
@media (max-width: 800px) {
.navigation {
/* */
justify-content: space-around;
}
}
/* */
@media (max-width: 500px) {
.navigation {
/* () () */
flex-direction: column;
}
}
Let's experiment with the flexibility of the elements. How about creating a mobile-first three-column layout with a full-size header and footer that doesn't depend on the order of the elements in the markup.
.wrapper {
display: flex;
flex-flow: row wrap;
}
/* flex-basis 100% */
.wrapper > * {
flex: 1 100%;
}
/*
* 1. header
* 2. article
* 3. aside 1
* 4. aside 2
* 5. footer
*/
/* */
@media all and (min-width: 600px) {
/* */
.aside { flex: 1 auto; }
}
/* */
@media all and (min-width: 800px) {
/* main
* main 2 ,
*/
.main { flex: 2 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}
Useful Resources
Support
Grid (hereinafter referred to as Grid or Grid)
CSS Grid Layout is by far the most powerful page layout tool. It is a bi-directional system. This means that it can work with both rows and columns, unlike Flex, which can only work with rows. Grid includes properties of a parent element (Grid Container, hereinafter referred to as a container) and properties of child elements (Grid Elements, hereinafter referred to as elements).
Terminology
Grid Container (hereinafter referred to as a container)
An element that is assigned a "display" property with a value of "grid" becomes a grid container. This container is the direct ancestor of all grid items. In the following example, a div with class "container" is a grid container.
<div class="container">
<div class="item item-1"> </div>
<div class="item item-2"> </div>
<div class="item item-3"> </div>
</div>
Grid Line (hereinafter referred to as a line)
The dividing line that forms the structure of the Grid. It can be vertical or horizontal and denotes the border of a row or column. The yellow line in the image below is an example of a vertical grid line (column grid line).
Grid Track (hereinafter referred to as track or track)
The space between two adjacent lines. You can think of tracks as rows or columns of the Grid. Here is an example of a track between the second and third lines.
Grid Area (hereinafter referred to as the area)
The total space between the four lines. An area can span any number of grid cells. Here is an example of the area between horizontal lines 1 and 3 and vertical lines 1 and 3.
Grid Element (hereinafter referred to as the element)
Child (direct descendant) of the container. In the following example, items with class "item" are Grid items, but items with class "sub-item" are not.
<div class="container">
<div class="item"> </div>
<div class="item">
<p class="sub-item"> </p>
</div>
<div class="item"> </div>
</div>
Grid cell (hereinafter referred to as a cell)
The space between two adjacent horizontal and vertical lines. It is the basic unit of the Grid. Here is an example of a cell between horizontal lines 1 and 2 and vertical lines 2 and 3.
Example
Flexible-width columns that automatically resize based on screen width without media queries.
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* min() */
/* grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); */
grid-gap: 1rem;
/* , */
/* gap: 1rem */
}
Grid container properties
display
This property makes the element a grid container and sets the grid context for its content.
.container {
display: grid | inline-grid;
}
- grid - block Grid
- inline-grid - inline Grid
Note that the ability to create nested Grids has been moved to the CSS Grid Level 2 specification .
grid-template-columns, grid-template-rows
These properties define the columns and rows of the Space-separated Grid values. Values represent the size of the track, and spaces represent the line.
.container {
grid-template-columns: ... | ...;
grid-template-rows: ... | ...;
}
- <track-size> - length, percentage or fractions of the free space of the Grid (using the "fr" unit)
- <line-name> - arbitrary name
When you leave white space between the track values, the lines are automatically assigned positive and negative numbers:
.container {
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}
You can explicitly specify line names. Note the square brackets:
.container {
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}
Lines can have several names. Here, for example, the second line has two names:
.container {
grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}
If the definition contains repeated fragments, you can use the "repeat" statement to shorten:
.container {
grid-template-columns: repeat(3, 20px [col-start]);
}
Which is equivalent to the following:
.container {
grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start];
}
If several lines have the same name, you can use the line name and the number of such lines.
.item {
grid-column-start: col-start 2;
}
The "fr" unit allows you to set the track size as a fraction of the container's free space. In the example below, each element is one-third the width of the container:
.container {
grid-template-columns: 1fr 1fr 1fr;
}
Free space is calculated after subtraction of fixed size elements. In the following example, the space available for allocation using the "fr" unit does not include 50px:
.container {
grid-template-columns: 1fr 50px 1fr 1fr;
}
grid-template-areas
This property defines the Grid template using the area names defined in the "grid-area" properties. Repeating area names causes the content to expand by the specified number of cells. A dot means an empty cell. This syntax allows you to visualize the structure of the Grid.
.container {
grid-template-areas:
" | . | none | ..."
"...";
}
- <grid-area-name> - area name
- ... - empty cell
- none - no area
Example:
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}
.container {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: auto;
grid-template-areas:
"header header header header"
"main main . sidebar"
"footer footer footer footer";
}
This code creates a Grid that is four columns wide and three lines high. The first (top) line is completely occupied by the header. The middle row consists of two "main" areas, one empty cell, and one "sidebar" area. The last line is the basement.
Each line in the definition must have the same number of columns.
Any number of dots can be used to represent an empty cell. As long as there is no space between the dots, they are an indicator of an empty cell.
Note that this syntax is used to represent areas, not lines. Using this syntax, the line on each side of the region is named automatically. If the region name is "foo", then the first (first) lines (line and column) of the region will be "foo-start", and the last - "foo-end". This means that some lines can have multiple names, as in the above example, where the top left line has three names: header-start, main-start, and footer-start.
grid-template
This property is shorthand for grid-template-rows, grid-template-columns, and grid-template-areas.
.container {
grid-template: none | <grid-template-rows> / <grid-template-columns>;
}
- none - resets the values of all three properties to default
- <grid-template-rows> / <grid-template-columns> - sets the "grid-template-rows" and "grid-template-columns" properties to the corresponding values, and the "grid-template-areas" property to "none"
You can use a more complex, but at the same time more convenient syntax to define the values of all three properties:
.container {
grid-template:
[row1-start] "header header header" 25px [row1-end]
[row2-start] "footer footer footer" 25px [row2-end]
/ auto 50px auto;
}
This is equivalent to the following:
.container {
grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
grid-template-areas:
"header header header"
"footer footer footer";
}
Since grid-template does not reset the implicit Grid properties (such as grid-auto-columns, grid-auto-rows, and grid-auto-flow), which is required in most cases, it is recommended to use the "grid" property instead.
column-gap, row-gap, grid-column-gap, grid-row-gap
These properties determine the size of the lines. In other words, they determine the amount of indentation between columns / lines.
.container {
/* */
column-gap: <line-size>;
row-gap: <line-size>;
/* */
grid-column-gap: <line-size>;
grid-row-gap: <line-size>;
}
- <line-size> - amount of indents
Example:
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
column-gap: 10px;
row-gap: 15px;
}
Padding is only created between columns / rows, not along the edges of the Grid.
Note that the "grid-column-gap" and "grid-row-gap" properties have now been renamed to "column-gap" and "row-gap".
gap, grid-gap
This property is shorthand for row-gap and column-gap.
.container {
/* */
gap: <grid-row-gap> <grid-column-gap>;
/* */
grid-gap: <grid-row-gap> <grid-column-gap>;
}
- <grid-row-gap> <grid-column-gap> - padding sizes
Example:
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
gap: 15px 10px;
}
If the value of the "row-gap" property is not set, it is set to the value of the "column-gap" property.
Note that the "grid-gap" property has now been renamed to "gap".
justify-items
This property determines the alignment of items in cells along the line (horizontal) axis (as opposed to the "align-items" property, which determines the alignment along the block (column, vertical) axis). The value of this property applies to all elements in the container.
.container {
justify-items: start | end | center | stretch;
}
- start - elements are shifted to the beginning of their cells (left border)
- end - elements are shifted to the end of the cells (right border)
- center - elements are centered
- stretch - elements fill the full width of the cells
.container {
justify-items: start;
}
.container {
justify-items: end;
}
.container {
justify-items: center;
}
.container {
justify-items: stretch;
}
The position of an individual item along the row axis of the cell is controlled by the "justify-self" property.
align-items
This property determines the alignment of items in cells along the box (column, vertical) axis (as opposed to the "justify-items" property, which determines the alignment along the row (horizontal) axis). The value of this property applies to all elements in the container.
.container {
align-items: start | end | center | stretch;
}
- start - elements are shifted to the beginning of their cells (top border)
- end - elements are shifted to the end of cells (bottom border)
- center - items are centered
- stretch - elements fill the full height of the cells
.container {
align-items: start;
}
.container {
align-items: end;
}
.container {
align-items: center;
}
.container {
align-items: stretch;
}
The position of an individual element along the cell column axis is controlled by the "align-self" property.
place-items
This property is shorthand for align-items and justify-items.
.container {
place-items: <align-items> <justify-items>;
}
- <align-items> <justify-items> is the first value for align-items, the second for justify-items. If there is no second value, the first value is assigned to both properties.
Example:
.container {
place-items: center start;
}
Items are centered along the column axis and at the origin along the line axis.
justify-content (column alignment)
Sometimes the total width of the Grid elements (its columns) is less than the width of the container. This can happen when defining fixed size elements (using px, for example). In this case, we can define the order of the Grid columns in the container. This property determines the alignment of the Grid along the line axis - the alignment of the columns (as opposed to the "align-content" property, which determines the alignment of the Grid along the box (column) axis - the alignment of rows).
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
- start - shifts the Grid to the beginning of the container (left border)
- end - moves the Grid to the end of the container (right border)
- center - The grid is centered
- stretch — ,
- space-around — ,
- space-between — , — ,
- space-evenly — ,
.container {
justify-content: start;
}
.container {
justify-content: end;
}
.container {
justify-content: center;
}
.container {
justify-content: stretch;
}
.container {
justify-content: space-around;
}
.container {
justify-content: space-between;
}
.container {
justify-content: space-evenly;
}
align-content ( )
Sometimes the total height of the Grid elements (its rows) is less than the height of the container. This can happen when defining fixed size elements (using px, for example). In this case, we can determine the order of the Grid rows in the container. This property defines the alignment of the Grid along the box (column) axis - the alignment of rows (as opposed to the "justify-content" property, which determines the alignment of the Grid along the inline axis - the alignment of columns).
.container {
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
- start - shifts the Grid to the beginning of the container (top border)
- end - shifts the Grid to the end of the container (bottom border)
- center - The grid is centered
- stretch - the lines are stretched so that the Grid takes up the entire height of the container
- space-around - equal space between lines, and half of that space around the edges of the container
- space-between - the first line is shifted to the beginning of the container, the last - to the end, free space is evenly distributed between the rest of the lines
- space-evenly - equal space both between lines and at the edges of the container
.container {
align-content: start;
}
.container {
align-content: end;
}
.container {
align-content: center;
}
.container {
align-content: stretch;
}
.container {
align-content: space-around;
}
.container {
align-content: space-between;
}
.container {
align-content: space-evenly;
}
place-content
This property is shorthand for align-content and justify-content.
.container {
place-content: <align-content> <justify-content>;
}
- <align-content> <justify-content> is the first value for align-content, the second is for justify-content. If there is no second value, the first value is assigned to both properties.
Example:
.container {
place-content: center start;
}
Rows are centered in the container, columns are at the beginning.
grid-auto-columns, grid-auto-rows (size of implicit tracks)
These properties determine the size of automatically generated tracks (implicit tracks). Implicit tracks are created when there are more items than cells in the Grid, or when an item is placed outside of the Grid.
.container {
grid-auto-columns: <track-size> ...;
grid-auto-rows: <track-size> ...;
}
- <track-size> - length, percentage or fractions of the free space of the Grid (using the "fr" unit)
Example:
.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px;
}
This creates a 2x2 Grid.
Let's say we use the "grid-column" and "grid-row" properties to position the items as follows:
.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.item-b {
grid-column: 5 / 6;
grid-row: 2 / 3;
}
The element with class "item-b" starts with vertical line 5 and ends with vertical line 6, but we haven't defined those lines. Since we are referencing non-existent lines, implicit zero-width tracks are created to fill in the indents. We can use the "grid-auto-columns" property to define the width of the implicit tracks:
.container {
grid-auto-columns: 60px;
}
grid-auto-flow
The auto-placement algorithm can be used to position items outside the Grid. The property in question determines how this algorithm should work.
.container {
grid-auto-flow: row | column | row dense | column dense;
}
- row (default) - the algorithm fills the current row to the limit and, if necessary, when the width of the current row is not enough, creates a new row
- column - the algorithm fills the current column to the limit and, if necessary, when the height of the current column is insufficient, creates a new column
- dense - intelligent filling of the Grid when there are elements of different sizes
Note that dense changes the visual order of the elements, which can have a negative impact on accessibility.
Let's assume we have the following markup:
<section class="container">
<div class="item-a">item-a</div>
<div class="item-b">item-b</div>
<div class="item-c">item-c</div>
<div class="item-d">item-d</div>
<div class="item-e">item-e</div>
</section>
We define a Grid with five columns and two rows and set the "grid-auto-flow" property to "row" (which is the default):
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: row;
}
When placing items in the Grid, we only place two items:
.item-a {
grid-column: 1;
grid-row: 1 / 3;
}
.item-e {
grid-column: 5;
grid-row: 1 / 3;
}
Since the value of the "grid-auto-flow" property is "row", our Grid looks like the image below. Pay attention to the arrangement of elements with classes "item-b", "item-c" and "item-d" (preference is given to rows):
If you change the value of the property "grid-auto-flow" to "column", the Grid will look like this way (preference is given to columns):
grid
This property is shorthand for grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, and grid-auto-flow (note that one declaration may contain only "explicit" or "implicit" properties).
- none - all properties accept default values
- <grid-template> - similar to grid-template shorthand
- <grid-template-rows> / [auto-flow && dense?] <grid-auto-columns>? - defines the value for grid-template-rows. If the keyword "auto-flow" is to the right of the slash, the value of the "grid-auto-flow" property becomes "column". If the keyword "dense" is specified in addition to auto-flow, the auto-nesting algorithm packs the items accordingly. If the value for the "grid-auto-columns" property is omitted, its value becomes "auto"
- [auto-flow && dense?] <grid-auto-rows>? / <grid-template-columns> - Defines the value for grid-template-columns. If the keyword "auto-flow" is to the left of the slash, the value of the "grid-auto-flow" property becomes "row". If the keyword "dense" is specified in addition to auto-flow, the auto-nesting algorithm packs the items accordingly. If the value for the "grid-auto-rows" property is omitted, its value becomes "auto"
The following two blocks of code are equivalent:
.container {
grid: 100px 300px / 3fr 1fr;
}
.container {
grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
}
The following two blocks of code are equivalent:
.container {
grid: auto-flow / 200px 1fr;
}
.container {
grid-auto-flow: row;
grid-template-columns: 200px 1fr;
}
The following two blocks of code are equivalent:
.container {
grid: auto-flow dense 100px / 1fr 2fr;
}
.container {
grid-auto-flow: row dense;
grid-auto-rows: 100px;
grid-template-columns: 1fr 2fr;
}
And the following two blocks of code are also equivalent:
.container {
grid: 100px 300px / auto-flow 200px;
}
.container {
grid-template-rows: 100px 300px;
grid-auto-flow: column;
grid-auto-columns: 200px;
}
In this case, we can use a more complex, but at the same time more convenient syntax for simultaneously defining the "grid-template-areas", "grid-template-rows" and "grid-template-columns" properties and setting other properties to default values ... What you need to do for this is to define the names of the lines and the sizes of the tracks with the corresponding areas on one line. This is easier to demonstrate with an example:
.container {
grid: [row1-start] "header header header" 1fr [row1-end]
[row2-start] "footer footer footer" 25px [row2-end]
/ auto 50px auto;
}
This is equivalent to the following:
.container {
grid-template-areas:
"header header header"
"footer footer footer";
grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
}
Grid item properties
Note that the properties float, display: inline-block, display: table-cell, vertical-align, and column- * applied to a grid element have no effect.
grid-column-start, grid-column-end, grid-row-start, grid-row-end
These properties determine the position of an element in the Grid by snapping to specific lines. grid-column-start / grid-row-start are the start lines of the item and grid-column-end / grid-row-end are the end lines.
.item {
grid-column-start: <number> | <name> | span <number> | span <name> | auto;
grid-column-end: <number> | <name> | span <number> | span <name> | auto;
grid-row-start: <number> | <name> | span <number> | span <name> | auto;
grid-row-end: <number> | <name> | span <number> | span <name> | auto;
}
- <line> - can be a number (snapping to the line number) or name (snapping to the line name)
- span <number> - the element will be stretched for the specified number of tracks
- span <name> - the element will stretch until it reaches the line with the specified name
- auto - auto layout, auto expand or default one column stretch
.item-a {
grid-column-start: 2;
grid-column-end: five;
grid-row-start: row1-start;
grid-row-end: 3;
}
.item-b {
grid-column-start: 1;
grid-column-end: span col4-start;
grid-row-start: 2;
grid-row-end: span 2;
}
If no grid-column-end / grid-row-end property values are specified, the item will occupy 1 track by default.
Elements can overlap each other. You can use the z-index property to control the stacking order of elements.
grid-column, grid-row
These properties are shorthand for grid-column-start + grid-column-end and grid-row-start + grid-row-end, respectively.
.item {
grid-column: <start-line> / <end-line> | <start-line> / span <value>;
grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}
- <start-line> / <end-line> - the values are the same as the original properties, including the span
Example:
.item-c {
grid-column: 3 / span 2;
grid-row: third-line / 4;
}
If no end line is specified, the element will default to 1 track.
grid-area
This property defines the name of the element, which is used as the value in the grid-template-areas property. grid-area can also be used as shorthand for grid-row-start + grid-column-start + grid-row-end + grid-column-end.
.item {
grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
- <name> - arbitrary name of the element
- <row-start> / <column-start> / <row-end> / <column-end> - can be numbers or line names
Naming an element:
.item-d {
grid-area: header;
}
Shorthand for grid-row-start + grid-column-start + grid-row-end + grid-column-end:
.item-d {
grid-area: 1 / col4-start / last-line / 6;
}
justify-self
This property specifies the alignment of an element in a cell along the row axis (as opposed to the align-self property, which specifies alignment along the box (column) axis). This property applies to an element within a single cell.
.item {
justify-self: start | end | center | stretch;
}
- start - the element is shifted to the beginning of the cell (left border)
- end - the element is shifted to the end of the cell (right border)
- center - the element is centered
- stretch - the element fills the entire width of the cell
.item-a {
justify-self: start;
}
.item-a {
justify-self: end;
}
.item-a {
justify-self: center;
}
.item-a {
justify-self: stretch;
}
The justify-items property is used to control the alignment of all Grid items along the line axis.
align-self
This property determines the alignment of an item in a cell along the box (column) axis (as opposed to the justify-self property, which determines the alignment along the row axis). This property applies to an element within a single cell.
.item {
align-self: start | end | center | stretch;
}
- start - the element is shifted to the beginning of the cell (top border)
- end - the element is shifted to the end of the cell (bottom border)
- center - the element is centered
- stretch - the element fills the entire cell height
.item-a {
align-self: start;
}
.item-a {
align-self: end;
}
.item-a {
align-self: center;
}
.item-a {
align-self: stretch;
}
The align-items property is used to control the alignment of all Grid items along the block (column) axis.
place-self
This property is shorthand for align-self and justify-self.
- auto - default value
- <align-self> / <justify-self> is the first value for align-self, the second for justify-self. If the second value is omitted, the first value is applied to both properties
.item-a {
place-self: center;
}
.item-a {
place-self: center stretch;
}
- , px, rem, % .., , min-content, max-content, auto , , — (fr). grid-template-columns: 200px 1fr 2fr min-content
- , . , , 1fr, 200px: grid-template-columns: 1fr minmax(200px, 1fr)
- repeat() : grid-template-columns: repeat(10, 1fr) ( , 1fr)
- The combination of these features allows you to achieve incredible layout flexibility, for example: grid-template-columns: repeat (auto-fill, minmax (200px, 1fr)) (from the example at the beginning of the Grid section)
Useful Resources
Support
Tutorial
In this tutorial, we will create a simple trainer for basic Flexbox properties.
Markup
<main>
<div id="controls">
<div id="buttons">
<button data-btn="addBtn">Add Item</button>
<button data-btn="removeBtn">Remove Item</button>
</div>
<fieldset id="flexContainerProps">
<legend>Flex Container Props</legend>
<label for="flexDirection">flex-direction</label>
<select id="flexDirection">
<option value="row" selected>row</option>
<option value="row-reverse">row-reverse</option>
<option value="column">column</option>
<option value="column-reverse">column-reverse</option>
</select>
<label for="flexWrap">flex-wrap</label>
<select id="flexWrap">
<option value="nowrap">nowrap</option>
<option value="wrap" selected>wrap</option>
<option value="wrap-reverse">wrap-reverse</option>
</select>
<label for="justifyContent">justify-content</label>
<select id="justifyContent">
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center" selected>center</option>
<option value="space-between">space-between</option>
<option value="space-around">space-around</option>
<option value="space-evenly">space-evenly</option>
</select>
<label for="alignItems">align-items</label>
<select id="alignItems">
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center" selected>center</option>
<option value="stretch">stretch</option>
<option value="baseline">baseline</option>
</select>
<label for="alignContent">align-content</label>
<select id="alignContent">
<option value="flex-start" selected>flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="stretch">stretch</option>
<option value="space-between">space-between</option>
<option value="space-around">space-around</option>
<option value="space-evenly">space-evenly</option>
</select>
</fieldset>
<fieldset id="flexItemProps">
<legend>Flex Item Props</legend>
<label for="order">order</label>
<input
id="order"
type="number"
min="-5"
max="5"
step="1"
value="0"
/>
<label for="flexGrow">flex-grow</label>
<input
id="flexGrow"
type="number"
min="0"
max="5"
step="1"
value="0"
/>
<label for="flexShrink">flex-shrink</label>
<input
id="flexShrink"
type="number"
min="1"
max="6"
step="1"
value="1"
/>
<label for="alignSelf">align-self</label>
<select id="alignSelf">
<option value="auto" selected>auto</option>
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="stretch">stretch</option>
<option value="baseline">baseline</option>
</select>
</fieldset>
</div>
<div id="flexContainer">
<div class="flex-item selected">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
</div>
</main>
Here we have a flexContainer with six flex-items and a controls to control toggling the properties of the flexContainerProps and selected flexItemProps. Also in the second container, you have two buttons: one for adding an element to the flex container (addBtn), the other for removing the last flex element (removeBtn).
Styles
main {
display: flex;
justify-content: center;
align-items: center;
}
#controls {
margin-right: 0.4rem;
}
#buttons {
margin: 0.4rem;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
button {
margin: 0.2rem;
}
label {
display: block;
margin: 0.4rem;
}
select {
width: 100%;
}
#flexContainer {
width: 600px;
height: 600px;
border: 1px dashed #222;
border-radius: 4px;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.flex-item {
min-width: 178px;
min-height: 178px;
background: radial-gradient(circle, yellow, orange);
border: 1px solid #222;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
color: #222;
font-size: 2rem;
display: flex;
justify-content: center;
align-items: center;
user-select: none;
cursor: pointer;
}
.flex-item:nth-child(2n) {
min-width: 158px;
min-height: 158px;
}
.flex-item:nth-child(3n) {
min-width: 198px;
min-height: 198px;
}
.flex-item.selected {
background: radial-gradient(circle, lightgreen, darkgreen);
}
Flex elements should be of different sizes and at the same time flexible. We achieve this with min-width / min-height and nth-child. The selected item is of class "selected" with a different background color.
Script
//
const controls = document.querySelector('#controls')
const buttons = document.querySelector('#buttons')
const flexContainer = document.querySelector('#flexContainer')
//
buttons.addEventListener('click', (e) => {
//
if (e.target.tagName !== 'BUTTON') return
//
const { btn } = e.target.dataset
switch (btn) {
// -
case 'addBtn':
// 6
// -
//
const num = document.querySelectorAll('.flex-item').length + 1
// , 7
//
if (num < 7) {
// "div"
const newItem = document.createElement('div')
//
newItem.className = 'flex-item'
//
newItem.textContent = num
// -
flexContainer.append(newItem)
}
break
// -
case 'removeBtn':
//
const index = document.querySelectorAll('.flex-item').length - 1
// , 0
// -
if (index > 0) {
// ,
const itemToRemove = document.querySelectorAll('.flex-item')[index]
//
itemToRemove.remove()
}
break
}
})
//
controls.addEventListener('change', (e) => {
//
const prop = e.target.id
//
const value = e.target.value
// ,
// - -
//
if (e.target.parentElement.id === 'flexContainerProps') {
flexContainer.style[prop] = value
} else {
const selectedItem = document.querySelector('.selected')
selectedItem.style[prop] = value
}
})
// -
flexContainer.addEventListener('click', (e) => {
// -
if (
e.target.className !== 'flex-item' ||
e.target.classList.contains('selected')
)
return
// "selected"
if (document.querySelector('.selected') !== null)
document.querySelector('.selected').classList.remove('selected')
//
e.target.classList.add('selected')
// - "-"
//
// -
//
// ,
//
// -
const getStyle = (property, element = e.target) =>
getComputedStyle(element).getPropertyValue(property)
// , DOM-, "id",
// ,
order.value = getStyle('order')
flexGrow.value = getStyle('flex-grow')
flexShrink.value = getStyle('flex-shrink')
alignSelf.value = getStyle('align-self')
})
As you can see, nothing complicated. Of course, the functionality of the resulting simulator is very limited. However, I believe this is sufficient to understand how the basic properties of Flexbox work.
I recommend that you try to create a similar simulator for the basic properties of the Grid - this will be an excellent practice and will allow you to understand everything properly.
You may also find one of my recent projects interesting, the Modern HTML Starter Template .
Thank you for your attention and have a nice day.