Misha Moroshko
Misha Moroshko

Reputation: 171459

CSS: How to let overflowing grid items not affect the defined grid?

Consider the following 4 columns grid:

.container {
  width: 400px;
  height: 200px;
  position: relative;
}

.grid-columns {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
  z-index: -1;
}

.grid-column {
  background-color: #ddd;
}

.columns {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
}

.column {
  background-color: rgba(0, 0, 255, 0.5);
  grid-column-start: 3;
  grid-column-end: span 2;
}
<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column"></div>
  </div>
</div>

The blue item starts at the third grey area and occupies the last 2 columns as expected.

However, if we make it span 5 columns instead of 2:

grid-column-end: span 5;

...implicit tracks are added and the blue item doesn't start at the same place anymore:

enter image description here

.container {
  width: 400px;
  height: 200px;
  position: relative;
}

.grid-columns {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
  z-index: -1;
}

.grid-column {
  background-color: #ddd;
}

.columns {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
}

.column {
  background-color: rgba(0, 0, 255, 0.5);
  grid-column-start: 3;
  grid-column-end: span 5;
}
<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column"></div>
  </div>
</div>

How could I force the blue item to start at the same place even if it overflows the grid?

I thought that adding grid-auto-columns: 0 to the grid would do the trick, but it doesn't.

Upvotes: 1

Views: 942

Answers (1)

Temani Afif
Temani Afif

Reputation: 274024

Use percetange to define the width instead of specifing column to avoid creating implicit columns. 100% is the width of one column and don't forget to account for the gaps:

.container {
  width: 400px;
  height: 200px;
  position: relative;
}

.grid-columns {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
  z-index: -1;
}

.grid-column {
  background-color: #ddd;
}

.columns {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
}

.column {
  background-color: rgba(0, 0, 255, 0.5);
  grid-column-start: 3;
  width:calc(5*100% + (5 - 1)*30px)
}
<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column"></div>
  </div>
</div>

With CSS variable you can make the syntax easier:

.container {
  width: 400px;
  height: 50px;
  position: relative;
  margin:10px;
}

.grid-columns {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
  z-index: -1;
}

.grid-column {
  background-color: #ddd;
}

.columns {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 30px;
}

.column {
  background-color: rgba(0, 0, 255, 0.5);
  grid-column-start: 3;
  width:calc(var(--n,1)*100% + (var(--n,1) - 1)*30px)
}
<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column"></div>
  </div>
</div>

<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column" style="--n:2"></div>
  </div>
</div>

<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column" style="--n:3"></div>
  </div>
</div>

<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column" style="--n:5"></div>
  </div>
</div>

Another idea in case you will have fixed value is to define the template using pixel values and then you will be able to use grid-column-end: span X;

.container {
  width: 400px;
  height: 50px;
  position: relative;
  margin:10px;
}

.grid-columns {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-auto-columns: calc((100% - 3*30px) /4);
  grid-auto-flow: column;
  grid-column-gap: 30px;
  z-index: -1;
}

.grid-column {
  background-color: #ddd;
}

.columns {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  grid-auto-columns: calc((100% - 3*30px) /4);
  grid-auto-flow: column;
  grid-column-gap: 30px;
}

.column {
  background-color: rgba(0, 0, 255, 0.5);
  grid-column-start: 3;
  grid-column-end: span var(--n);
}
<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column"></div>
  </div>
</div>

<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column" style="--n:2"></div>
  </div>
</div>

<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column" style="--n:3"></div>
  </div>
</div>

<div class="container">
  <div class="columns">
    <div class="grid-columns">
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
      <div class="grid-column"></div>
    </div>
    <div class="column" style="--n:5"></div>
  </div>
</div>

Upvotes: 1

Related Questions