Register to get access to free programming courses with interactive exercises

Arrangement of elements in the grid CSS: Layout on the Grid

In the last lesson, we created a 12-column grid. In this case, all the elements in it could only be placed one after the other, and had the width of one column. Of course, in real projects this is a rare situation. Often, each element has its own unique arrangement, and rarely do they stand just one after the other horizontally.

In one of the first lessons, we mentioned that all Grid-lines have ordinal numbers. Each Grid-line has 2 values: a number for counting from left to right and a number for counting from right to left. And in the latter case, the numbers have a negative value. Let's see how it looks like on the example of a regular grid.

Grid line numbering

There are five vertical Grid-lines in this grid. The very first has two ordinal numbers: 1 and -5. There are 4 horizontal Grid-lines. The lowest one has the ordinal numbers 4 and -1.

These numbers can be used to bind elements to specific Grid-lines. Note that when using Grid we we focus much less on notions like the width and heights of elements. These two characteristics are now left to the columns and rows. The size of the element inside the grid depends on them.

Let's go back to the example from the last lesson. We implemented a 12-column grid with three elements inside.

Now, knowing the ordinal numbers of all Grid-lines place our elements in the following order:

  • The first item will occupy 12 columns, starting with Grid-line number 1. It'll take up two whole rows.
  • The second element should be located below the first element and will take up 4 columns, starting with the first.
  • The third element will occupy the remaining 8 columns next to the second element.

The end result is a typical 2-column layout structure. There are four properties in CSS Grid Layout for positioning elements along Grid-lines:

  • grid-column-start — ndicates the initial vertical Grid-line of the element's location.
  • grid-column-end — indicates the final vertical Grid-line of the element's location. Note that the value indicates before which column to place the item. The column specified in this property is not activated. If you want to include the specified column as well, you need to add a new one. For example, for a 12-column layout, you need to enter 13 if you want to include the last column.
  • grid-row-start — indicates the initial horizontal Grid-line of the element's location.
  • grid-row-end — indicates the final horizontal Grid-line the property specifies before which row to place the element.

Using these properties, we can not only set the initial positions from which the element is drawn, but also the final positions, which gives us the width of the element. Let's set the necessary properties for all three blocks. Let's add some semantics.

Note that we set grid-column-start for the header. This may seem superfluous, because the block starts from the first column. This is true if no end Grid-line is specified. If you remove the grid-column-start property, it's as if the element starts expanding from right to left instead of left to right.

In order to make these properties more convenient to use, there are abbreviated ways to enter them. They allow you to write start and end values using just one property. The grid-column property is used to specify the start and end strip horizontally. We use grid-row to do the same vertically. The value is the start and end strip, separated by slash /.

If we use abbreviations, the example above can be written as follows:

.grid-header {
  grid-column: 1 / 13;
  grid-row: 1 / 3;

.grid-aside {
  grid-column: 1 / 5;
  grid-row: 3 / 13;

.grid-main {
  grid-column: 5 / 13;
  grid-row: 3 / 13

One interesting technique when positioning elements within strips is to use negative values. Since each strip has two values, it's also possible to refer to them with negative values. This is especially useful when you want to stretch the item to the full width of the container. Instead of counting the number of strips, you can specify -1 as the final value. This will automatically stretch the item to the last strip. You no longer have to keep the number of strips in your head and change them when you change the grid.

As an example, let's stretch the header using a negative final value.

Keyword span

When making layouts, it is often inconvenient to know which strip an element starts from, and from which one it ends. It's much better to know which strip the element is drawn from and the number of columns it should occupy. It's impossible to do this with the tools that we've studied so far.

To solve this problem, the developers of the standard introduced the keyword span, ndicating the number of cells needed for the element when placed inside the grid. Now, instead of specifying the index of the strip where it should end, you can use this syntax: span <number of cells>.

Let's continue working with the two-column layout. When creating the header, we used a negative value to set determine the final strip. Let's move on to the two columns below. Using the keyword span, it's possible to shorten the code and make it more understandable.

.grid-header {
  grid-column: 1 / -1;
  grid-row: 1 / span 2; /* Specify that the element occupies two columns vertically */

.grid-aside {
  grid-column: 1 / span 4; /* Specify that the element occupies 4 columns horizontally */
  grid-row: 3 / -1;

.grid-main {
  grid-column: 5 / -1;
  grid-row: 3 / -1

An interesting feature is that you can use keyword span on its own as a value. In this case, the browser will place the element with the number of lines/columns that you specified. For example, the following will create a 2-column wide element:

.col-2 {
  grid-column: span 2;

This is useful when arranging elements within a grid. With this approach, it's possible to create your own framework, in which classes are responsible for the number of columns occupied by a block.

Naming lines

For convenience and to make it easier to read your CSS, in addition to using line indexes, you can give your lines names. These can be any names that describe a given line. As we go on, we'll be able to work using these names. This is useful when creating complex layouts, because it's not great to have to constantly remember where the different blocks start and end. The number of errors will increase as the layout becomes more complex. In the case of names, everything is much simpler, because they clearly describe the Grid-line with a name that makes sense to the developer.

In order to create named Grid-lines use the following syntax for the grid-template-columns and grid-template-rows properties: [Line name] is the width of the strip after the line. You can set any number of different names, and you can do so directly in the layout. It won't damage the current template.

Let's add named lines to our two-column layout to indicate the beginnings of each area. We use them to designate starting rows and columns. There will be four of these named lines:

  1. header-top — The topmost line from which the header of the site will be drawn.
  2. content-begin — The line where the main content of the site starts. In this case, it's aside and main Use it as a header height limiter.
  3. sidebar-begin — The left line from which aside will be drawn.
  4. main-begin — The line from which main begins. Let's use it to limit the width of aside.

Let's substitute the names in the existing CSS and see how they are written:

.grid-12 {
  display: grid;
  grid-template-columns: [sidebar-begin] 1fr repeat(3, 1fr) [main-begin] 1fr repeat(7, 1fr);
  grid-template-rows: [header-top] 1fr 1fr [content-begin] 1fr repeat(9, 1fr);

  height: 100vh;

Let's parse the following line: grid-template-columns: [sidebar-begin] 1fr repeat(3, 1fr) [main-begin] 1fr repeat(7, 1fr);. It can be divided into four parts:

  • [sidebar-begin] 1fr. As described, we create a named line named sidebar-begin and a one-fraction-wide strip.
  • repeat(3, 1fr). One entry you've already seen, which will create 3 strips with a width of 1 fraction each.
  • [main-begin] 1fr. A named line main-begin is created. The width of the strip after the line will be 1 fraction.
  • repeat(7, 1fr). Seven strips with a width of 1 fraction each are created.

These names can now be used in the grid-column-start, grid-column-end, grid-row-start and grid-row-end properties that we studied.

It's important to note: that even if you name a line, it doesn't lose its index. You can refer to these lines both by their index (positive or negative) and by their names.

Creating named Grid areas

As well as allowing you to name Grid-lines the developers have also made it possible to name entire areas. As you remember, an area is several strips that are connected by single Grid-lines. So how can naming areas help with creating layouts? In fact, this tool is quite groundbreaking when it comes to creating designs in CSS. This property allows you not only to name abstract areas, but also to visualize the grid using those names. One of the disadvantages of this method is that it's a little unwieldy. Let's deal with this more when we do the practice tasks.

The grid-template-areas property is used to create named areas. It takes data wrapped in double quotes as a value. The data in question describes the areas located on the grid. The more columns they occupy, the more times they need to be repeated inside the value. The values themselves are separated by a space. Create a grid of 6 columns. Put a 2 column layout in it, as in the previous example. First, let's define the header. It takes up the entire width of the screen, so it needs to be allocated six columns. Let's call this area, naturally, the header. You can choose whatever name you like for this area. We also need to specify the block that will be the header area. This is done using the grid-area property, the value of which is the name of the area. In this case, it's header.

.grid-6 {
  display: grid;
  grid-template-areas: "header header header header header header";

.grid-header {
  grid-area: header;

Note that the .grid-6 .grid-6 container lacks the grid-template-columns and grid-template-rows properties. Their job is now the job of the grid-template-areas role. Specifying a certain number of areas in it automatically creates columns with a width of 1 fraction. If you need other values, you can always use the grid-template-columns and grid-template-rows properties to set the desired strip widths.

Now we've done the top row, it's time to start on the next row, where we'll place aside and main. To do this, continue to enter values in the grid-template-areas property. Since we need a new row, it makes no sense to write inside the value with header Let's add a space, and write new double quotes containing the locations of elements in the next row.

.grid-6 {
  display: grid;
  grid-template-areas: "header header header header header header" "aside aside main main main main";

.grid-header {
  grid-area: header;

.grid-aside {
  grid-area: aside;

.grid-main {
  grid-area: main;

Note that: in each row, the number of columns must be the same. If you omit this point on any line, the browser will ignore the grid-template-areas property because it can't understand or process what you want from it.

If more rows are needed, you can continue to add them. This is important if you have non-standard cell sizes. In other cases, the height of blocks will be determined by the content within them. This is standard behavior, you'll know it already from designing layouts. In this case, we created a grid of 6 columns and two rows.

CSS allows you to move lines within a property to make it easier to read. This makes the grid-template-areas property more visible. You can also put any number of spaces within the values themselves. The columns in each row can be set below each other:

.grid-6 {
  display: grid;
  grid-template-areas: "header header header header header header"
                       "aside  aside  main   main   main   main";

There are situations when instead of one of the columns you need some existing area, but an empty cell. Since the number of columns in each row must be the same, you can't just delete one of the areas. Instead grid-template-areas can take a special value that denotes an empty area. This value is a period - .. Let's make the header in the current grid one column smaller. The header should take up 5 columns instead of 6. In this case, the value of the property will look like this:

.grid-6 {
  display: grid;
  grid-template-areas: "header header header header header ."
                       "aside  aside  main   main   main   main";

Do it yourself

Create a three-column layout consisting of the following:

  • A header.
  • A left sidebar.
  • Main Content.
  • A right sidebar.
  • A footer.

Use both methods when creating. Use Grid-lines first, then Grid-areas. The number of columns in the grid is up to you. In this case, there can't be less than three.

Hexlet Experts

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
hours of theory

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing:">Bookmate</span>
<span class="translation_missing" title="translation missing:">Healthsamurai</span>
<span class="translation_missing" title="translation missing:">Dualboot</span>
<span class="translation_missing" title="translation missing:">Abbyy</span>
Suggested learning programs
Layout with the latest CSS standards
5 months
from scratch
under development
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.