Search code examples
javascriptcsshoverpseudo-class

not clickable but hoverable pseudo elements


I am building a star-rating element using CSS. I made a set of clickable radio buttons as pink elements. When I click these elements, all elements after them become grey, and all elements before them turn pink.

I want to set a hover on them so I set all the pinks to become grey as I hover.

The problem is that when I hover through the greys , they are already grey so nothing changes.

The solution I am trying is to set five pseudo elements on top of my radio buttons so I can set them to be pink as I hover. These pseudo elements should never be clickable so should never change from gray to pink.

The problem is that I cannot click through the pseudo elements, as they are above.

If I give all the divs for the pseudo elements pointer-events:none, there will be no hover. If I set a div to wrap these pseudo element's divs, they will hover but clicking is still not possible.

Is there a way to achieve this? A better approach maybe?

here is the code:

 * {
  padding: 0;
  margin: 0;
}

.div {
  display: flex;
  flex-direction: row;
  background: orchid;
  width: 500px;
  height: 200px;
}

.holder-wrapper {
  top: 0;
  left: 0;
  position: absolute;
  font-size: 100px;
  color: lightpink;
  display: flex;
  flex-direction: row;
  width: 500px;
  height: 200px;
  
}

input {
  appearance: none;
  font-size: 100px;
  color: lightpink;
}

input::before {
  position: relative;
  content: '\2602';
}

.holder::before {
  content: '\2601';
}

input:checked ~ ::before {
  color: #333;
}

.holder:hover ~ ::before {
  color: #333;
}
<div class="div">
  <input type="radio" data-rate="1" name="rating" class="rating--star" checked/>
  <input type="radio" data-rate="2" name="rating" class="rating--star" />
  <input type="radio" data-rate="3" name="rating" class="rating--star" />
  <input type="radio" data-rate="4" name="rating" class="rating--star" />
  <input type="radio" data-rate="5" name="rating" class="rating--star" />
  
  <div class="holder-wrapper">
    <div class="holder"></div>
    <div class="holder"></div>
    <div class="holder"></div>
    <div class="holder"></div>
    <div class="holder"></div>
  </div>
</div>

   

codepen => enter link description here

I dont understand jquery so if you want to jquery something please, explain what youre doing c:


Solution

  • * {
        padding: 0;
        margin: 0;
    }
    
    .div {
        display: flex;
        flex-direction: row;
        background: orchid;
        width: 500px;
        height: 200px;
        opacity: 1;
        
    
    }
    
    input {
        appearance: none;
        font-size: 100px;
        color: black;
    }
    input::before {
        position: relative;
        content: "\2602";
        color: black;
        opacity:1;
        transition: opacity 0.3s ease-in-out;
    }
    input:focus{
    outline:none;
    }
    input:checked ~ ::before {
        opacity:0.3
    
    }
    
    input:hover ~ ::before {
        opacity:0.2
    }
    <input type="radio" data-rate="1" name="rating" class="rating--star" checked />
    <input type="radio" data-rate="2" name="rating" class="rating--star" />
    <input type="radio" data-rate="3" name="rating" class="rating--star" />
    <input type="radio" data-rate="4" name="rating" class="rating--star" />
    <input type="radio" data-rate="5" name="rating" class="rating--star" />
    
    </div>

    I found a way. I simplified by removing the holder elements, and using opacity values to respond to hover(0.2) and click (0.3). Strange thing is the ':checked' pseudo-selector actually affects the elements to the right of the mouse. So I worked with that.

    I was going to try a JS approach but accessing pseudo elements is a nightmare!