0

i have to create a progressbar timeline using html and css.Here is the snapshot of output: Output current Currently it is static on 4th number with all previous highlighted. what i want is that when user hover over 3 or 4 or any digit then all previous including current become active, i tried it but not yet success. here is my JSFiddle:https://jsfiddle.net/4ypjufmo/1/ Any Help is highly appreciated

    @import "compass/css3";
 li {
     width: 2em;
     height: 2em;
     text-align: center;
     line-height: 2em;
     border-radius: 1em;
     background: dodgerblue;
     margin: 0 1em;
     display: inline-block;
     color: white;
     position: relative;
}
 li::before {
     content: '';
     position: absolute;
     top: 0.9em;
     left: -4em;
     width: 4em;
     height: 0.2em;
     background: dodgerblue;
     z-index: -1;
}
 li:first-child::before {
     display: none;
}
 .active {
     background: dodgerblue;
}
 .active ~ li {
     background: lightblue;
}
 .active ~ li::before {
     background: lightblue;
}
 body {
     font-family: sans-serif;
     padding: 2em;
}
kate elly
  • 67
  • 9
  • `.active ~ li` will not select the preceding elements. You can use this hack though: https://stackoverflow.com/a/36118012/4813913 – m4n0 Oct 19 '20 at 05:04
  • I can't think of an elegant way but you may be able to bruteforce this by giving each number a hover state where it styles the numbers before. – Ale Plo Oct 19 '20 at 05:06

4 Answers4

1

This method uses javascript to recognize which item has the mouseover and then adds the active class to all the ones prior. Those elements will retain their active class until an element is moused over that would cause the active class to be removed.

Note that I also added data attributes to your <li> elements to make it a little easier to process them:

let liArray = document.querySelectorAll("li");
liArray.forEach( (element) => 
   element.addEventListener("mouseover",
        function( event ) {   
        doHighlights(+event.target.dataset.step);
    }
));

function doHighlights(inStep) {
   let liArray = document.querySelectorAll("li");
   //console.log(inStep);
   liArray.forEach( (element) => {
      //console.log(+element.dataset.step, inStep);
        if (+element.dataset.step <= inStep) {
        element.classList.add("active");
      } else {
         element.classList.remove("active");
      }
   })
}
@import "compass/css3";

li {
  width: 2em;
  height: 2em;
  text-align: center;
  line-height: 2em;
  border-radius: 1em;
  background: lightblue;
  margin: 0 1em;
  display: inline-block;
  color: white;
  position: relative;
}

li::before {
  content: '';
  position: absolute;
  top: 0.9em;
  left: -4em;
  width: 4em;
  height: 0.2em;
  background: lightblue;
  z-index: -1;
}

li.active::before {
  background: dodgerblue;
}

li:first-child::before {
  display: none;
}

li.active {
  background: dodgerblue;
}
body {
     font-family: sans-serif;
     padding: 2em;
}

/*
 .active ~ li {
     background: lightblue;
}
 .active ~ li::before {
     background: lightblue;
}
*/
/*
li:hover {
  background: dodgerblue;
}
*/
<ul>
  <li data-step="1">1</li>
  <li data-step="2">2</li>
  <li data-step="3">3</li>
  <li data-step="4">4</li>
  <li data-step="5">5</li>
  <li data-step="6">6</li>
  <li data-step="7">7</li>
</ul>  

(JSFiddle version here: https://jsfiddle.net/79hwa6s4/)

Marc
  • 11,403
  • 2
  • 35
  • 45
0

That's easy! All you have to do is remove active (Class) from the li tag in the HTML file and replace .active with li:hover in the CSS file.

JSFiddle :: https://jsfiddle.net/chbej806/2/


Changes

=> HTML

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
</ul>  

=> CSS

@import "compass/css3";
 li {
     width: 2em;
     height: 2em;
     text-align: center;
     line-height: 2em;
     border-radius: 1em;
     background: dodgerblue;
     margin: 0 1em;
     display: inline-block;
     color: white;
     position: relative;
}
 li::before {
     content: '';
     position: absolute;
     top: 0.9em;
     left: -4em;
     width: 4em;
     height: 0.2em;
     background: dodgerblue;
     z-index: -1;
}
 li:first-child::before {
     display: none;
}
 li:hover{
     background: dodgerblue;
   cursor: pointer;
}
 li:hover ~ li {
     background: lightblue;
}
 li:hover ~ li::before {
     background: lightblue;
}
 body {
     font-family: sans-serif;
     padding: 2em;
}
Partha Maity
  • 156
  • 4
0

activeIndex = -1;
$("#my-progress li").each(function(index){
  if($(this).hasClass("active"))
    activeIndex = index;
})
$("#my-progress li").mouseover(function(index){
  $("#my-progress li").removeClass("active");
  $(this).addClass("active");
})
$("#my-progress li").mouseout(function(index){
  $("#my-progress li").removeClass("active");
  $($("#my-progress li")[activeIndex]).addClass("active");
})
li {
     width: 2em;
     height: 2em;
     text-align: center;
     line-height: 2em;
     border-radius: 1em;
     background: dodgerblue;
     margin: 0 1em;
     display: inline-block;
     color: white;
     position: relative;
   cursor:pointer
}
 li::before {
     content: '';
     position: absolute;
     top: 0.9em;
     left: -4em;
     width: 4em;
     height: 0.2em;
     background: dodgerblue;
     z-index: -1;
}
 li:first-child::before {
     display: none;
}
 .active {
     background: dodgerblue;
}
 .active ~ li {
     background: lightblue;
}
 .active ~ li::before {
     background: lightblue;
}
 body {
     font-family: sans-serif;
     padding: 2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="my-progress">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li class="active">4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
</ul>
if you wants to mouseover item freezes and not recovered to last state ... remove the following code from your script:
$("#my-progress li").mouseout(function(index){
  $("#my-progress li").removeClass("active");
  $($("#my-progress li")[activeIndex]).addClass("active");
})
Mehrzad Tejareh
  • 635
  • 5
  • 21
0

Well why don't you use JavaScript for that, just for changing which <li> element has the class "active", here is how you can do it, and I have written some comments to help you understand the code

// an event delegation for the ul on hover
document.querySelector("ul").onmouseover = function(e) {
  // get the current active <li> element to disactivate it later
  let element = this.querySelector(".active");
  // if the current hovered element is a <li> element
  if(e.target.nodeName === "LI") {
    // just activate the current hovered element
    e.target.classList.add("active");
    // and disactivate the old one only if we found one
    element !== e.target && (element.classList.remove("active"));
  }
}
@import "compass/css3";
li {
     width: 2em;
     height: 2em;
     text-align: center;
     line-height: 2em;
     border-radius: 1em;
     background: dodgerblue;
     margin: 0 1em;
     display: inline-block;
     color: white;
     position: relative;
}
 li::before {
     content: '';
     position: absolute;
     top: 0.9em;
     left: -4em;
     width: 4em;
     height: 0.2em;
     background: dodgerblue;
     z-index: -1;
}
 li:first-child::before {
     display: none;
}
 .active {
     background: dodgerblue;
}
 .active ~ li {
     background: lightblue;
}
 .active ~ li::before {
     background: lightblue;
}
 body {
     font-family: sans-serif;
     padding: 2em;
}
<ul>
  <li class="active">1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
</ul>
Saadi Toumi Fouad
  • 2,779
  • 2
  • 5
  • 18