显示块和 css 转换未触发的解决方法
workaround for display block and css transitions not triggering
对于这个问题的这么多更新,我很抱歉,我很高兴大家试图帮助我。我认为下面有一个更清晰的理解这个问题的方法:
CSS 如果您将元素的显示 属性 设置为在更改附加过渡的 属性 之前立即阻止,则
CSS 过渡将不适用。考虑以下代码:
CSS:
#creative {
display: none;
opacity: 0;
transition: opacity 0.5s;
}
HTML:
<div id="creative">
<span>Sample text</span>
</div>
Javascript:
var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'block';
dom.creative.style.opacity = 1;
该元素将正确显示,但没有任何过渡。此问题的解决方法是通过访问元素的视觉属性之一强制重绘:
dom.creative.style.display = 'block';
var a = dom.creative.offsetHeight; /* <-- forces repaint */
dom.creative.style.opacity = 1;
有解决这个问题的好方法吗?顺便说一句,我的意思是每次我需要更改显示 属性 和带有过渡的 属性 时,不要添加额外的行 javascript 代码。
没有为 absolute 属性定义转换,例如 display。如何在 none
和 block
之间 插入 ?你不能。但是您可以创建一些 post 函数,这些函数将在动画完成后 运行。
使用 setTimeout
您可以使用setTimeout
并在动画结束后执行一些代码:
ANIMATION_TIME = 0.5 * 1000; // in ms
function show(element) {
// Display property must be set inmediatly; otherwise, the 'show' animation won't be visible until it ends.
element.style.display = 'block';
element.opacity = 1;
}
function hide(element) {
element.opacity = 0;
setTimeout(function() {
element.style.display = 'none';
}, ANIMATION_TIME);
}
// Call examples
var dom = {};
dom.creative = document.getElementById('creative');
show(dom.creative);
hide(dom.creative);
使用动画事件
正如@trustk 指出的那样,您还可以(最好)使用 DOM 事件:
function show(element) {
element.style.display = 'block';
element.opacity = 1;
element.removeEventListener("animationend", afterHide, false);
}
function afterHide(e) {
// e.target -> element
e.target.display = 'none';
}
function hide(element) {
element.opacity = 0;
element.addEventListener("animationend", afterHide, false);
}
如果您只是为不透明度调用添加超时,它应该可以工作!只要不同时调用显示和不透明度属性,持续时间几乎可以为零。
var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'block';
setTimeout(function(){
dom.creative.style.opacity = 1;
},1);
如果可以选择 jQuery,您也可以使用 jQuery 淡入淡出。然后你可以完全忽略不透明度,就像...
dom.creative.fadeIn(500)
根据您在问题中提供的代码,我将在这里采用完全不同的方式,并使用 animation
代替,这将使整个 repaint问题消失
更新了脚本,将 div 设置为 display: block
var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'none';
var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
if (dom.creative.style.display == 'block') {
dom.creative.style.display = 'none';
} else {
dom.creative.style.display = 'block';
}
})
#creative {
display: none;
opacity: 0;
animation: opac 1s forwards;
margin: 20px;
}
@keyframes opac {
100% {
opacity: 1;
}
}
button {
margin: 20px;
}
<button id="button">Toggle display</button>
<div id="creative">
<span>Sample text</span>
</div>
如果不需要 display: none
,可以使用 transition
并像这样简单地切换 class
var dom = {};
dom.creative = document.getElementById('creative');
var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
dom.creative.classList.toggle('show');
})
#creative {
opacity: 0;
transition: opacity 1s;
margin: 20px;
}
#creative.show {
opacity: 1;
transition: opacity 1s;
}
button {
margin: 20px;
}
<button id="button">Toggle display</button>
<div id="creative">
<span>Sample text</span>
</div>
对于transition
,除了offsetHeight
和setTimeout
方案外,还有一个3:rd,视觉效果和toggle display一样block/none,设置 height/width 为 0。
var dom = {};
dom.creative = document.getElementById('creative');
var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
dom.creative.classList.toggle('show');
})
#creative {
width: 0;
height: 0;
opacity: 0;
transition: opacity 1s, width 0s 1s;
margin: 20px 0;
}
#creative.show {
width: 100%;
height: auto;
opacity: 1;
transition: opacity 1s, width 0s;
}
button {
margin: 20px 0;
}
<button id="button">Toggle display</button>
<div id="creative">
<span>Sample text</span>
</div>
<div>Other content</div>
您可以在不使用 javascript 的情况下仅使用 css 过渡来显示/隐藏元素。
<!--html-->
<div id="parent">Some parent text
<div id="creative">Some details</div>
</div>
/*css*/
#parent #creative{
opacity:0;
visibility:hidden;
clip: rect(0px,0px,0px,0px);
transition: all 0.5s;
}
#parent:hover #creative{/*trigger transition*/
opacity:1;
visibility:visible;
clip: rect(0px,220px,0px,330px);
}
对于这个问题的这么多更新,我很抱歉,我很高兴大家试图帮助我。我认为下面有一个更清晰的理解这个问题的方法:
CSS 如果您将元素的显示 属性 设置为在更改附加过渡的 属性 之前立即阻止,则
CSS 过渡将不适用。考虑以下代码:
CSS:
#creative {
display: none;
opacity: 0;
transition: opacity 0.5s;
}
HTML:
<div id="creative">
<span>Sample text</span>
</div>
Javascript:
var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'block';
dom.creative.style.opacity = 1;
该元素将正确显示,但没有任何过渡。此问题的解决方法是通过访问元素的视觉属性之一强制重绘:
dom.creative.style.display = 'block';
var a = dom.creative.offsetHeight; /* <-- forces repaint */
dom.creative.style.opacity = 1;
有解决这个问题的好方法吗?顺便说一句,我的意思是每次我需要更改显示 属性 和带有过渡的 属性 时,不要添加额外的行 javascript 代码。
没有为 absolute 属性定义转换,例如 display。如何在 none
和 block
之间 插入 ?你不能。但是您可以创建一些 post 函数,这些函数将在动画完成后 运行。
使用 setTimeout
您可以使用setTimeout
并在动画结束后执行一些代码:
ANIMATION_TIME = 0.5 * 1000; // in ms
function show(element) {
// Display property must be set inmediatly; otherwise, the 'show' animation won't be visible until it ends.
element.style.display = 'block';
element.opacity = 1;
}
function hide(element) {
element.opacity = 0;
setTimeout(function() {
element.style.display = 'none';
}, ANIMATION_TIME);
}
// Call examples
var dom = {};
dom.creative = document.getElementById('creative');
show(dom.creative);
hide(dom.creative);
使用动画事件
正如@trustk 指出的那样,您还可以(最好)使用 DOM 事件:
function show(element) {
element.style.display = 'block';
element.opacity = 1;
element.removeEventListener("animationend", afterHide, false);
}
function afterHide(e) {
// e.target -> element
e.target.display = 'none';
}
function hide(element) {
element.opacity = 0;
element.addEventListener("animationend", afterHide, false);
}
如果您只是为不透明度调用添加超时,它应该可以工作!只要不同时调用显示和不透明度属性,持续时间几乎可以为零。
var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'block';
setTimeout(function(){
dom.creative.style.opacity = 1;
},1);
如果可以选择 jQuery,您也可以使用 jQuery 淡入淡出。然后你可以完全忽略不透明度,就像...
dom.creative.fadeIn(500)
根据您在问题中提供的代码,我将在这里采用完全不同的方式,并使用 animation
代替,这将使整个 repaint问题消失
更新了脚本,将 div 设置为 display: block
var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'none';
var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
if (dom.creative.style.display == 'block') {
dom.creative.style.display = 'none';
} else {
dom.creative.style.display = 'block';
}
})
#creative {
display: none;
opacity: 0;
animation: opac 1s forwards;
margin: 20px;
}
@keyframes opac {
100% {
opacity: 1;
}
}
button {
margin: 20px;
}
<button id="button">Toggle display</button>
<div id="creative">
<span>Sample text</span>
</div>
如果不需要 display: none
,可以使用 transition
并像这样简单地切换 class
var dom = {};
dom.creative = document.getElementById('creative');
var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
dom.creative.classList.toggle('show');
})
#creative {
opacity: 0;
transition: opacity 1s;
margin: 20px;
}
#creative.show {
opacity: 1;
transition: opacity 1s;
}
button {
margin: 20px;
}
<button id="button">Toggle display</button>
<div id="creative">
<span>Sample text</span>
</div>
对于transition
,除了offsetHeight
和setTimeout
方案外,还有一个3:rd,视觉效果和toggle display一样block/none,设置 height/width 为 0。
var dom = {};
dom.creative = document.getElementById('creative');
var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
dom.creative.classList.toggle('show');
})
#creative {
width: 0;
height: 0;
opacity: 0;
transition: opacity 1s, width 0s 1s;
margin: 20px 0;
}
#creative.show {
width: 100%;
height: auto;
opacity: 1;
transition: opacity 1s, width 0s;
}
button {
margin: 20px 0;
}
<button id="button">Toggle display</button>
<div id="creative">
<span>Sample text</span>
</div>
<div>Other content</div>
您可以在不使用 javascript 的情况下仅使用 css 过渡来显示/隐藏元素。
<!--html-->
<div id="parent">Some parent text
<div id="creative">Some details</div>
</div>
/*css*/
#parent #creative{
opacity:0;
visibility:hidden;
clip: rect(0px,0px,0px,0px);
transition: all 0.5s;
}
#parent:hover #creative{/*trigger transition*/
opacity:1;
visibility:visible;
clip: rect(0px,220px,0px,330px);
}