cssanimationshutter

Two rolling shutters animation in CSS


I want to do animation of opening two (top and bottom) 'shutters', behind which I want to show some data (eg. number).

I am using z-index, because I want the number behind this curtain (opening shutters) to be there before curtain is open.

Animation need to be that upper stripe will shrink to the top edge and lower striper will shrink to the bottom edge. Shrink should be visible as making height of each strip lower - so from original height of 13px to 0px. At the same time upper's stripe CSS top attribute should be +=1px and lower's stripe top should be -=1px, to mimic that they are opening.

For now i have problem with making each stripe height from original value to 0px (only one of them is 'opening'). And i don't know how to change their top attributes at the same time.

When in middle of animation time, it should like below:

enter image description here

CSS and HTML

#wrapper {
  width: 100px;
  height: 30px;
  border: 2px solid black;
  position: relative;
  top: 50px;
  z-index: 2;
}
.stripe {
  position: relative;
  width: 98px;
  height: 13px;
  background: green;
  z-index: 1;
  border: 1px solid red;
  transition: height 500ms ease-in-out;
}
.stripe:hover {
  height: 0;
}
#money {
  position: relative;
  top: -25px;
  width: 90%;
  display: block;
  margin: 0 auto;
  z-index: 0;
  text-align: center;
}
<div id="wrapper">
  <div class="stripe"></div>
  <div class="stripe"></div>
  <input type="text" id="money" value="1200">
</div>


Solution

  • You should really be using position:absolute for this and relative widths and heights (percentage values). A few tricks thrown in and I think this is closer to what you were trying to achieve.

    #wrapper {
      width: 100px;
      height: 30px;
      border: 2px solid black;
      position: relative;
      top: 50px;
      z-index: 2;
    }
    .stripe {
      position: absolute;
      width: 100%;
      height: 50%;
      background: green;
      z-index: 1;
      transition: height 500ms ease-in-out;
    }
    .stripe:first-child {
      border-bottom: 1px solid transparent;
      top: 0;
    }
    .stripe + .stripe {
      border-top: 1px solid transparent;
      bottom: 0;
    }
    
    #wrapper:hover .stripe {
      height: 0;
    }
    #money {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      width: 90%;
      display: block;
      margin: auto;
      z-index: 0;
      text-align: center;
      height: 1.2em;
      line-height: 1.2em;
    }
    <div id="wrapper">
      <div class="stripe"></div>
      <div class="stripe"></div>
      <input type="text" id="money" value="1200">
    </div>

    To clarify what I mean by a few tricks, I used a transparent 1px border on the bottom and top of the top and bottom shutters (respectively); I used a set width and height on the input box with margin: auto to both vertically and horizontally center it; and I used the <selector> + <selector> selector (adjacent sibling selector) to differentiate between either stripe (this is fully CSS2.1 compliant and will work pretty far back for browser compatibility).

    Edit:

    As requested, to convert this solution to a javascript one, just replace all occurrences of :hover (there's only one in this situation) with a class (e.g. .hover-state); and toggle the class with your favorite goto event listener format. No need for more than one class in this case.

    var wrapper = document.getElementById('wrapper');
    
    wrapper.addEventListener('mouseenter', function(){
    		this.classList.toggle('hover-state');
    });
    #wrapper {
      width: 100px;
      height: 30px;
      border: 2px solid black;
      position: relative;
      top: 50px;
      z-index: 2;
      cursor: text;
      display: block;
    }
    .stripe {
      position: absolute;
      width: 100%;
      height: 50%;
      background: green;
      z-index: 1;
      transition: height 500ms ease-in-out;
    }
    .stripe:first-of-type {
      border-bottom: 1px solid transparent;
      top: 0;
    }
    .stripe + .stripe {
      border-top: 1px solid transparent;
      bottom: 0;
    }
    
    #wrapper.hover-state .stripe, input:focus ~ .stripe {
      height: 0;
    }
    #money {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      width: 90%;
      display: block;
      margin: auto;
      z-index: 0;
      text-align: center;
      height: 1.2em;
      line-height: 1.2em;
      outline: none!important;
      border: none;
      background: transparent;
    }
    <label id="wrapper">
      <input type="text" id="money" value="1200">
      <div class="stripe"></div>
      <div class="stripe"></div>
    </label>