Using SCSS to target a sibling class when hovering over an element with CSS

Is there a way to alter styles of a sibling element on hover using only CSS?

I attempted something similar but was unsuccessful.

HTML:

<ul>
   <li class="item active">name1</li>
   <li class="item">name2</li>
   <li class="item">name3</li>
   <li class="item">name4</li>
</ul>

SCSS

ul {
  padding: 0;
  margin: 0;

  li {
    cursor: pointer;
    list-style: none;
    padding: 12px 16px;

    &.active {
       background-color: $primary-blue;
       color: white;
    }

    &:hover {
       background-color: $primary-blue;
       color: white;

       ~ .active {
         background-color: white !important;
         color: black !important;
       }
    }
  }
}

I am attempting to change the style of elements on hover while simultaneously removing the style of the currently active element. The active element could be any position in the list, up to 10 elements. This example has been simplified for clarity.

EDIT! IMPORTANT! I have noticed some confusion regarding my request, I hope this plunker will help clarify things :)

https://plnkr.co/edit/RQy04Qv1zy0nukhnlN82

Answer №1

To achieve the desired layout using only CSS, utilize the order property in combination with Flexbox or Grid:

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
}

li {
  cursor: pointer;
  list-style: none;
  padding: 12px 16px;
}
 
li:last-child {
  order: -1; /* rearranged to maintain layout */
}
 
.active {
  background-color: blue;
  color: white;
}

li:hover {
  background-color: blue;
  color: white;
}

li:hover ~ .active {
  background-color: white;
  color: black;
}
<ul>
 <li class="item">name2</li>
 <li class="item">name3</li>
 <li class="item">name4</li>
 <li class="item active">name1</li> <!-- must be placed last for ~ selector functionality -->
</ul>

Answer №2

"My goal is to be able to hover over any element and apply specific styles, while also hiding the active element's style. The active element could be any of the elements in a list of up to 10 items."


Achieving this behavior with CSS alone is possible, however, it requires a layout change as complex interactions using pure CSS involve:

  1. Precise positioning of elements in relation to others, considering parent-child relationships and cascading rules that impact inheritance.

  2. The requirement for unique attributes and default behaviors for certain element groups, types, or tags. Simply applying CSS to a list won't suffice to achieve the desired behavior.

Layout

  1. <input id='chx0' type="checkbox" hidden='true'>
    act as invisible switches controlling the state (specific styles) of other elements. When a checkbox is :checked, all affected elements enter an active state.

  2. <label id='btn0' for='chx0'></label>
    are buttons triggering the associated checkbox via the attribute: for= "chx0"

  3. Due to cascading nature of CSS rules, only sibling elements following the checkboxes can be styled – which essentially includes any next sibling down the DOM tree along with its children/descendants. Think of it like a family hierarchy:

    Previous-Element-Sibling <section>Elder Brother</section>

    Reference Point 🢂

    <input id='chx0' type='checkbox'>

    Next-Element-Sibling <li>Younger Brother</li>

    You can target your younger brother but not your older brother.

  4. In Demo 2, there are two checkbox-label pairs:

    • ACTIVE / INACTIVE controls the behavior of the .active element.

    • ORDER / CHAOS changes the order of <dd> elements (optional and added for demonstration).


While I'm not familiar with SCSS, it appears that you aim to modify the style of sibling elements. However, the general sibling combinator ~ seems to work but lacks the desired effect: white background with black text. In this demo, the adjacent sibling combinator + is used with inverted colors for better visibility of changes.

Demo 1

ul {
  padding: 0;
  margin: 0;
}

li {
  cursor: pointer;
  list-style: none;
  padding: 12px 16px;
}

li.active {
  background-color: blue;
  color: white;
}

li:hover {
  background-color: blue;
  color: white;
}

li:hover+li {
  background-color: black !important;
  color: white !important;
}
<ul>
  <li class="item active">name1</li>
  <li class="item">name2</li>
  <li class="item">name3</li>
  <li class="item">name4</li>
</ul>

Demo 2

.dataList {
  display: flex;
  flex-flow: column nowrap;
}

.btn {
  background: rgba(0, 0, 0, 0);
  padding: 3px 5px;
  margin: 20px 0 -15px 30px;
  border: 2px ridge grey;
  border-radius: 4px;
  cursor: pointer;
  display: inline-block;
  width: 12ch;
  text-align: center;
}

#btn0::before {
  content: 'ACTIVE';
  color: green;
}

#chx0:checked~#btn0::before {
  content: 'INACTIVE';
  color: tomato;
}

#btn1::before {
  content: 'ORDER';
  color: blue;
}

#chx1:checked~#btn1::before {
  content: 'CHAOS';
  color: orange;
}

#chx1:checked~.dataList dd:nth-of-type(1) {
  order: 8
}

#chx1:checked~.dataList dd:nth-of-type(2) {
  order: 5
}

#chx1:checked~.dataList dd:nth-of-type(3) {
  order: 6
}

#chx1:checked~.dataList dd:nth-of-type(4) {
  order: 10
}

#chx1:checked~.dataList dd:nth-of-type(5) {
  order: 3
}

#chx1:checked~.dataList dd:nth-of-type(6) {
  order: 2
}

#chx1:checked~.dataList dd:nth-of-type(7) {
  order: 4
}

#chx1:checked~.dataList dd:nth-of-type(8) {
  order: 1
}

#chx1:checked~.dataList dd:nth-of-type(9) {
  order: 7
}

#chx1:checked~.dataList dd:nth-of-type(10) {
  order: 9
}

.data {
  color: white;
  background: rgba(0, 0, 0, 0.8);
  border: 2px inset white;
  padding: 3px 5px
}

.active {
  color: gold;
  border: 2px ridge gold;
  background: rgba(0, 0, 0, 1);
}

.active::after {
  content: ' is ACTIVE';
  font-weight: 900;
}

#chx0:checked~.dataList:hover .data.active {
  border: 2px inset white;
  color: white;
  background: rgba(0, 0, 0, 0.8);
}

#chx0:checked~.dataList:hover .active::after {
  content: '';
  font-weight: normal;
}

.data:hover {
  color: #000;
  background: #fff;
}

.data.active:hover {
  color: lime;
  border-color: lime;
  background: #000;
}

#chx0:checked~.dataList .data.active:hover {
  color: #000;
  background: #fff;
}

.data.hovered {
  color: yellow;
}
<input id='chx0' type='checkbox' hidden='true'>
<input id='chx1' type='checkbox' hidden='true'>

<label id='btn0' class='btn' for='chx0'></label>
<label id='btn1' class='btn' for='chx1'></label>

<dl class='dataList'>
  <dt class='data term'>DATA LIST</dt>
  <dd class='data'>ITEM 0</dd>
  <dd class='data'>ITEM 1</dd>
  <dd class='data'>ITEM 2</dd>
  <dd class='data'>ITEM 3</dd>
  <dd class='data active'>ITEM 4</dd>
  <dd class='data'>ITEM 5</dd>
  <dd class='data'>ITEM 6</dd>
  <dd class='data'>ITEM 7</dd>
  <dd class='data'>ITEM 8</dd>
  <dd class='data'>ITEM 9</dd>
</dl>

Answer №3

It seems that including the ampersand in the active selector may be necessary, like this:

li {
    cursor: pointer;
    list-style: none;
    padding: 12px 16px;

    &.active {
       background-color: $primary-blue;
       color: white;
    }

    &:hover {
       background-color: $primary-blue;
       color: white;

       ~ &.active {
         background-color: white !important;
         color: black !important;
       }
    }
  }

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

Expanding list item with jQuery

I am facing an issue with the dropdown functionality of my <li> elements. The problem occurs when clicking on the 4th option, as the expander appears on top instead of dropping down beneath the list item. If you check out this jsFiddle, you can see ...

Why is my AngularJS application triggering two events with a single click?

<button id="voterListSearchButton" class="serachButton" ng-click="onSearchButton1Click()">find</button> This button allows users to search for specific information: $scope.onSearchButton1Click = function() { var partId = $("#partIdSearch" ...

A step-by-step guide on initializing and setting a cookie value with expiration

Below is the code I have added. Can someone please help me locate the bug? Here is the code snippet: $_SESSION['browser'] = session_id(); setcookie($expire, $_SESSION['browser'], time() + (60 * 1000), "/"); echo "Value is: " . $_COO ...

Refresh a row in real-time by utilizing a modal with JavaScript or jQuery

Is there a way to dynamically edit and update a previously submitted row (category name) in a table? I am able to edit a row by clicking on an edit button and displaying a modal with the current value. However, I am facing a challenge when trying to submit ...

What is the best way to ensure grid element takes up 100% of the available height within a flex column

I am working with this HTML structure: https://i.stack.imgur.com/fy5Yz.png My goal is to have the .SceneWithHistory-Container take up 100% of the available height in its parent element. Below is my CSS code: .Module-Container margin-top: 120px; displ ...

Customize WordPress pages by adding a variety of unique logos for a

I am currently customizing a WordPress theme (Increate themes) for a client. They are looking to have a page with different content and a unique logo. My question is, how can I change the logo specifically for this page? This is the section of code in my ...

Scrapy and Python data gets corrupted by <br> tags causing issues

As I attempt to extract the text from Amazon reviews using scrapy, I encounter an issue. Reviews with multiple lines have their text separated by "< br >" tags within a span element. So, when I try to scrape the first review, I use this line of code: r ...

When clicking on a different tab, the Bootstrap tab will shift to the left, outlining the new selection

While working with Bootstrap, I created a small footer with a tab. However, whenever I click on the second value, the entire div shifts to the left. How can I keep it in place? Below is my code along with two images depicting how the first tab aligns corr ...

Issue with JQuery's click and submit events not triggering, but change event is working fine

My webpage has a dynamic DOM that includes add and save buttons to interact with elements. Each row also has a remove option for deletion. When a user logs in, the controller redirects them to their homepage in the codeigniter PHP framework. This controlle ...

Task: Choose MySQL option and Retrieve JSON data

I have a question regarding implementing a function in a separate module file and calling it within a route to retrieve query data: function getSobre() { return new Promise((resolve, reject) => { db.query(`SELECT * FROM sobre ORDER BY cod ...

In what ways can the current theme be utilized to optimize spacing?

Greetings everyone, I need assistance with adding margins above and below a Button element. Below is the relevant code snippet: const useStyles = makeStyles(() => ({ progress: { display: 'block', margin: 'auto', }, })); ...

I am attempting to add user input to the parent container when the button is clicked, but for some reason it is

Recently delving into jquery, I attempted to dynamically add an input field to a parent div on button click, but encountered some difficulties. Specifically, my goal was to insert a div with an input element into the parent div identified by the id "join ...

The styling for buttons links is malfunctioning

I am currently developing my own version of Bootstrap and focusing on buttons and links. I have anchor tags within the button element, but the link styling is not displaying correctly. HTML <button class="btn-danger"><a href="#">Danger</a& ...

Is it possible to place a secondary read more button next to the first one using CSS?

If you notice the code snippet, you will see that a "read more" button appears. How can I add another "read more" button to align side by side? I may even want to include three "read more" buttons, each opening in a separate modal box. ...

Challenges arise when using two side-by divs with a 100% height

Caution: This page may include NSFW images. I am attempting to set the left div to a width of 300px and have the right one fill the remaining space on the page. After finally getting them to sit side by side, I encountered some strange height issues due ...

Display HTML content generated by JavaScript in the page source

Can the HTML elements I've added through JavaScript and jQuery codes be displayed in the page source (ctrl+U)? ...

A straightforward jQuery conditional statement for dynamically generated content

If the div '#ajax' contains content, I want to make the div '.container' clickable. Here is the basic jQuery script I have implemented: if ('#ajax:empty') { $('.container').css('pointer-events', ' ...

Activate the preview mode by transmitting information between two controllers

I'm trying to set up a preview mode in one controller to show an image in another controller using an angular service. However, I'm struggling with the final step of getting the URL from the passed parameter into the ng-src in SideMenuCtrl dynami ...

illuminate selected row in datatable using a jquery plugin

My data is displayed using the jQuery plugin DataTable, and everything appears to be working well. I am retrieving my data from PHP using AJAX. However, I encountered an issue when trying to highlight the row that was hovered over while navigating around ...

Updating the text of an element will occur only when the specified condition has been met

I am trying to dynamically change the text within the <span data-testid="recapItemPrice">ZADARMO</span> element from 'ZADARMO' to 'DOHODOU' only when the text inside the parent element 'INDIVIDUÁLNA CENA PREP ...