I'm using bootstrap's 12-column grid layout and I'd like to make a "development helper" that overlays the grid columns & gutters so we can visualize the grid to help the non-developers on my team understand how the grid works in a real application.
I'm using SCSS to generate a linear-gradient
with alternating stripes, and it's mostly working but something in the calculations is just slightly off.
Here is the relevant portion of my SCSS code
@function grid-stripes($column-color, $gutter-color: transparent) {
$stripes: null;
$col-width: percentage(divide(1, $grid-columns));
@for $i from 1 through $grid-columns {
//Columns
$col-pos: calc((#{$col-width} * #{$i}) - #{$grid-gutter-width});
$stripes:
$stripes,
$column-color $col-pos,
$column-color $col-pos;
//Gutters
@if $i != $grid-columns {
//Don't add a final gutter
$gutter-pos: calc((#{$col-width} * #{$i}) - #{$grid-gutter-width});
$stripes:
$stripes,
$gutter-color $gutter-pos,
$gutter-color $gutter-pos;
}
}
@return linear-gradient(to right, $stripes);
}
.row {
position: relative;
&::before {
display: block;
content: '';
position: absolute;
left: $grid-gutter-width / 2;
right: $grid-gutter-width / 2;
height: 100%;
z-index: 1;
opacity: 0.25;
pointer-events: none; //allow clicks to pass through
background: grid-stripes(red);
background-size: cover;
}
}
If I have this layout that uses the grid, I would want the overlay to show one red column on top of each grid column. On something that takes up 6 columns, I should see the 6 red columns
Instead, my overlay just isn't quite correct in terms of spacing the columns out with the gutters in between the columns, and it seems to fade between the transparent and red colors, where I just want a hard line to divide these
Here is a working demo of it so you can see the output generated by SCSS: https://codepen.io/FiniteLooper/pen/ZEgYrbP?editors=0100
I need to to always show 12 columns regardless of what it contains, this way you always see the grid in terms of what layout options are available to you
To have your column visible, having a pseudo element is a good idea, this way you can stack it on top of your grid.
Using background-image: linear-gradient()
with hard stops, you can highlight both the gutter (made with padding) and the content of the column.
background: linear-gradient(to right,
black 0%,
black 0.5px,
rgba(255, 0, 0, 0.2) 0.5px,
rgba(255, 0, 0, 0.2) 0.75rem,
rgba(255, 255, 0, 0.2) 0.75rem,
rgba(255, 255, 0, 0.2) calc(100% - 0.75rem),
rgba(255, 0, 0, 0.2) calc(100% - 0.75rem),
rgba(255, 0, 0, 0.2) calc(100% - 0.5px),
black calc(100% - 0.5px)
);
black 0%, black 0.5px
will create a black line, starting at the beginning and 0.5px wide.rgba(255, 0, 0, 0.2) 0.5px, rgba(255, 0, 0, 0.2) 0.75rem,
will highlight in red the left gutter. Starting after the black line, it will be 0.75rem wide. It's half of the gutter as a gutter is a combination of the right padding a of column and the left padding of the following column. To be precise, it should be calc(0.75rem - 0.5px)
.rgba(255, 255, 0, 0.2) 0.75rem, rgba(255, 255, 0, 0.2) calc(100% - 0.75rem)
then you highlight the content, it starts after half the gutter and will stop at the next gutter calc(100% - 0.75rem)
.Now you have the background-image
for 1 column.
All you need to do now, is to repeat this gradient:
background-size: calc(100% / 12);
As you have twelve columns, you need to configure the gradient to take 1/12 of the total width. Then it will repeat.
.visible-grid {
.row {
position: relative;
&::before {
display: block;
content: '';
position: absolute;
height: 100%;
z-index: 1;
opacity: 0.25;
pointer-events: none;
left: 0;
right: 0;
background: linear-gradient(to right,
black 0%,
black 0.5px,
rgba(255, 0, 0, 0.2) 1px,
rgba(255, 0, 0, 0.2) 0.75rem,
rgba(255, 255, 0, 0.2) 0.75rem,
rgba(255, 255, 0, 0.2) calc(100% - 0.75rem),
rgba(255, 0, 0, 0.2) calc(100% - 0.75rem),
rgba(255, 0, 0, 0.2) calc(100% - 0.5px),
black calc(100% - 0.5px)
);
background-size: calc(100% / 12);
}
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.2/css/bootstrap.min.css" rel="stylesheet" />
<main class="container mt-2 visible-grid">
<button type="button" class="btn btn-primary" onclick="document.querySelector('main').classList.toggle('visible-grid')">Toggle Grid</button>
<h3>Plain Columns</h3>
<div class="row mt-2">
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 1</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 2</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 3</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 4</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 5</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 6</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 7</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 8</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 9</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 10</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 11</div>
</div>
<div class="col-1">
<div style="height: 200px" class="bg-secondary text-white">col 12</div>
</div>
</div>
<hr>
<h2>Example Content</h2>
<div class="row mt-2">
<div class="col-6">
<div class="card shadow">
<div class="card-body">
<h5 class="card-title">6 Columns</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
</div>
<div class="col-3">
<div class="card shadow">
<div class="card-body">
<h5 class="card-title">3 Columns</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
</div>
<div class="col-3">
<div class="card shadow">
<div class="card-body">
<h5 class="card-title">3 Columns</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
</div>
</div>
</main>