Varin
Varin

Reputation: 2453

transform: translateY(-50%) causes 1px jump/shift in IE and EDGE

Please see an example in jsfiddle. https://jsfiddle.net/0uwmxt02/1/

In IE and EDGE the transform: translateY(-50%) causes 1px jump up and down at the start and end of the animation. In Chrome the displacement still occurs but it is smooth. Any idea of what causes it?

.submenu-arrow-hover {
  position: relative;
  width: 200px;
  top:50px;
 }
  
 .submenu-arrow-hover:after {
    //background: rgba(155, 173, 188, 0.9);
    position:absolute;
    content:'';
    width: 1px;
    height: 28px;
    border: 1px solid red;
    border-right:0;
    border-top:0;
    top:50%;
    right:-1px;
    transform-origin: 0 0;
    transform: translateY(-50%);
    transition-duration: .3s;
  }
  
.submenu-arrow-hover:hover::after {
      //background: rgba(155, 173, 188, 0.9);
      position:absolute;
      content:'';
      width: 20px;
      height:20px;
      border: 1px solid red;
      border-right:0;
      border-top:0;
      top:50%;
      right:-1px;
      transform-origin: 0 0;
      transform: translateY(-50%) rotate(45deg);
}
<div class="submenu-arrow-hover">HOVER ME</div>

Upvotes: 2

Views: 2065

Answers (4)

Prid
Prid

Reputation: 1624

For Chrome, this StackOverflow answer worked wonderfully!

Add this to the element that has translateY applied: -webkit-backface-visibility: hidden;

Upvotes: 1

Varin
Varin

Reputation: 2453

I ended up having to use jQuery as elements will have variable height and the arrow position needs to be adjusted when the screen is resized and when elements change size/position.

    function setMargins(arrow) {
    parentHeight = $(arrow).parent().height();  
    arrowHeight = $(arrow).height();  
    topMargin = (parentHeight - (arrowHeight - 1)) / 2 ;    
    $(arrow).css("margin-top", topMargin);    
}


$(document).ready(function(){
    $('.submenu-arrow-hover--arrow').each(function() {
    setMargins(this);
})
});

// timeout function needed as there is transition on the menu elements so
// function has to fire few milliseconds after the transitions have finished animating

$(window).resize(function() {
    setTimeout(function(){
    $('.submenu-arrow-hover--arrow').each(function() {

        setMargins(this)            
    })    
}, 600);
});

Upvotes: 0

Syden
Syden

Reputation: 8625

  • Equal .submenu-arrow-hover:after's height to .submenu-arrow-hover:hover::after's (20px), otherwise the height async will make it bounce.

.submenu-arrow-hover {
  position: relative;
  width: 200px;
  top: 50px;
}

.submenu-arrow-hover:after {
  //background: rgba(155, 173, 188, 0.9);
  position: absolute;
  content: '';
  width: 1px;
  height: 20px;
  border: 1px solid red;
  border-right: 0;
  border-top: 0;
  top: 50%;
  right: -1px;
  transform-origin: 0 0;
  transform: translateY(-50%);
  transition-duration: .3s;
}

.submenu-arrow-hover:hover::after {
  //background: rgba(155, 173, 188, 0.9);
  position: absolute;
  content: '';
  width: 20px;
  height: 20px;
  border: 1px solid red;
  border-right: 0;
  border-top: 0;
  top: 50%;
  right: -1px;
  transform-origin: 0 0;
  transform: translateY(-50%) rotate(45deg);
}
<div class="submenu-arrow-hover">HOVER ME</div>

Upvotes: 1

Conan
Conan

Reputation: 2709

Appears to be some kind of confusion between the translation and rotation. As a workaround, try removing the translateY() requirement completely:

.submenu-arrow-hover {
  position: relative;
  width: 200px;
  top: 50px;
  
  /* outline and excess height added as a test */
  outline: 1px dotted #ccc;
  height: 100px;
}

.submenu-arrow-hover::after {
  position: absolute;
  content: '';
  width: 1px;
  height: 28px;
  border: 0;
  border-left: 1px solid red;
  border-bottom: 1px solid transparent;
  right: -1px;
  transform-origin: 0 0;
  transition-duration: .3s;
  
  /* position top of pseudo element halfway down */
  top: 50%;
  margin-top: -14px; /* accurately centre by offsetting by half the height */
}

.submenu-arrow-hover:hover::after {
  width: 20px;
  height: 20px;
  border-bottom-color: red;
  transform: rotate(45deg);
}
<div class="submenu-arrow-hover">HOVER ME</div>

EDIT: updated to ensure arrow is centred vertically within parent <div/>.

Upvotes: 2

Related Questions