Placing, Spanning, and Density in CSS Grid

Published on December 12, 2019
Default avatar

By Chris Nwamba

Placing, Spanning, and Density in CSS Grid

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.


The most common thing you learn in CSS Grid is usually related to the grid container and rather than the grid items. A generic grid definition applied to the grid container is enough for a basic layout structure. However, when you need more control over the contents of the grid, the grid container is limited its uses.

For example, you may want a 4 x 2 grid but the first grid item should take up column 1 and 2 as well as row 1 and 2. Or maybe you want an item to span till the last grid column track when you have no idea what the runtime total number of the grid column track is.

Each grid item’s size is predefined and you need to find a way to size them relatively to other items in the grid container.

In this tutorial you’ll explore placing, spanning, and density in CSS Grid.

Placing Grid Items: Start Here, End There

Everything in the browser has a default style, for example, 0 or auto. There could also be other defaults that you need to be aware of before adjusting for custom values. When you have a grid, the grid items have placement values defined by grid-[x]-start and grid-[x]-end (where x can be column or row). The value is auto.

When you see a grid layout, it can help to remember that each item in that grid has a placement value no matter how symmetric the flow looks:

    .container {
      display: grid;
      grid-gap: 10px;
      grid-template-columns: repeat(5, 1fr)

    .item {
      grid-column-start: auto; /_ default _/
      grid-column-end: auto; /_ default _/
      grid-row-start: auto; /_ default _/
      grid-row-end: auto; /_ default _/

Placing Columns

Let’s adjust these default values starting with columns:

    .item:nth-child(1) {
      grid-column-start: 1;
      grid-column-end: 5;
  • We want the first item in the grid .item:nth-child(1)
  • To start at line one, grid-column-start: 1;
  • And end at line 5, grid-column-end: 5;

See the full code here.

Placing Rows

The same rules apply to row-placing:

    .item:nth-child(22) {
      grid-row-start: 1;
      grid-row-end: 4;

However, grid-row-[x] will reset the grid item default placement to start at column line 1 and row line 1, then the placement spanning will occur.

You’ll see in this code that line 22 left its spot and moved up to line 1 before spanning.

If you want it to stay at its original column track, then you have to explicitly state that:

    .item:nth-child(20) {
      grid-column-start: 3;
      grid-row-start: 5;
      grid-row-end: 10;

You can provide only start or end—you do not have to provide the placing properties in pairs. You can just provide one and the rest will stay as auto (default). The tricky thing to watch out for is that if you change only the value of grid-[x]-start, the grid item will start at the line, not the track:

    .item:nth-child(1) {
      grid-column-start: 5;

On the other hand, if you specify end only, it will start from the specified end value and span the grid inversely. For example, if you tell item 10 to end at 3, it will start from the nearest next line 2 and draw to line 3:

    .item:nth-child(10) {
      grid-column-end: 3;

You can see all the code here.

There’s also shorthand syntax for grid-[x]-start and grid-[x]-end that allows you to do away with the -start and -end code:

    .item {
      grid-column: [start] / [end];
      grid-row: [start] / [end];

Here are some examples that can replace the code samples we have written so far:

    .item {
      grid-column: 1 / 5; /__ Line 1 to 5 /
      grid-row: 1 / 4; /*_ Line 1 to 4 __/
      grid-column: 5 / auto; / Line 5 to 6 *_/
      grid-column: auto / 3; /_ Line 2 to 3 _/

Spanning: Start/End Here, Take n

We have been using the word “span” to describe the number of tracks a placement should occupy. When we say line 1 to 5, we are saying the grid item should span from 1 to 5. I usually refer to this as implicit spanning.

There is a span keyword that serves as a value. When this is used, you can refer to it as explicit spanning. Placing and spanning are flexible enough that you can use both implicit and explicit spanning as value to a single property.

Spanning Columns

Let’s start with looking at how we can span an item across a column track:

    .item:nth-child(1) {
      grid-column: span 5;

This is an alternative to the first example we wrote:

    .item:nth-child(1) {
      grid-column: 1 / 5;

But we can include additional detail:

    .item:nth-child(1) {
      grid-column: span 2 / 5;

Here we end at 5 and the span 2 tracks backward.

Another example:

    .item:nth-child(1) {
      grid-column: 2 / span 2;

Here we start at column line 2 and end at column line 4 (after 2 jumps).

Spanning Rows

Everything you have learned so far in this tutorial about rows applies without exception:

    .item:nth-child(1) {
      grid-column: 2 / span 2;
      /_ highlight line_/
      grid-row: span 5

We are still spanning the first time, but then we’re spanning on the row axis. The browser will draw the box down to occupy five tracks.

Excess Placement and Spanning

Recall that we have explicitly defined our grid to have 5 columns. We can span or place an item from column 6 up like the following:

    .item:nth-child(1) {
      grid-column: span 10; /_ 1 _/
      grid-column: 1 / 10; /_ 2 _/
      grid-column: 7 / 10; /_ 3 _/
      grid-column: 1 / span 10; /_ 4 _/

Implicit tracks will be created to accommodate them.

Negative Integers as Values

Negative integers are as useful as the positives—they inverse the placement or spanning. Hence, instead of starting from the first column or row, the placement or spanning will start from the last column or row.

These code snippets are direct opposites:

    .item:nth-child(1) {
      grid-column: 1 / 5
    .item:nth-child(1) {
      grid-column: -1 / -5

Since we are starting at the end to draw backward as I mentioned above, there will be room for item 2 in column 1 so it gets pushed down. We will look at using density to fill up these spaces created in such cases (if the content is not symmetric).

There is a way that you can span to the end of a column or row without needing to know how many columns are defined by the grid container. This is useful when you are using auto-fill or auto-fit in defining a dynamic grid:

    .item:nth-child(1) {
      grid-column: 1 / -1

Specifying -1 for row end or column end will make the grid item span till the end of grid starting at what ever start you provided (in this case line 1).

However, this does not work on implicit grids. Therefore since we defined only column and row in the grid container, this will not do anything:

    .item:nth-child(1) {
      grid-row: 1 / -1;

For it to work, you would have to give an explicit row definition to the grid container. For example:

    .container {
      grid-template-rows: repeat(10, 30px);


In the previous examples, you will have seen some placement or spanning that caused empty spaces scattered in the middle of a grid.

You can close these spaces using grid-auto-flow property on the grid container to close up those white spaces:

    .container {
      grid-auto-flow: dense;

One thing you should be aware of is that if you have symmetric content that needs to follow an order, making the flow dense will distort that order. This is a trade-off you have to make if you want a compact design while still placing grid items irregularly.

Notice how after placing item 1 at the end, the grid comes back to continue placing 2 at the beginning of the tracks.


In this tutorial, we explored CSS Grid: placing, spanning, and density.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us

About the authors
Default avatar
Chris Nwamba


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
Leave a comment

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel