在元素样式上设置.cssText时,转换不起作用?

时间:2019-11-12 17:46:17

标签: javascript html dom css-transitions

我有以下CSS代码段:

.Test-Content {
  transition: height 2s;
}

以及以下HTML代码:

<div id="mydiv" class="Test-Content">foo</div>

使用纯JavaScript,我试图像这样更改div的高度:

myId = document.getElementById("mydiv");
myId.style.cssText = "height: 0;";

/* ... Lots of code and situations where the browser re-renders the page ... */

myId.style.cssText = "height: 100px";

这确实将div的高度从原来的值更改为0,然后更改为100px,但是没有任何动画,即立即。我不明白为什么会这样。毕竟div的类列表中有.Test-Content,因此任何高度的变化都应触发过渡。

有人可以解释为什么不是这种情况吗?

当我将其更改为以下(非常奇怪和令人担忧的)代码时,它会按预期工作:

CSS:

.Test-Content-A {
  transition: height 2s;
  height: 0;
}
.Test-Content-B {
  transition: height 2s;
  height: 10px; /* or whatever number you prefer */
}

HTML:

<div id="mydiv" class="Test-Content-A Test-Content-B">foo</div>

JavaScript :(与上面相同)

似乎只有在该元素的类列表中也有两个具有不同style.cssText属性的类的情况下,才可以直接通过设置元素的height来触发过渡。

在Firefox和Chrome浏览器中,我遇到了这个问题(到目前为止尚未测试其他问题),在撰写本文时都处于当前补丁程序级别。

3 个答案:

答案 0 :(得分:2)

您可能会遇到以下几段所示的几件事。第一次单击“展开”或“折叠”时,它不会设置动画,但是之后单击“展开”或“折叠”将触发动画。

document.getElementById("expand").addEventListener('click', () => {
  myId = document.getElementById("mydiv");
  myId.style.cssText = "height: 100px";
});

document.getElementById("collapse").addEventListener('click', () => {
  myId = document.getElementById("mydiv");
  myId.style.cssText = "height: 0;";
});

document.getElementById("unset").addEventListener('click', () => {
  myId = document.getElementById("mydiv");
  myId.style.cssText = "";
});

document.getElementById("setandexpand").addEventListener('click', () => {
  myId = document.getElementById("mydiv");
  myId.style.cssText = "height: 0;";
  setTimeout(() => { myId.style.cssText = "height: 100px"; });
});
.Test-Content {
  transition: height 2s;
}
<div id="mydiv" class="Test-Content">foo</div>

<button id="expand">Expand</button>
<button id="collapse">Collapse</button>
<button id="unset">Unset</button>


<button id="setandexpand">Set and expand</button>

问题可能是您遇到的:

1。 CSS只能从一个值过渡到一个值。

cssText = ""(初始值)到cssText = "height: 100px"不会动画。您可以通过单击“取消设置”,然后单击“展开”或“折叠”来重现此内容。

2。如果在一个代码块中多次设置CSS,则浏览器将仅处理最后一个。

浏览器设置后不会立即呈现更改,而是根据所有设置在执行所有可执行JavaScript和更新页面之间进行切换。您可以将其分为两个离散的步骤来解决。最好的办法可能是在HTML中设置style="height: 0"或添加一个高度为零的类。

否则,您可以执行以下操作:

myId.style.cssText = "height: 0";
setTimeout(() => { myId.style.cssText = "height: 100px"; });

此代码将高度设置为零,让浏览器更新样式,然后执行新代码,将高度设置为100px,浏览器可以对其进行动画处理。当然,您只需要调用cssText = "height: 0",因为一旦渲染它,浏览器就可以进行动画处理。

您可以在代码段中单击“取消设置”,然后单击“设置并展开”来查看此内容。元素将立即减少到零,然后扩大到100px。多次单击不应似乎没有任何作用,因为每次浏览器将开始将动画降低到零,然后在毫秒内开始动画恢复到100px。

答案 1 :(得分:1)

使用JS触发CSS动画的最简单方法之一就是更改类。

CSS:

.Test-Content {
  height: 0;
  transition: height 2s;
}
.Test-Content.taller {
  height: 10px;
}

然后使用Javascript:

1)用于添加类(向前动画)

document.getElementById("mydiv").classList.add('taller');

2)用于删除类(向后动画)

document.getElementById("mydiv").classList.remove('taller');

答案 2 :(得分:1)

这可能无法回答您有关为什么的过渡不适用于style.cssText的问题。但是,如果您希望div在页面加载时立即更改高度,我建议使用动画代替如下所示:

.Test-Content {
  transition: height 2s;
  height: 100px;
  animation: grow 2s;
}

@keyframes grow {
  from {
    height: 0
  }
  to {
    height: 100px;
  }
}

这消除了使用JavaScript的需要,并且更好地帮助防止JavaScript执行CSS可以做的事情。