Retrieve the bounding rectangle of a div that has the CSS style `display: contents` using the getBoundingClientRect

My objective is to apply styling and obtain the bounding box of an entire "row" within a CSS grid, including features like highlighting when hovering over it.

To achieve the styling aspect, I make use of the display: contents property, so that the styles can affect the child elements without affecting the overall layout structure.

However, I encountered an issue where attempting to retrieve the size (height) of the row using getBoundingClientRect results in all zeros being returned.

const row = document.getElementById("firstrow");
console.log(row.getBoundingClientRect());

const actual_cell = document.getElementById("data");
console.log(actual_cell.getBoundingClientRect());
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}
.row {
  display: contents;
}
.row:hover div {
  background-color: lightgray;
}
.cell {
  border: 1px black solid;
  max-height: 100px;
}
.ipsum {
  height: 200px;
  max-height: 300px;
}
<div class="grid">
  <div class="row" id="firstrow">
      <div class="cell">hello</div>
      <div class="cell" id="data">world</div>
      <div class="cell ipsum">ipsum lorem</div>
  </div>
</div>

One possible solution could be to iterate through all the elements below the row. However, this method is quite complex as it involves not only determining the maximum height of the element but also considering its display properties (e.g., pop-up menus or nested display: contents) and position in the grid (such as spanning multiple rows with multiple cells).

Is there a simpler way to accomplish this?

Answer №1

Indeed, the Elements styled with display: contents can create a strange sensation of being both present and absent in the DOM simultaneously.

To visualize the bounds and overlaying the row with a red div:

const row = document.querySelectorAll("#firstrow > *");

const rect = [...row]
  .map(item => item.getBoundingClientRect())
  .reduce((a, b) => {
    const x = Math.min(a.left, b.left), 
      y = Math.min(a.top, b.top),
      width = Math.max(a.right, b.right) - x,
      height = Math.max(a.bottom, b.bottom) - y;

    return new DOMRectReadOnly(x, y, width, height);
  });

console.log(rect);

var cover = document.createElement("div");
document.body.append(cover);

Object.assign(cover.style, {
  position: "absolute",
  top: rect.y + "px",
  left: rect.x + "px",
  width: rect.width + "px",
  height: rect.height + "px",
  background: "#FF0000A0"
});
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}
.row {
  display: contents;
}
.row:hover div {
  background-color: lightgray;
}
.cell {
  border: 1px black solid;
  max-height: 100px;
}
.ipsum {
  height: 200px;
  max-height: 300px;
}
<div class="grid">
  <div class="row" id="firstrow">
      <div class="cell">hello</div>
      <div class="cell" id="data">world</div>
      <div class="cell ipsum">ipsum lorem</div>
  </div>
</div>

Answer №2

To achieve a consistent style for your row within the grid, consider using JavaScript to match the grid's styling, retrieve the necessary values, and then resetting the row by removing any inline styles applied.

const grid = document.querySelector('.grid');
console.log('grid:', grid.getBoundingClientRect());

const row = document.getElementById("firstrow");
row.style.gridTemplateColumns = '1fr 1fr 1fr'
row.style.display = 'grid';
console.log('row height:', row.offsetHeight);
console.log('row top:', row.offsetTop);
row.style = ''

const actual_cell = document.getElementById("data");
console.log('ipsum cell:', actual_cell.getBoundingClientRect());
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}
.row {
  display: contents;
}
.row:hover div {
  background-color: lightgray;
}
.cell {
  border: 1px black solid;
  max-height: 100px;
}
.ipsum {
  height: 200px;
  max-height: 300px;
}

* {
  margin: 0;
  box-sizing: border-box;
}
<h1>hello world</h1>
<div class="grid">
  <div class="row" id="firstrow">
      <div class="cell">hello</div>
      <div class="cell">world</div>
      <div class="cell ipsum" id="data">ipsum lorem</div>
  </div>
</div>

Answer №3

Discovering the height of a single row in pixels by analyzing the computed value of the grid-template-rows property within the grid element is achievable.
This calculated value will provide a collection of all the rows' computed heights, enabling you to extract the specific one you desire by separating the resulting string and targeting the desired index:

const big_cell = document.querySelector(".ipsum");
console.log("big_cell:", big_cell.getBoundingClientRect().height);
const small_cell = document.querySelector(".small");
console.log("small_cell:", small_cell.getBoundingClientRect().height);

const grid = document.querySelector(".grid");
document.querySelectorAll(".row").forEach((row, index) => {
  row.addEventListener("mouseenter", (evt) => {
    const computed = getComputedStyle(grid).gridTemplateRows.split("px")[index];
    console.log("current-row", computed);
  });
});
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}
.row {
  display: contents;
}
.row:hover div {
  background-color: lightgray;
}
.cell {
  border: 1px black solid;
  max-height: 100px;
}
.ipsum {
  height: 200px;
  max-height: 300px;
}
<div class="grid">
  <div class="row">
      <div class="cell">hello</div>
      <div class="cell">world</div>
      <div class="cell ipsum">ipsum lorem</div>
  </div>
  <div class="row">
      <div class="cell small">hello</div>
      <div class="cell">world</div>
      <div class="cell">ipsum lorem</div>
  </div>
  <div class="row">
      <div class="cell">hello</div>
      <div class="cell">world</div>
      <div class="cell ipsum">ipsum lorem</div>
  </div>
  <div class="row">
      <div class="cell">hello</div>
      <div class="cell">world</div>
      <div class="cell">ipsum lorem</div>
  </div>

</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

Retrieving script data from a webpage

I found a link that I want to extract content from, here is the link: https://www.whatever.com/getDescModuleAjax.htm?productId=32663684002&t=1478698394335 However, when I try to open it using Selenium, it doesn't work. It opens as plain text wit ...

Steps for positioning a div with list items to match the height of its parent container

I've been grappling with this problem for a long time now. Within the parent div "wrapper," there is a child div called "sidebar-wrapper" that contains an ul with li elements. I'm trying to make the height of "sidebar-wrapper" adjust to match t ...

Failure to connect HTML and CSS files

My HTML and CSS files are not linking even though they are in the same folder. Here is my HTML code: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatibl ...

Tips for combining or adding duplicated values in a Javascript array

I am facing a problem with an array object that looks like this: [ {"item_id":1,"name":"DOTA 2 Backpack","image":"XXX","qty":1,"original_price":1450000,"total_price":1450000}, {"item_id":2,"name":"Mobile Legend Backpack","image":"XXX","qty":1,"origin ...

Tips for ensuring the pop-up submenu remains visible even when the cursor is outside the parent container and submenu during hover

Is there a way to keep the pop submenu visible even when the mouse hovers outside of its parent container or the submenu? Currently, if the mouse doesn't move straight down from the parent container (B) .account-settings-container to the top arrow of ...

Display an image with only a portion visible, no canvas, no frame, and no need

My dilemma involves an img with a surrounding box div. http://jsfiddle.net/6d4yC/7/ 1) I am seeking to display only a portion of the image (250x150) without generating a white overlay when it is in its large size. Placing a #box1 div around the image has ...

An unsolicited border encompassing an image that does not resemble a CSS border or outline within the realm of Bootstrap 4

Utilizing Bootstrap4 Cards with .PNG image sources has resulted in an unexpected border appearing. It's not a border or outline issue. https://i.sstatic.net/KHgnP.png Here is the HTML <div class="row"> <div class="col-md-3"> <d ...

What is the best way to implement a Navbar link in React.js?

I am currently working on developing a website using Reactjs. I have successfully created a Navbar with two links - Home and Contact. However, when I click on the Contact link, although the URL changes accordingly, the page itself does not update. I have s ...

When working with JavaScript, the `textarea` value property will not recognize line breaks or white spaces when being read

Recently, I've been developing a browser-based notebook app. However, I encountered an issue where if I type a note like this: *hello this is my first note The app displays it as: hello this is my first note Additionally, I want elements with the ...

Ensure Angular JS includes a space or special character after applying a currency filter

Is there a way to include a space or special character after the "₹" symbol? Desired output: ₹ 49 Current output: ₹49 HTML - {{cart.getTotalPrice() | currency:"₹"}} ...

The web browser's engine is blocking the connection to the secure websocket server

Summary of Issue An error message stating "Websocket connection failed." appears in the browser console (Chrome or Brave) when trying to run this code: const ws = new WebSocket("wss://abcd.ngrok-free.app/") (Please note that the URL mentioned is not real ...

Utilize Google Maps API to showcase draggable marker Latitude and Longitude in distinct TextFields

I am currently utilizing the Google Maps example for Draggable markers. My objective is to showcase the latitude and longitude values within separate TextFields, where the values dynamically change as I drag the marker. Once the user stops dragging the mar ...

Problem with resizing in CSS and jQuery

I need help creating a chatbox that can be resized. I've almost got it, but the bottom part of the chatbox detaches when I resize it. Also, I'm having trouble making the userList a fixed size that won't be affected by resizing. Check out th ...

Creating a delayed queue using RxJS Observables can provide a powerful and

Imagine we have a line of true or false statements (we're not using a complicated data structure because we only want to store the order). Statements can be added to the line at any time and pace. An observer will remove items from this line and make ...

Adding a hash to asset paths in NextJS static builds

After running next build && next export, I receive a directory named out, which is great. When examining the source code, such as in the index.html file, it requests assets from <link rel="preload" href="/_next/static/css/styles.aa216922.chunk. ...

The teleport-controls feature is currently not functioning properly in VR mode with Aframe version 0.8.2

Having an issue with the teleport-controls under aframe 0.8.2. When in VR mode using Vive, only the curve appears after touching the trackpad of the controller, but the camera position does not change. However, in flat mode, both the curve and camera posit ...

Keeping an object in a multidimensional array based on its ID in Angular 4/Ionic 3 without removing it

Exploring a complex data structure: [{ propertyoutsideid: 1, items: [ {itemId: 1, something: 'something'}. {itemId: 2, something: 'something'}. {itemId: 3, something: 'something'}. ] },{ prope ...

Creating a three-column layout with position fixed in the center

I'm struggling with achieving a maximum width of 400px for the entire set of three columns and centering them. ---------------------------------------------------- | | | |----------------------------- ...

What causes my variable to show None instead of the current stock price?

I attempted to extract the stock price data from using BeautifulSoup. However, my program is not displaying the stock price and instead showing "None". How can I correctly retrieve the stock price information? My provided code snippet: from bs4 import Bea ...

Ways to Create a Text Overlay on an Image for your Banner

I have a banner div element with an image overlapping it. I'm trying to display my text without it being covered by the image, but I'm facing some challenges. Here's a visual example of the issue: https://i.stack.imgur.com/JdW75.png This ...