Creating a Grid Visualizer
Tags: css, design, javascript, webdev
Published: 2022-07-05 08:09:21

If you're working with a grid-system, chances are, you're using some kind of grid visualizer – maybe in Figma, or in Dev Tools.

I'm currently working on a project where I need a customizable grid-visualizer. Thankfully it's pretty simple – using a bit of math and CSS!

---

The markup for this demo is very basic. We have a grid, and a single piece of content:

```html
<div class="grid">
  <div class="content"></div>
</div>
```

In CSS, we need two custom properties to control the amount of columns and the column-gap:

```css
:where(html) {
  --columns: 6;
  --column-gap: 20px;
}
```

For the `.grid`-class, we need to set up a basic grid, using the two custom properties, we just configured:

```css
.grid {
  column-gap: var(--column-gap);
  display: grid;
  grid-template-columns: repeat(var(--columns, auto-fit), 1fr);
}
```

We'll add the colors for the columns and gaps as two new properties:

```css
--_col-bgc: hsl(200, 50%, 75%, .5);
--_gap-bgc: hsl(200, 50%, 45%, .5);
```

---

And now for a bit of math! The width of a column is:
```
100% / number of columns
```

From that value, we need to deduct the gap-width. There will always be one gap less than the number of columns, so:

```
((number of columns - 1) * gap-width) / number of columns
```

Simplified, this is:

```
(100% - (number of columns - 1) * gap-width)) / number of columns
```
In CSS, we add this logic to a custom property:


```css
--_w: calc( (100% - (((var(--columns) - 1) * var(--column-gap)))) / var(--columns) );
```

Finally, using our custom properties, we add a `repeating-linear-gradient`:


```css
background-image: repeating-linear-gradient(to right,
  var(--_col-bgc), var(--_col-bgc) var(--_w),
  var(--_gap-bgc) var(--_w), var(--_gap-bgc) calc(var(--_w) + var(--column-gap) ) );
```

With our default settings, this renders a nice 6-column grid with gaps:

![6-col-grid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fr1c5549iiirgbzh13g.png)

---

For the `.content`, we add a small chunk of css:

```css
.content {
  background-image: linear-gradient(45deg, black, transparent);
  grid-column: span var(--column-span, 3);
}
```

With the default `--column-span: 3`, this gives us:

![Content with colspan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58hg7gfs4fdot47yjkgc.png)
 
Let's compare this with Dev Tools' grid visualizer, which we add by clicking the small `grid`-button next to the markup:

![Enable Dev Tools Grid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w8jvhzflegrn6jvrdbxo.png)
 
 
This renders:

![Grid with Visualizer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/exzax7mmqesjn31dhgpz.png)

Cool – This seems to be working!

---

## Adding an editor

Finally, let's add a small editor, so we can easily play around with the columns-, gap- and colspan-properties:

```html
<form id="app">
  <fieldset>
    <legend>Grid Visualizer</legend>
    <label>Columns
      <input type="range" name="columns" value="6" min="1" max="12" />
    </label>
    <label>Gap
      <input type="range" name="column-gap" value="20" min="0" max="100" data-unit="px" />
    </label>
    <label>Column-span
      <input type="range" name="column-span" value="3" min="1" max="12" data-scope=".content" />
    </label>
  </fieldset>
</form>
```

To update the custom properties dynamically, we need a small JavaScript:


```js
app.addEventListener('input', (event) => setCustomProperty(event.target));
function setCustomProperty(input) {
  const scope = input.dataset.scope;
  const node = !scope ? document.documentElement : scope === 'self' ? input : scope === 'parent' ? input.parentNode : document.querySelector(scope);
  node.style.setProperty('--' + input.name, input.value + (input.dataset.unit || ''));
}
```

---

## Codepen demo
 
{% codepen https://codepen.io/stoumann/pen/QWmjmzy %}

---

Happy coding!