Search code examples
htmlcss

transform:translate(-50%,-50%) doesn't work well with transform:scale()


I am centering my element with class "play__circle" using position: absolute; (parent container is set to position:relative;) but when I use transform:scale() then the element doesn't stay in the center anymore. Initially the "play__circle" his hidden, but on hover its opacity is set to 1 and scale(0.7).

.container{
  width: 200px;
  height: 250px;
  background-color: rgba(208, 174, 191, 0.8);
  position: relative;
  padding:5px;
}

.play__circle{
  width: 60px;
  height: 60px;
  background-color: gray;
  border-radius: 100%;
  position: absolute;
  top:50%;
  left:50%;
  opacity:0;
  transform:translate(-50%, -50%);
  transition: opacity 300ms ease-in-out, transform    300ms ease-in-out;
}

.container:hover .play__circle{
  opacity: 1;
  transform:scale(0.7)
}

.content__one{
  width: 100%;
  height: 50%;
  background-color: rgba(205, 184, 86, 0.8);
}

.content__two{
  width: 100%;
  height: 50%;
  background-color: rgba(232, 125, 52, 0.8);
}
<div class="container">
  <div class="play__circle">

  </div>
  <div class="content__one">

  </div>
  <div class="content__two">

  </div>
</div>


Solution

  • TL;DR. transform properties need to be fully specified when animating

    The main concern in your case is that you have transform: translate(-50%, -50%); in your base styling, and only animating it by transform: scale(0.7); on hover. When animating a CSS property with multiple values, you often need to include all custom set values.

    That is, when you hover a mouse, CSS will transition only between scale(1) and scale(0.7) values and simply ignore the translate(-50%, -50%) since it's not specified.

    UPDATED: As @temani mentioned in the comment, transform-origin shouldn't have to be adjusted, given the scale is set after translate.

    ORIGINAL ANSWER (IGNORE): Also, you'd need to specify the transform-origin to top left corner, since you repositioned it by transform and it's no longer animating from the visual center. See the snippet below.

    .container{
      width: 200px;
      height: 250px;
      background-color: rgba(208, 174, 191, 0.8);
      position: relative;
      padding:5px;
    }
    
    .play__circle{
      width: 60px;
      height: 60px;
      background-color: gray;
      border-radius: 100%;
      position: absolute;
      top:50%;
      left:50%;
      opacity:0;
      transform:translate(-50%, -50%);
      transition: opacity 300ms ease-in-out, transform 300ms ease-in-out;
    }
    
    .container:hover .play__circle{
      opacity: 1;
      transform: translate(-50%, -50%) scale(0.7); /* This line is edited */
    }
    
    .content__one{
      width: 100%;
      height: 50%;
      background-color: rgba(205, 184, 86, 0.8);
    }
    
    .content__two{
      width: 100%;
      height: 50%;
      background-color: rgba(232, 125, 52, 0.8);
    }
    <div class="container">
      <div class="play__circle">
    
      </div>
      <div class="content__one">
    
      </div>
      <div class="content__two">
    
      </div>
    </div>