问题
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>
回答1:
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/>
.
回答2:
- Equal
.submenu-arrow-hover:after
'sheight
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>
回答3:
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);
});
回答4:
For Chrome, this StackOverflow answer worked wonderfully!
Add this to the element that has translateY applied: -webkit-backface-visibility: hidden;
来源:https://stackoverflow.com/questions/44117257/transform-translatey-50-causes-1px-jump-shift-in-ie-and-edge