Home > OS >  How to style all elements that share data attribute values?
How to style all elements that share data attribute values?

Time:06-25

I have a generic table on my hands to which I've added a data attribute index with a value:

<table>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
</table>

Would it be possible to influence all elements who share the same value of data-index through css?

Something like - CSS:

td[data-index.value]:hover{
    background-color: red;
}

What I want to accomplish is that when I hover over one td element all the other td elements who share the data-index value (example all who are ="1") get styliside. I am trying to accomplish a vertical column highlight.

Sollution that relies on javascript (typescript) and react:

The way I solved it with react and typescript if someone finds this later:

const handleColumnHoverEnter = (e: any) => {
    const allWithAttribute = Array.from(
        document.querySelectorAll("[data-index='"   e.target.dataset.index   "']")
      );
      allWithAttribute.forEach((element:any) => {
        element.style.backgroundColor = 'red';
      });
  }

  const handleColumnHoverLeave = (e: any) => {
    const allWithAttribute = Array.from(
        document.querySelectorAll("[data-index='"   e.target.dataset.index   "']")
      );
      allWithAttribute.forEach((element:any) => {
        element.style.backgroundColor = 'white';
      });
  }

Thanks to users bloodyKnucklese's and t.niese's suggestions!

CodePudding user response:

You could do something like that with the :has selector (which is at the time of writing only supported by Chrome 105 and Safari 15.4 ), so not really useful right now.

Anyhow, with :has you could have a slector like table:has([data-index="1"]:hover) [data-index="1"], which means, get the table elements that contains an element [data-index="1"] that is hovered, and select all descendance of that table that match [data-index="1"]

table:has([data-index="1"]:hover) [data-index="1"] {
  background-color: red;
}

table:has([data-index="2"]:hover) [data-index="2"] {
  background-color: red;
}

table:has([data-index="3"]:hover) [data-index="3"] {
  background-color: red;
}

table:has([data-index="4"]:hover) [data-index="4"] {
  background-color: red;
}

td {
  width: 10px;
  height: 10px;
  border: 1px solid red;
}

td::before {
  content: attr(data-index);
}
<table>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
    <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
</table>

Without the support of :has you need to use JavaScript.

For this purpose you can use event delegation, which has the advantage that the data attributes and number of elements can change without the need to update the listeners.

let table = document.querySelector('table');

table.addEventListener('mouseover', (evt) => {
  if ( evt.target.matches('[data-index]') ) {
    table.dataset.hover = evt.target.dataset.index;
  }
})

table.addEventListener('mouseout', (evt) => {
  if ( evt.target.matches('[data-index]') ) {
    table.dataset.hover = 0;
  }
})
[data-hover="1"] [data-index="1"] {
  background-color: red;
}

[data-hover="2"] [data-index="2"] {
  background-color: red;
}

[data-hover="3"] [data-index="3"] {
  background-color: red;
}

[data-hover="4"] [data-index="4"] {
  background-color: red;
}

td {
  width: 10px;
  height: 10px;
  border: 1px solid red;
}

td::before {
  content: attr(data-index);
}
<table>
  <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
  <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
  <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
  <tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
</table>

CodePudding user response:

Using Javascript to add mouseover and mouseout event handlers on each element. Get the element's dataset data-index value and use that to change the background on all elements having the same value:

document.querySelectorAll("td[data-index]").forEach(di => {
  di.addEventListener("mouseover", (event) => {
    document.querySelectorAll(`td[data-index="${di.dataset.index}"]`).forEach(
      dii => { dii.style.backgroundColor = "#EEEEEE"; }
    );
  });
  di.addEventListener("mouseout", (event) => {
    document.querySelectorAll(`td[data-index="${di.dataset.index}"]`).forEach(
      dii => { dii.style.backgroundColor = "#FFFFFF";  }
    );
  });
});
<table>
    <tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
    <tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
    <tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
    <tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
</table>

CodePudding user response:

It can be done like below.

td[data-index="1"]:hover{
    background-color: red;
}
  • Related