【问题标题】:Transitions not working when setting .cssText on an element's style?在元素样式上设置 .cssText 时转换不起作用?
【发布时间】:2020-03-08 11:28:55
【问题描述】:

我有以下 CSS sn-p:

.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 中遇到了这个问题(到目前为止还没有测试过其他的),在撰写本文时都处于当前的补丁级别。

【问题讨论】:

    标签: javascript html dom css-transitions


    【解决方案1】:

    您可能会遇到一些事情,如下面的 sn-p 所示。第一次点击“展开”或“折叠”时,它不会动画,但之后点击“展开”或“折叠”会触发动画。

    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"; });
    

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

    您可以在 sn-p 中看到这一点,方法是单击“取消设置”,然后单击“设置并展开”。该元素将立即减小到零,然后扩展为 100px。多次点击不应该似乎会做任何事情,因为每次浏览器都会开始动画到零,然后在几毫秒内开始动画回到 100px。

    【讨论】:

    • 非常感谢您的支持。这是我经常忘记的事情。但是,在这种情况下,它可能不是罪魁祸首,因为设置为 0 和设置为 100 发生在处理按钮单击的事件处理程序中,并且每次都交替执行,因此浏览器有足够的机会呈现页面之间。我会相应地编辑问题。
    【解决方案2】:

    使用 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');
    

    【讨论】:

    • 感谢,并为付出努力而投票。但正如我所写的,在这种情况下,简单的方法是不可行的。此外,我非常想了解问题到底出在哪里。
    【解决方案3】:

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

    .Test-Content {
      transition: height 2s;
      height: 100px;
      animation: grow 2s;
    }
    
    @keyframes grow {
      from {
        height: 0
      }
      to {
        height: 100px;
      }
    }
    

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

    【讨论】:

    • 感谢,并为付出努力而投票。但我需要在 JavaScript 中更改 div 的高度,因为我应该在事件处理程序中进行。
    • @Binarus 出于好奇:如果您想从事件处理程序中执行此操作,为什么不在示例代码中的事件处理程序中使用它?另外,你为什么用style.cssText而不是style.height
    • ad 1) 代码非常大,相应地剥离它可能会花费相当长的时间。广告 2)因为我必须将 height 属性与可能已经以元素的直接(即非类)样式设置的其他属性合并,结果证明只是将其附加到 .cssText by far 是最简单的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 2019-11-23
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    相关资源
    最近更新 更多