Search code examples
htmlcsscss-grid

Creating own CSS grid, 'offset' class is messing with width


I'm trying to create my own CSS grid, with offset classes.

The problem is, when I apply the offset class to the column, it messes up the width of it and the column goes really narrow. Without the offset class the width works perfectly.

/* grid system */

.container {
  background: #999;
  margin: 0 auto;
  padding: 0 15px;
  max-width: 1680px;
  width: 100%;
}

.row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  margin: 0 -15px;
}

.col {
  outline: 2px white dashed;
  padding: 15px;
}


/* cols */

.col-8 {
  grid-column: span 8;
}


/* col offsets */

.col-offset-1 {
  grid-column-start: 2;
}
<div class="container">
  <main class="row">
    <div class="col-8 col-offset-1">
      <p>
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Illum quibusdam perspiciatis, magnam autem velit totam quae consectetur tempora qui ipsum odit sed voluptatem quaerat error quos iusto aliquid nesciunt tenetur.
      </p>
    </div>
  </main>
</div>

I've also realised that, if I specify a start column to the CSS, then it works properly in this instance. But I can't set that to every column class as it will mess up my layout:

/* grid system */

.container {
  background: #999;
  margin: 0 auto;
  padding: 0 15px;
  max-width: 1680px;
  width: 100%;
}

.row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  margin: 0 -15px;
}

.col {
  outline: 2px white dashed;
  padding: 15px;
}


/* cols */

.col-8 {
  grid-column: 1 / span 8;
}


/* col offsets */

.col-offset-1 {
  grid-column-start: 2;
}
<div class="container">
  <main class="row">
    <div class="col-8 col-offset-1">
      <p>
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Illum quibusdam perspiciatis, magnam autem velit totam quae consectetur tempora qui ipsum odit sed voluptatem quaerat error quos iusto aliquid nesciunt tenetur.
      </p>
    </div>
  </main>
</div>


Solution

  • One approach is as follows, which uses a custom CSS property to pass the relevant offset to the .col-8 content you're trying to place:

    /* grid system */
    
    .container {
      background: #999;
      margin: 0 auto;
      padding: 0 15px;
      max-width: 1680px;
      width: 100%;
    }
    
    .row {
      display: grid;
      grid-template-columns: repeat(12, 1fr);
      margin: 0 -15px;
    }
    
    .col {
      outline: 2px white dashed;
      padding: 15px;
    }
    
    /* cols */
    
    .col-8 {
      /* here we're using the CSS calc() function to determine the
         column-grid-line at the start of the grid-column-track into
         which the content should be placed; this takes the form of
         1 + <offset>, as the starting edge of the grid is number 1.
         Into this calculation we pass in the --offset custom
         property or, if that property isn't defined, the default of
         0: */
      grid-column: calc(1 + var(--offset, 0)) / span 8;
    }
    
    /* col offsets */
    
    .col-offset-1 {
      /* here we define the --offset property with the appropriate
         value: */
      --offset: 1;
    }
    <div class="container">
      <main class="row">
        <div class="col-8 col-offset-1">
          <p>
            Lorem ipsum, dolor sit amet consectetur adipisicing elit. Illum quibusdam perspiciatis, magnam autem velit totam quae consectetur tempora qui ipsum odit sed voluptatem quaerat error quos iusto aliquid nesciunt tenetur.
          </p>
        </div>
      </main>
    </div>

    JS Fiddle demo.

    References: