skip to Main Content

In the example below when we hover any row from group 1, all group 1 rows change colour. I want to apply this same logic for N number of groups.

Let’s say we have 300 of these groups of 3 rows. How can we achiveve this highlighting for each group without copy and pasting the CSS rule 300 times.

Can this be achieved with pure css?

.parent:has(.group-1:hover) .group-1 {
  background-color: blue;
}
<body class="parent">
  <p class="group-1">Group 1</p>
  <p class="group-1">Group 1</p>
  <p class="group-1">Group 1</p>
  <p class="group-2">Group 2</p>
  <p class="group-2">Group 2</p>
  <p class="group-2">Group 2</p>
  <p class="group-3">Group 3</p>
  <p class="group-3">Group 3</p>
  <p class="group-3">Group 3</p>
</body>

3

Answers


  1. you can give all of them 1 more class name besides their specific class names.
    and also if you can do this:

    .parent > *{}
    

    this selection, let you select all of the parent/body children.
    you can also select all <p></p> element if you have use <p></p> tag just here.

    Login or Signup to reply.
  2. Well if you can not alter the HTML to make them wrapped in groups, you can dynamically create your CSS so you are not manually writing out all the rules.

    // get all the elements with the group class
    const allElements = document.querySelectorAll('p[class*="group-"]')
    
    // get all the classNames from the elements
    const allClassNames = Array.from(allElements).map(({
      className
    }) => className);
    
    // de-dupe
    const groupings = new Set(allClassNames);
    
    // build the selectors
    const selectors = Array.from(groupings.values()).map(className => `.parent:has(.${className}:hover) .${className}`).join(",")
    
    // your CSS you want to be in the rule
    const theStyles = 'background-color: blue;'
    
    // make a stylesheet
    const styleEl = document.createElement("style");
    
    // add it to the document
    document.head.appendChild(styleEl);
    
    //get the sheet
    const styleSheet = styleEl.sheet;
    
    //create the new rule
    styleSheet.insertRule(`${selectors}{${theStyles}}`, 0);
    P {
      margin: 0; padding: 0;
    }
    <div class="parent">
      <p class="group-1">Group 1</p>
      <p class="group-1">Group 1</p>
      <p class="group-1">Group 1</p>
      <p class="group-2">Group 2</p>
      <p class="group-2">Group 2</p>
      <p class="group-2">Group 2</p>
      <p class="group-3">Group 3</p>
      <p class="group-3">Group 3</p>
      <p class="group-3">Group 3</p>
    </div>
    Login or Signup to reply.
  3. If you definitely know that each group has exactly 3 entries you can use a combination of nth-child, before pseudo element (to hold the background) and z-index.

    This snippet confines the hover to the first element in a group, but it appears to the user that they are hovering on the group in general as it is a before pseudo element on the first element that is overlaying the others in the group.

    <style>
      .parent {
        overflow: hidden;
      }
      
      .parent>p {
        width: 100%;
        display: inline-block;
        position: relative;
      }
      
      .parent>p:nth-child(3n-2) {
        z-index: 1;
      }
      
      .parent>p:nth-child(3n-2)::before {
        content: '';
        background: transparent;
        position: absolute;
        width: 100%;
        height: 100vw;
      }
      
      .parent>p:nth-child(3n-2):hover::before {
        background: yellow;
        z-index: -1;
      }
      
      .parent>p:nth-child(3n-2):hover~p:nth-child(3n-2) {
        z-index: 2;
        background: white;
      }
      
      .parent>p:nth-child(3n-2):hover~p:nth-child(3n-2)+p,
      .parent>p:nth-child(3n-2):hover~p:nth-child(3n-2)+p+p {
        z-index: 3;
        rbackground: white;
      }
      
      .parent>p:nth-child(3n-2):hover~p:nth-child(3n-2)::before {
        z-index: -1;
        background: white;
      }
      
      .parent>p:nth-child(3n-2):hover+p,
      .parent>p:nth-child(3n-2):hover+p+p {
        z-index: 2;
      }
      
      .parent>p:nth-child(3n-1),
      .parent>p:nth-child(3n) {
        pointer-events: none;
      }
    </style>
    
    <body>
      <div class="parent">
        <p class="group-1">Group 1</p>
        <p class="group-1">Group 1</p>
        <p class="group-1">Group 1</p>
        <p class="group-2">Group 2</p>
        <p class="group-2">Group 2</p>
        <p class="group-2">Group 2</p>
        <p class="group-3">Group 3</p>
        <p class="group-3">Group 3</p>
        <p class="group-3">Group 3</p>
        <p class="group-4">Group 4</p>
        <p class="group-4">Group 4</p>
        <p class="group-4">Group 4</p>
        <p class="group-5">Group 5</p>
        <p class="group-5">Group 5</p>
        <p class="group-5">Group 5</p>
      </div>
    </body>

    Aside: whether you would actually want to do this in practice is another matter. While it does achieve the highlighting, it is IMO a bit hacky and I’d probably go for a bit of JS just to make it more obvious what is going on ie. simpler to maintain.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search