Rows in grid that can be collapsed into a more compact form

I have implemented a grid layout to display multiple rows, each containing 3 columns (an image, a label, and an SVG graphic). I need the ability to hide/unhide entire rows based on specific logic.

After experimenting with different methods and researching various blog posts, I have developed an approach that comes close to meeting my requirements.

However, there are two minor issues that I find concerning:

  1. The <img> and <svg> elements are not perfectly centered. The height of .grid-row is 4px taller than necessary (104px vs. the 100px height of both <img> and <svg>). How can I eliminate this extra 4px in height? A helpful comment from @Paulie_D addressed this problem
  2. During the transition, the content within the row and the surrounding grid do not move at the same speed. I would like the entire row to disappear as one cohesive unit, rather than individual components vanishing separately. Additionally, the final part of the row disappears from the top while the rest vanishes from the bottom. Is there a way to change this behavior?

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>

Answer №1

I may have made things more complex than necessary. A straightforward transition (without the transform) on grid-template-rows should solve the issue.

N.B. I had to eliminate the align-items rule to prevent the hidden content from still protruding (for some unknown 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Finding the data type based on the button clicked with javascript: A beginner's guide

I am trying to work with a PHP function that generates dynamically created divisions. Each of these divisions contains a different data type and a button. How can I extract the data type of a division when the user clicks on the submit button using JavaScr ...

Automatic closure of the div tag in JavaScript

I am revamping my website to a more modern web application, and here is the HTML code I am using: <joexn-profile> <joexn-logo></joexn-logo> <joexn-text></joexn-text> </joexn-profile> Additionally, here is the JavaScrip ...

Failed to add a new entry to the Sharepoint 2013 List

Having trouble saving an item to a SharePoint list using Knockout.js and REST. In my Ajax POST request, I've used ko.toJSON but the entry doesn't show up in the SharePoint list. It's possible that I'm passing the wrong parameter value. ...

Is it possible to use jQuery to highlight HTML tags within a textarea field?

Is there a simple method using jQuery to highlight html-tags in red within a textarea? I'm clueless about how to achieve this since HTML tags aren't allowed in textarea, correct? :( Alternatively, can someone provide me with some helpful resour ...

Uncovering the hidden gems within a data attribute

Trying my best to explain this clearly. What I have is a data-attribute that holds a large amount of data. In this case, I need to extract each individual basket product ID and display them as separate strings. The challenging part for me is locating thi ...

Is there a way to navigate by scrolling, moving a centrally-positioned SVG along a path while also resizing the SVG?

After following the instructions in this post about resizing SVGs, I managed to keep the red square on the path while resizing the SVG. However, a new issue arises when scrolling down - the red square is not moving to stay positioned at the center of the w ...

Rotation using CSS in Internet Explorer 8

Can anyone help me with a CSS solution for rotating elements in IE8? I've tried some solutions that claim to work in IE8, but they're not working for me. What am I doing wrong? Here's what I've attempted: <!DOCTYPE html> <htm ...

Tips for adjusting the vertical position of an image within a bootstrap column by a small amount

Apologies in advance if this question has already been addressed, and I am struggling to adapt it to my specific scenario. My objective is to adjust the positioning of the two images shown in the screenshot example below so that they align with the grey b ...

Mysterious jQuery feature: Transform your top slider to slide in from the right side

My expertise lies in web design using Photoshop, while other programmers bring my designs to life. However, I've been considering taking on the coding part myself for a change with jQuery being outside of my comfort zone. This is my first project in w ...

Unable to interact with webpage element using Java and Selenium_INVALID

I have attempted various methods such as WebDriverWait, .click(), .sendKeys(Keys.RETURN), implicitWait, explicitWait, and more, but I am facing difficulties in clicking on this specific web element. Here is the HTML code snippet that I am trying to intera ...

The pagination feature in the R web scraper is not functioning correctly

library(rvest) library(RCurl) library(XML) library(stringr) #Retrieving Page Number getTotalPages <- function(URL) { print(URL) parsedDocument <- read_html(URL) pageNumber <- parsedDocument %>% html_nodes(".al-pageNumber") %>% ...

Create a website that includes a feature for reading text aloud

Embarking on a new venture, I am thrilled to introduce my latest project. This project involves creating a spell checker designed specifically for children, with the added feature of sending performance reports directly to their teachers. The teacher inte ...

Repeated tweets detected within real-time Twitter stream

I've been working on developing a live update Twitter feature, but I've noticed that it sometimes duplicates tweets and behaves erratically. Did I make a mistake somewhere in my code? http://jsfiddle.net/JmZCE/1/ Thank you in advance (note: I p ...

"Utilize the on() method to bind a click event to dynamically generated elements received

After reading several discussions on using on() to link events to dynamically generated HTML elements, I decided to create an example (FIDDLE) where the click event is bound to elements div.clicktitle fetched via AJAX. These div elements contain data attri ...

Show an item vertically centered within its parent container

Following is the appearance of the selector: https://i.sstatic.net/njql9.png The text currently appears close to the bottom of the selector. I would like it to be centered vertically while maintaining its horizontal positioning towards the left side. He ...

The image is failing to display in the CSS

As a beginner in the world of CSS and HTML, I encountered an issue where my background image is not showing up. Here's the code snippet that I have: ... <style type="text/css"> #header_contain{ width:935px; height: 135px; ...

Conceal header and footer bar in Jquery Datatable theme

I need assistance in removing the header/footer bar from this table Here is a visual representation of what I am looking to remove: The jQuery code for this table: $(document).ready(function() { var oTable = $('#tableSmooth').dataTable({ ...

Having issues with vertical space distribution in flexbox column layout

Is there a way to align vertical content with space-between without specifying the height? I want to justify-content-between the red and black divs in the third column without setting a height value. Can this be achieved considering we already have a max-h ...

Align text to the center vertically on the screen

I am struggling to vertically center my text on a page. Whenever I click a button, the page becomes gray with a loading message. Although I've managed to horizontally center it, vertical alignment is posing a challenge. CSS .LockOff { display: n ...

Is using display:table an effective approach for achieving equal height columns?

I am currently working on a responsive design project and I need two columns of equal height. I do not want to rely on JavaScript for this, and I prefer having some whitespace between the columns to enhance readability. I have tried two different layouts; ...