CSS Select All Previous Siblings for a Star Rating

CSS select all previous siblings for a star rating

// obtain all spans from DOM
const spans = document.querySelectorAll('span');
// set a variable at global scope as indicator
let flag = false;

// add event listener to each span
spans.forEach((sp, j)=>{
sp.addEventListener('click', ()=>{
// if clicked, then not dismissing the background colour after mouse leave
flag = true;
// reassign all spans back to original grey
spans.forEach(dsp=>{
dsp.style.backgroundColor = '#eee';
});
// assign bg to red of the spans from 0 to clicked index
Array.from(new Array(j+1), (x, i) => i).forEach(ind=>{
spans[ind].style.backgroundColor = 'red';
});
});
// redo if mouse enters
sp.addEventListener('mouseenter', ()=>{
flag = false;
});
// if any span is hovered
sp.addEventListener('mouseover', ()=>{
// reassign all spans back to original grey
spans.forEach(dsp=>{
dsp.style.backgroundColor = '#eee';
});
// assign bg to red of the spans from 0 to clicked index
Array.from(new Array(j+1), (x, i) => i).forEach(ind=>{
spans[ind].style.backgroundColor = 'red';
});
});
// in moseleave, only save the background colour if click happened
sp.addEventListener('mouseleave', ()=>{
if(!flag){
spans.forEach(dsp=>{
dsp.style.backgroundColor = '#eee';
});
}
});
});
span {
display:inline-block;
width: 32px;
height: 32px;
background-color:#eee;
}

span:hover {
background-color:red;
opacity: 0.8;
cursor: pointer;
}
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>

Is there a previous sibling selector?

No, there is no "previous sibling" selector.

On a related note, ~ is for general successor sibling (meaning the element comes after this one, but not necessarily immediately after) and is a CSS3 selector. + is for next sibling and is CSS2.1.

See Adjacent sibling combinator from Selectors Level 3 and 5.7 Adjacent sibling selectors from Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification.

Multiple colors of previous silbing selector

If you are open to reversing the order of your items in the HTML this is fairly simple to do as you can use :nth-child(n) along with the ~ to color your items. The only downside is that the CSS gets a bit lengthy.

.stars {  display: flex;  flex-direction: row-reverse;  cursor: pointer;  width: 230px;  background: black;  color: white;}
.star { padding: 5px;}
.star:nth-child(5):hover,.star:nth-child(5):hover ~ .star { color: red;}
.star:nth-child(4):hover,.star:nth-child(4):hover ~ .star { color: blue;}
.star:nth-child(3):hover,.star:nth-child(3):hover ~ .star { color: green;}
.star:nth-child(2):hover,.star:nth-child(2):hover ~ .star { color: orange;}
.star:nth-child(1):hover,.star:nth-child(1):hover ~ .star { color: yellow;}
<div class="stars">  <span class="star">ICO5</span>  <span class="star">ICO4</span>  <span class="star">ICO3</span>  <span class="star">ICO2</span>  <span class="star">ICO1</span></div>

Sibling selectors and first-of-type don't work when I try to select the first ul element after a prior one

Using nth-of-type that scales with each ul works

[1, 3, 5, 7, 9, 12, 15].forEach((level, index) => $$('div#main-content > ul')[index].innerHTML = [].map.call(['blue', 'green', 'orange', 'red'].flatMap(colour => $$('#invocations-level-'+level+' ~ ul:nth-of-type('+(index+1)+') li a.rating-' + colour)), function(el) {
return el.parentElement.outerHTML;
}));

It looks like ul:nth-of-type('+(index+1) is needed, because it's never the nth-of-type that's a sibling of #invocations-level-* but in the selected parent's children. This makes sense when you remember a CSS rule is read right-to-left, so the ~ has to be evaluated after nth-of-type.

CSS hover on the elements before

You could create this with Flexbox and change order of elements with flex-direction: row-reverse. You can also use ~ general sibling selector to select all sibling elements that come after hovered element .

.rating {  display: inline-flex;  flex-direction: row-reverse;}i {  width: 20px;  height: 20px;  margin: 5px;  border: 1px solid black;  transition: all 0.3s ease-in;}i:hover ~ i,i:hover {  background: black;}
<div class="rating">  <i id="minStar1" class="fa fa-star fa-lg" aria-hidden="true"></i>  <i id="minStar2" class="fa fa-star fa-lg" aria-hidden="true"></i>  <i id="minStar3" class="fa fa-star fa-lg" aria-hidden="true"></i>  <i id="minStar4" class="fa fa-star fa-lg" aria-hidden="true"></i>  <i id="minStar5" class="fa fa-star fa-lg" aria-hidden="true"></i></div>

CSS for star rating system

I think you want this: http://jsfiddle.net/AAgU9/4/

You're using your selectors incorrectly. .st1:hover .stf will target descendants of .st1:hover with a class of stf. You have no such elements.

Instead, you want to look at siblings and, specifically, you want to use ~ which targets siblings that come after some element, meaning something like #someElem ~ div would select all div elements that are siblings of #someElem but also come after it.

So, just re-order your HTML:

<div style="position:relative">
<div class="stb"></div>
<div class="sts st1"></div>
<div class="sts st2"></div>
<div class="sts st3"></div>
<div class="sts st4"></div>
<div class="sts st5"></div>
<div class="stf"></div>
</div>

and use ~ in your css:

.st1:hover ~ .stf {
width: 28px;
}
.st2:hover ~ .stf {
width:56px;
}
.st3:hover ~ .stf {
width:84px;
}
.st4:hover ~ .stf {
width:112px;
}
.st5:hover ~ .stf {
width:140px;
}

some readin': http://css-tricks.com/child-and-sibling-selectors/

CSS selectors for radio buttons previous to one checked

CSS Approach:

With CSS only, you can use flexbox.

  • Use flex-direction: row-reverse;

    row-reverse: Behaves the same as row but the main-start and main-end points are permuted.

  • Use the general sibling selector.

    The ~ combinator separates two selectors and matches the second
    element only if it is preceded by the first, and both share a common
    parent.


#review-form .star-rating {
display: inline-flex;
flex-direction: row-reverse;
}

#review-form input[type=radio] + .label_star::before {
content: "\f006";
/* Radio Unchecked */
}

#review-form input[type=radio]:checked ~ .label_star::before {
content: "\f005";
/* Radio Checked */
}

#review-form .star-rating {  display: inline-flex;  flex-direction: row-reverse;}#review-form input,#review-form textarea {  background: none repeat scroll 0 0 #333333;  border: 0 none;  color: #fff;  margin: 0;  max-width: 100%;  padding: 7px 4px;}#review-form .radio {  display: inline-block;}#review-form input[type=radio] {  display: none;}#review-form input[type=radio] + label {  display: block;}#review-form input[type='radio'] + .label_star:before {  display: inline-block;  font-family: FontAwesome;  font-style: normal;  font-weight: normal;  line-height: 1;  -webkit-font-smoothing: antialiased;  -moz-osx-font-smoothing: grayscale;  //padding-right: 8px;  width: 23px;}#review-form input[type=radio] + .label_star::before {  content: "\f006";  /* Radio Unchecked */}#review-form input[type=radio]:checked ~ .label_star::before {  content: "\f005";  /* Radio Checked */}
<link href="//netdna.bootstrapcdn.com/font-awesome/3.0/css/font-awesome.css" rel="stylesheet" /><div class="form-group" id="review-form">  <label id="rating" for="rating">RATING</label>  <span class="star-rating star-5">  <input type="radio" id="option5" name="star-radios" value="5">  <label class="label_star" id="option5_label" for="option5"></label>  <input type="radio" id="option4" name="star-radios" value="4">  <label class="label_star" id="option4_label" for="option4"></label>  <input type="radio" id="option3" name="star-radios" value="3">  <label class="label_star" id="option3_label" for="option3"></label>  <input type="radio" id="option2" name="star-radios" value="2">  <label class="label_star" id="option2_label" for="option2"></label>  <input type="radio" id="option1" name="star-radios" value="1">  <label class="label_star" id="option1_label" for="option1"></label></span></div>


Related Topics



Leave a reply



Submit