7

I have a progress bar which has two children(parts). Whenever each of this children is hovered the total height of the progress and its children will change. I have managed to solve for the first children using the next sibling selector but I can't find a solution for the second children (the yellow part). Up to now I have solved this using jQuery but I want to do this in pure CSS.

fiddle: https://jsfiddle.net/zfh263r6/5/

$('#start').on({
  mouseenter: function () {
   //$(this).css('height', '4px');
      //$( 'progress' ).css('height', '4px');
  },
  mouseleave: function () {
   //$(this).css('height', '');
     // $( 'progress' ).css('height', '');
  }
});
#progress_wrap {
    position: relative;
    height: 4px; /*max height of progress*/
    background: #f3f3f3;
}

progress {
    appearance: none;
    -moz-appearance: none;
    -webkit-appearance: none;
    width: 100%;
    border:none;
    height: 2px;
    transition:all .25s ease-in;
    cursor: pointer;
    background-color: #fff;
    position: absolute;
    top: 0;
    left: 0;
    display: block;
}

progress:hover, progress:hover + #start {height: 4px}

progress[value]  {
    /* Reset the default appearance */
    -webkit-appearance: none;
     -moz-appearance: none;
       appearance: none;

    /* Get rid of default border in Firefox. */
    border: none;

    /* For IE10 */
    color: #f8008c;
}

progress[value]::-webkit-progress-bar {
    background-color: #fff;
    border:none;
}

progress[value]::-webkit-progress-value {background:#f8008c}

progress::-ms-progress-value {background:#f8008c}

progress::-moz-progress-bar {background:#f8008c}

progress::-ms-fill {border: none}

#start {
    height: 2px;
    transition: all .25s ease-in;
    cursor: pointer;
    background-color: #ffe232;
    position: absolute;
    top: 0;
    left: 0px;
    width: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="progress_wrap">
  <progress min="0" max="1" value="0.66" id="progress"></progress> 
  <div id="start" style="display: inline-block; left: 50px;"></div>
</div>
M1X
  • 4,971
  • 10
  • 61
  • 123

2 Answers2

8

No CSS doesn't have a previous sibling selector but you can use ~ selector -

Let's say you have a list of links and when hovering on one, all the previous ones should turn red. You can do it like this:

/* default link color is blue */
.parent a {
  color: blue;
}

/* prev siblings should be red */
.parent:hover a {
  color: red;
}
.parent a:hover,
.parent a:hover ~ a {
  color: blue;
}
<div class="parent">
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
</div>
Sankar
  • 6,908
  • 2
  • 30
  • 53
sudo_dudo
  • 573
  • 1
  • 5
  • 18
  • Thanks for the solution! – M1X Dec 28 '15 at 21:58
  • 2
    This answer is a copy from https://stackoverflow.com/a/27993987/940158 – alexandernst Jul 20 '22 at 14:49
  • @alexandernst looks like the original answer was (kind of) credited but then removed in a subsequent edit. Let me try editing it back. **Update:** the edit queue is full, so unfortunately I can't edit it back now :( – Hippo Oct 06 '22 at 12:07
3

From comment:

make progress and start the hover-height and then make progress_wrap overflow:hidden and shorter and make that expand on hover.

To avoid pushing other elements around, we can add some negative bottom margin at the same time.

#progress_wrap {
    position: relative;
    height: 2px;
    background: #f3f3f3;
    overflow:hidden;
    transition: all .25s ease-in;
}

#progress_wrap:hover, progress:hover + #start {
  height: 4px;
  margin-bottom:-2px;
}

progress,#start {
  height: 4px; /*This is a change from existing, not a new declaration*/
}

https://jsfiddle.net/5t90s4jk/