I am using a grid layout to show several rows. Each row contains 3 columns (an image, a label and an svg graphic) and I want (based on some logic not relevant here) to hide/unhide entire rows.
After a lot of trial and error and reading a myriad of different blog posts, I adapted the following approach which is pretty close to what I want to achieve.
There are 2 minor things which, however, bother me.
<img>
nor the <svg>
are completely centered. .grid-row
is 4px
taller than necessary (it's height is 104px
, while both the <img>
and the <svg>
are 100px
tall). Why? How to get rid of the 4px
?function toggleRow() {
const i = d3.select('#row').property('value');
const row = d3.select('.grid-row:nth-child(' + i +')');
row.classed('visible', !row.classed('visible'));
}
:root {
--transitionLength: 0.4s;
--transitionTiming: ease;
}
.grid {
display: inline-grid;
grid-template-columns: 110px minmax(200px, max-content) 1fr;
row-gap: 5px;
}
.grid-row {
display: grid;
grid-template-columns: subgrid;
grid-template-rows: 0fr;
grid-column: 1 / 4;
align-items: center;
column-gap: 10px;
overflow: hidden;
background-color: lightgray;
transition: grid-template-rows var(--transitionLength) var(--transitionTiming);
}
.grid > .visible {
grid-template-rows: 1fr;
}
.grid-item {
min-height: 0;
transform: translateY(-100%);
visibility: hidden;
transition: transform var(--transitionLength) var(--transitionTiming),
visibility 0s var(--transitionLength) var(--transitionTiming);
}
.grid > .visible > .grid-item {
transform: translateY(0);
visibility: visible;
transition: transform var(--transitionLength) var(--transitionTiming),
visibility 0s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<div class="grid">
<div class="grid-row visible">
<div class="grid-item img"><img src="https://picsum.photos/100" alt="Placeholder Image"/></div>
<div class="grid-item label">
<h2>Can be a long Line with several words...</h2>
</div>
<div class="grid-item svg">
<svg xmlns="http://www.w3.org/2000/svg" width="163.63" height="100" viewBox="0 0 18 11">
<rect width="18" height="11" fill="#fff" />
<path d="M0,5.5h18M6.5,0v11" stroke="#002F6C" stroke-width="3" />
</svg>
</div>
</div>
<div class="grid-row">
<div class="grid-item img"><img src="https://picsum.photos/100" alt="Placeholder Image" /></div>
<div class="grid-item label">
<h2>...or very short</h2>
</div>
<div class="grid-item svg">
<svg xmlns="http://www.w3.org/2000/svg" width="163.63" height="100" viewBox="0 0 18 11">
<rect width="18" height="11" fill="#fff" />
<path d="M0,5.5h18M6.5,0v11" stroke="#002F6C" stroke-width="3" />
</svg>
</div>
</div>
</div>
<br>
<input type="number" id="row" name="number" min="1" max="3" value="1" />
<button onclick="toggleRow()">Toggle Row</button>
I think I over-complicated matters a bit. A simple transition (without the transform) on grid-template-rows
should do the trick.
N.B. I needed to remove the align-items
rule, lest the hidden content would still protrude (for whatever reason).
function toggleRow() {
const i = d3.select('#row').property('value');
const row = d3.select('.grid-row:nth-child(' + i +')');
row.classed('visible', !row.classed('visible'));
}
:root {
--transitionLength: 250ms;
--transitionTiming: ease-out;
}
.grid {
display: inline-grid;
grid-template-columns: 110px minmax(200px, max-content) 1fr;
row-gap: 5px;
}
.grid-row {
display: grid;
grid-column: 1/4;
grid-template-columns: subgrid;
background-color: lightgray;
grid-template-rows: 0fr;
transition: grid-template-rows var(--transitionLength) var(--transitionTiming);
/*align-items: center;*/
column-gap: 10px;
}
.grid > .visible {
grid-template-rows: 1fr;
}
.grid-row > .grid-item {
overflow: hidden;
min-height: 0;
}
.grid-item > img, .grid-item > svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<div class="grid">
<div class="grid-row visible">
<div class="grid-item img"><img src="https://picsum.photos/100" alt="Placeholder Image" /></div>
<div class="grid-item label">
<h2>Can be a long Line with several words...</h2>
</div>
<div class="grid-item svg">
<svg xmlns="http://www.w3.org/2000/svg" width="163.63" height="100" viewBox="0 0 18 11">
<rect width="18" height="11" fill="#fff" />
<path d="M0,5.5h18M6.5,0v11" stroke="#002F6C" stroke-width="3" />
</svg>
</div>
</div>
<div class="grid-row">
<div class="grid-item img"><img src="https://picsum.photos/100" alt="Placeholder Image" /></div>
<div class="grid-item label">
<h2>...or very short</h2>
</div>
<div class="grid-item svg">
<svg xmlns="http://www.w3.org/2000/svg" width="163.63" height="100" viewBox="0 0 18 11">
<rect width="18" height="11" fill="#fff" />
<path d="M0,5.5h18M6.5,0v11" stroke="#002F6C" stroke-width="3" />
</svg>
</div>
</div>
</div>
<br>
<div>
<input type="number" id="row" name="number" min="1" max="3" value="1" />
<button onclick="toggleRow()">Toggle Row</button>
</div>