【问题标题】:CSS :hover rerender after covering element height 0CSS :hover 覆盖元素高度 0 后重新渲染
【发布时间】:2016-11-12 10:47:41
【问题描述】:

我有一个我称之为 back 的元素被另一个我称之为 front 的元素覆盖。

Back 在 CSS 中设置为在悬停时更改颜色。 Front 设置为,当悬停时,在 1s 延迟和现在位于 Front 元素上的鼠标指针后消失位于返回元素上。

Front 通过在 JavaScript 中设置 height: 0 消失。在 Front 消失并且鼠标指针悬停在 Back 上后,浏览器不会重新渲染 Back 上的悬停效果导致其颜色没有按应有的方式改变。

当我通过从 DOM 中自然删除 Front 来尝试相同的示例时,它可以正常工作。不过,我的应用要求我通过设置 height: 0 来执行此操作。

您可以在以下示例中亲自尝试。您将看到一个红色框和一个蓝色框。红色是 Front,蓝色是 Back。当您将鼠标指针移到红色框时,红色框的颜色变为green。当您将鼠标移到蓝色框上时,一秒钟后,它会消失。

这个例子的重点是表明在蓝色框消失后,鼠标指针现在悬停在红色框上,因此它应该变成green

this example 中,蓝色框已从 DOM 中完全移除,并且可以正常工作。

不过,在this example 中,蓝色框将通过设置height: 0 来移除。消失后,红色元素不会变成green,直到我移动鼠标。

有没有办法强制浏览器重新渲染?

问题在 Google Chrome 和 Microsoft Edge 中仍然存在。 Firefox 运行良好。

【问题讨论】:

    标签: javascript css cross-browser hover rerender


    【解决方案1】:

    不要尝试强制浏览器重新呈现,您只需向 foo 添加一个类,当 bar 消失,然后在 mouseleave 上恢复正常。

    CSS

    #foo.hover, /* <- I just added this */
    #foo:hover {
        background-color: green;
    }
    

    JavaScript

    var
      foo = document.getElementById("foo"),
      bar = document.getElementById("bar");
    
    /* Set the 'mouseenter' event for bar to set the height to 0 and & the 'hover' class. */
    bar.onmouseenter = function() {
      setTimeout(function() {
        bar.style.height = 0;
        foo.classList.add("hover");
      }, 1000);
    }
    
    /* Set the 'mouseleave' event for bar to remove the 'hover' class. */
    bar.onmouseleave = function() {
      foo.classList.remove("hover");
    }
    

    查看以下 sn-p 以获得直观的表示。

    片段:

    /* --- JavaScript --- */
    var
      foo = document.getElementById("foo"),
      bar = document.getElementById("bar");
    
    /* Set the 'mouseenter' event for bar. */
    bar.onmouseenter = function() {
      setTimeout(function() {
        /* Set the height to 0. */
        bar.style.height = 0;
        
        /* Add the 'hover' class. */
        foo.classList.add("hover");
      }, 1000);
    }
    
    /* Set the 'mouseleave' event for bar. */
    bar.onmouseleave = function() {
      /* Remove the 'hover' class. */
      foo.classList.remove("hover");
    }
    /* --- CSS --- */
    #foo {
      width: 200px;
      height: 200px;
      background-color: red;
      position: absolute;
      top: 10px;
      left: 15px;
    }
    #foo.hover,
    #foo:hover {
      background-color: green;
    }
    #bar {
      width: 200px;
      height: 200px;
      background-color: blue;
      position: absolute;
      top: 100px;
      left: 100px;
    }
    <!-- HTML -->
    <div id = "foo"></div>
    <div id = "bar"></div>

    【讨论】:

    • 我正在寻找一些没有JS的。
    【解决方案2】:

    这可能是浏览器问题,但有一些方法可以强制 webkit 重绘。但我不建议你这样做。您可以简单地使用 bar.style.display = 'none'; 而不是将高度设置为零。

    另一种强制重绘/重绘效果很好的解决方案:

    sel.style.display='none';
    sel.offsetHeight; // no need to store this anywhere, the reference is enough
    sel.style.display='';
    

    **

    为避免闪烁,您可以尝试使用'inline-block''table''run-in' 而不是'none',但这可能会产生副作用。此外,超时 0 会触发重排,就像查询 offsetHeight 一样:sel.style.display = 'run-in'; setTimeout(function () { sel.style.display = 'block'; }, 0);

    试试这个真的很管用!

    【讨论】:

    • 这确实有效,它是已在此处发布的最佳解决方案。但这在 Edge 中不起作用。
    • 一种常见的设计模式是使用样式类来切换内联元素(例如锚点)的样式和内容。 jquery.mobile 包含样式类,可将您的锚元素转换为切换开关。
    【解决方案3】:

    只需使用 transition 属性就可以在 CSS 中实现。

    #foo {
      width: 200px;
      height: 200px;
      background-color:red;
      position: absolute;
      top:10px;
      left:15px;
      z-index: 10;
    }
    
    #foo:hover {
      background-color: green;
    }
    
    #bar {
      width: 200px;
      height: 200px;
      background-color:blue;
      position: absolute;
      top:100px;
      left:100px;
      z-index: 20;
      
      transition: all 1000000s; 
    }
    
    #bar:hover {
      transition: all 0.01s;
      opacity: 0;
      z-index: 1;
    }
    <div id="foo"></div>
    <div id="bar"></div>

    【讨论】:

      【解决方案4】:

      如果back完全front覆盖,您可以在中设置front.style['pointer-events'] = 'none' onmouseenter 回调,让鼠标在 front 消失之前激活 back:hover 规则。

      modified working snippet

      【讨论】:

      • 这不是ma case,但我考虑在我的项目中使用它。它可以帮助我。
      • 谢谢。在我的情况下,pointerEvents 属性对我有帮助。赏金是你的,但我认为它不能回答这个一般性问题。
      【解决方案5】:

      这似乎真的是一个浏览器问题,there are some ways on how to force webkit to redraw。但我真的不建议你这样做。您可以简单地使用bar.style.display = 'none'; 而不是将高度设置为零。具有相同的效果,一切都按预期工作。看到这个小提琴:https://jsfiddle.net/zkhorh38/4/

      【讨论】:

      • 我的应用在front(蓝色)元素中使用了嵌套元素(带有position: absolute)。其中display: none 隐藏但height: 0 使其可见。
      • 您的解决方案适用于 Chrome,但不适用于 Microsoft Edge。
      猜你喜欢
      • 2019-09-25
      • 2014-01-24
      • 1970-01-01
      • 2017-09-01
      • 2021-07-18
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 2010-10-06
      相关资源
      最近更新 更多