不查询宽度就无法转换 属性
Transition not working without querying width property
我想通过将 class 添加到 js 中的 div 来为点击事件上的 translateX 设置动画。 css 文件中添加了变换和过渡属性。
var widget = document.getElementById('widget');
widget.style.display = 'block';
document.getElementById('widget2').clientWidth; //comment this line out and it wont work
widget.className = 'visible';
仅当我在添加 class.[=13 之前查询 dom 中 any 元素的宽度 属性 时才有效=]
这是一个 jsfiddle:
https://jsfiddle.net/5z9fLsr5/2/
谁能解释为什么这不起作用?
那是因为您开始转换并修改了 display
属性 "at the same time"。更改 display
会破坏任何转换(无可否认,需要引用),因此将 display
更改和实际转换隔离开来是个好主意:
https://jsfiddle.net/5z9fLsr5/3/
document.getElementById('showWidget').addEventListener('click', function(e) {
e.preventDefault();
var widget = document.getElementById('widget');
widget.style.display = 'block';
//document.getElementById('widget2').clientWidth;
window.setTimeout(function(){
widget.className = 'visible';
},0);
});
#widget {
width: 200px;
height: 80px;
background: black;
position: absolute;
transition: transform 500ms;
transform: translateX(-200px);
display: none;
}
#widget.visible {
transform: translateX(200px);
}
#widget2 {
position: absolute;
right: 0
}
<a href="#" id="showWidget">show</a>
<div id="widget"></div>
<div id="widget2">xxx</div>
查询clientWidth
好像"pause"执行了一段时间,所以也行。
这里的问题是display: none
的初始设置。对于浏览器的布局管理器,这表明布局应该被完成,就好像有问题的元素甚至不在 DOM 中一样(请注意,它仍然是)。这意味着 CSS 样式 transform: translateX(-200px);
将不会被应用。
这样做:
widget.style.display = 'block';
widget.className = 'visible';
基本上同时触发两个修改 - 布局仅在两个语句都执行后才重新完成。插入 document.getElementById('widget2').clientWidth;
(clientHeight
也有效)会触发布局管理器重新绘制,从而注册 transform: translateX(-200px)
.
正如其他人在我之前提到的,解决方案是使用 opacity
而不是 display
(这是我的选择),或者使用 setTimeout
延迟0(参见 Why is setTimeout(fn, 0) sometimes useful?)。
我想通过将 class 添加到 js 中的 div 来为点击事件上的 translateX 设置动画。 css 文件中添加了变换和过渡属性。
var widget = document.getElementById('widget');
widget.style.display = 'block';
document.getElementById('widget2').clientWidth; //comment this line out and it wont work
widget.className = 'visible';
仅当我在添加 class.[=13 之前查询 dom 中 any 元素的宽度 属性 时才有效=]
这是一个 jsfiddle: https://jsfiddle.net/5z9fLsr5/2/
谁能解释为什么这不起作用?
那是因为您开始转换并修改了 display
属性 "at the same time"。更改 display
会破坏任何转换(无可否认,需要引用),因此将 display
更改和实际转换隔离开来是个好主意:
https://jsfiddle.net/5z9fLsr5/3/
document.getElementById('showWidget').addEventListener('click', function(e) {
e.preventDefault();
var widget = document.getElementById('widget');
widget.style.display = 'block';
//document.getElementById('widget2').clientWidth;
window.setTimeout(function(){
widget.className = 'visible';
},0);
});
#widget {
width: 200px;
height: 80px;
background: black;
position: absolute;
transition: transform 500ms;
transform: translateX(-200px);
display: none;
}
#widget.visible {
transform: translateX(200px);
}
#widget2 {
position: absolute;
right: 0
}
<a href="#" id="showWidget">show</a>
<div id="widget"></div>
<div id="widget2">xxx</div>
查询clientWidth
好像"pause"执行了一段时间,所以也行。
这里的问题是display: none
的初始设置。对于浏览器的布局管理器,这表明布局应该被完成,就好像有问题的元素甚至不在 DOM 中一样(请注意,它仍然是)。这意味着 CSS 样式 transform: translateX(-200px);
将不会被应用。
这样做:
widget.style.display = 'block';
widget.className = 'visible';
基本上同时触发两个修改 - 布局仅在两个语句都执行后才重新完成。插入 document.getElementById('widget2').clientWidth;
(clientHeight
也有效)会触发布局管理器重新绘制,从而注册 transform: translateX(-200px)
.
正如其他人在我之前提到的,解决方案是使用 opacity
而不是 display
(这是我的选择),或者使用 setTimeout
延迟0(参见 Why is setTimeout(fn, 0) sometimes useful?)。