What techniques can I use to change multiple sibling elements with CSS when hovering over them?

Imagine a scenario where hovering over any row within group 1 changes the color of all rows within that same group. Now, extend this concept to apply to an unlimited number of groups, denoted by N.

Let's consider having 300 groups, each consisting of 3 rows. How can we implement this highlighting effect for every group without manually duplicating the CSS rule 300 times?

Is it feasible to achieve this purely with 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>

Answer №1

If you find yourself unable to modify the HTML structure to group elements together, you can dynamically generate your CSS rules to avoid manual typing.

// Select all elements with a class containing 'group-'
const allElements = document.querySelectorAll('p[class*="group-"]')

// Extract classNames from the elements
const allClassNames = Array.from(allElements).map(({
  className
}) => className);

// Remove duplicates
const groupings = new Set(allClassNames);

// Construct the selectors
const selectors = Array.from(groupings.values()).map(className => `.parent:has(.${className}:hover) .${className}`).join(",")

// Define the CSS styles for the rule
const theStyles = 'background-color: blue;'

// Create a stylesheet element
const styleEl = document.createElement("style");

// Append it to the head of the document
document.head.appendChild(styleEl);

// Access the stylesheet
const styleSheet = styleEl.sheet;

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

Answer №2

If you are certain that each group consists of exactly 3 entries, you can implement a solution using nth-child, before pseudo element (for holding the background), and z-index.

This code snippet limits the hover effect to the first element in a group while giving the user the impression that they are hovering over the entire group. This is achieved by using a before pseudo element on the first element that overlays 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>

On a side note: implementing this approach in practice may not be ideal. While it does achieve the desired highlighting effect, some may consider it to be a bit hacky. An alternative solution using JavaScript could make the functionality clearer and easier to maintain.

Answer №3

It seems that achieving this effect solely with CSS is currently not possible, but a simple JavaScript solution can be implemented by assigning a common data attribute to all members of the group. This way, when hovering over one member, all members will receive a data-active attribute.

Your CSS code can then target 'all items with [data-attr] as if they are hovered':

p[data-active] {background:blue;}

While I may not excel in JavaScript, it's plausible that there are ways to refine this method. Nonetheless, this approach is concise and does not necessitate modifications to the HTML or any dynamic CSS generation.

Check out this demo:

document.querySelectorAll(".parent p")
  .forEach(p => addListeners(p));

function addListeners(p){
  p.addEventListener("mouseover", select);
  p.addEventListener("mouseout", deselect);
}

function select(){
  document.querySelectorAll("p."+this.className)
    .forEach(p => p.setAttribute("data-active",""));
}

function deselect(){
  document.querySelectorAll("p."+this.className)
    .forEach(p => p.removeAttribute("data-active"));
}
p {margin:0}
p[data-active] {
background:blue;
}
<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-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-3">Group 3</p>
  <p class="group-3">Group 3</p>
</div>

Answer №4

Aside from their specific class names, each of them can be assigned an additional class name. Furthermore, if you implement the following:

.parent > *{}

This selector allows you to target all children of the parent/body element. You can also style all <p></p> elements by using the <p></p> tags specifically.

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

Show information from mysql in a dual-column format

I am pulling data from a single table in mysql, currently displaying it in one column. I want the data to be displayed in two columns next to each other. You can check out the results at www.urimsopa.com Here is my current code: $results = $mysqli->qu ...

unable to interpret information

I've encountered an issue with posting data to my webpage (page3.php). Despite using $test=$_POST['radio_second']; on the page, the test variable remains empty. Any help in resolving this would be greatly appreciated. Thank you! <p> ...

Expanding a non-bootstrap navigation bar upon clicking the menu

I'm having some difficulty getting my navigation menu to show up when I click the navigation menu icon. HTML nav role="navigation" class="navbar"> <div class="nav-header"> <a href="#"><span style="font-family: 'Cab ...

Issues with creating modal images using only JavaScript

I am facing an issue with modal popup images. I have a collection of images and attempted to implement this code (with some modifications): https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_modal_img However, it seems to only work for the initi ...

Achieve perfect alignment of Bootstrap checkboxes

Is there a way to vertically align checkboxes in a column with their labels? My goal is to have these elements centered on the page, but I want the checkboxes themselves to be aligned vertically. <div class="row"> <div class="span12 paginatio ...

Difficulty in making Materialize.css column match the height of the entire row

Utilizing React.js, Materialize.css, and certain MaterialUI components in collaboration to build a website. Developed a header (React component, basic div with title and logout button) for the site using a Materialize.css "grid". Issue: The react compone ...

Is there a way to access an SD card by clicking on an HTML link using JavaScript?

UPDATE: I am seeking a way to embed an HTML file with JavaScript or jQuery that can directly access the contents of the SD card while being opened in a browser. Currently, I have posted code for accessing it through an activity, but I want to be able to d ...

Placing 2 elements next to each other - Where the left element remains static and the right element's width increases as the page expands

Hey there! I'm really struggling to position two elements, an aside and a section (I believe the use of these HTML5 elements is important for their content). On this page Click Here, my goal is to keep the 'Locations' (Aside) element static ...

Expanding image in table data to full screen upon clicking using jQuery

I am trying to display an image in my table and then use jQuery to pop up a modal with the full-screen image. However, the image only pops up at the top of the table data. This is the code I have so far: <tbody> <tr> <td><?php ...

When the enter key is pressed, the form will be automatically submitted

My current implementation includes the utilization of Bootstrap input tags as shown below: myPage.html <form th:object="${field}" name="modal" method="post" th:action="@{/ajouterFieldEcran}"> ... <div class="form-group row"> <label ...

Various instances of the jQuery niceScroll plugin

I successfully set up jQuery niceScroll on the body, but now I want different themed scrollbars on one page. Below is my code snippet: Here is my fiddle: http://jsfiddle.net/JPA4R/135/ <script> $(document).ready(function () { $("body").niceScroll ...

Is there a way to ensure a Bootstrap grid column takes up the entire remaining row space?

I have a dynamic set of elements that need to be inserted into a page, with some elements being labeled as "small" and others as "big". The challenge is that I do not know in advance the quantity or order of these elements. If an element is labeled "small ...

Troubleshooting issue: Angular not resolving controller dependency in nested route when used with requirejs

When the routes are multiple levels, such as http://www.example.com/profile/view, the RequireJS is failing to resolve dependencies properly. However, if the route is just http://www.example.com/view, the controller dependency is resolved correctly. Below ...

What is the proper method for storing user registration information in the database so that it can be easily retrieved and accessed later? (Error message)

User.cs: An error is occurring in the User class where 'User' is not a valid type in the context of TestBlazor project. It happened when attempting to save user registration data. using System; using System.Collections.Generic; using S ...

I'm a bit uncertain about the best placement for my progress bar component during the API call

Trying to grasp material ui I managed to implement the progress bar. Struggling with loading it until my data is fully loaded. Uncertain about where to place my progress bar component. Could you guide me on how to resolve this issue during API calls, so I ...

Pass information from a row to an AngularJS controller upon clicking the checkbox within the row

I need help with some HTML code that utilizes AngularJS to display a table. Each row in this table contains a checkbox. Here is a snapshot of the table layout: https://i.sstatic.net/ibDor.jpg Below is the actual HTML code: <div ng-app ng-controll ...

What is the functionality of 'min-height: 100vh' when child elements stack due to a small width?

In a parent element, I have two child elements: <div id="registration"> <div id="left-panel"></div> <div id="right-panel"></div> </div> The styling is as follows: #registration{ @include l { flex-dire ...

HTML filtering using the <select> element

Is there a way to implement this script for options instead of buttons? The goal is to filter the HTML section, but it seems to not work with <option> tags. Instead of displaying the all class, it shows nothing. CSS .show { display: block; } .filt ...

What is the proper way to eliminate the port from a URL so that the images sourced from the XAMPP database can function correctly?

I am a beginner in Angular and I am facing an issue with Angular and XAMPP. I am attempting to load images from mySQL database where I stored their destinations. The problem is that Angular is trying to access that destination through this link: https://i ...

Formatting text and images in CSS

Looking to align images at the bottom of each column in a div with 3 columns, but struggling due to varying text lengths. Any tips on how to achieve this? https://i.sstatic.net/fuPgl.png Thank you, Carolin #content_row{ margin-top:150px; marg ...