【问题标题】:'transform3d' not working with position: fixed children“transform3d”不适用于位置:固定的孩子
【发布时间】:2013-02-18 02:43:24
【问题描述】:

我有一种情况,在正常的 CSS 情况下,固定的 div 将准确定位在指定的位置(top:0pxleft:0px)。

如果我有一个具有 translate3d 转换的父级,这似乎不受尊重。我没有看到什么吗?我尝试过其他 webkit-transform,例如样式和转换原点选项,但没有运气。

我附上了JSFiddle 的示例,其中我希望黄色框位于页面的顶角而不是容器元素的内部。

您可以在下面找到小提琴的简化版本:

#outer {
    position:relative; 
    -webkit-transform:translate3d(0px, 20px , 0px); 
    height: 300px; 
    border: 1px solid #5511FF; 
    padding: 10px;
    background: rgba(100,180,250, .8); 
    width: 80%;
}
#middle{
    position:relative; 
    border: 1px dotted #445511; 
    height: 300px; 
    padding: 5px;
    background: rgba(250,10,255, .6);
}
#inner {
    position: fixed; 
    top: 0px;
    box-shadow: 3px 3px 3px #333; 
    height: 20px; 
    left: 0px;
    background: rgba(200,180,80, .8); 
    margin: 5px; 
    padding: 5px;
}
<div id="container">
    Blue: Outer, <br>
    Purple: Middle<br>
    Yellow: Inner<br>
    <div id="outer"> 
        <div id="middle">
            <div id="inner">
                Inner block
            </div>
        </div>
    </div>
</div>

如何使 translate3d 与固定位置的孩子一起工作?

【问题讨论】:

标签: html css css-position css-transforms


【解决方案1】:

这是因为transform 创建了一个新的局部坐标系,根据W3C spec

在 HTML 命名空间中,除none 之外的任何转换值都会导致创建堆叠上下文和包含块。该对象充当固定定位后代的包含块。

这意味着固定位置固定在转换后的元素上,而不是视口上。

目前没有我知道的解决方法。

这也记录在 Eric Meyer 的文章中:Un-fixing Fixed Elements with CSS Transforms

【讨论】:

  • 谢谢,我没有注意到实际的规范有这个信息.....我想我得到了数学答案的等价物:“根据定义”:)
  • @INT,我认为不会有解决方法。不允许变通办法有一个主要用例:用户提供的输入可能会覆盖其指定区域之外的控件(想想恶意电子邮件将选项添加到 gmail 工具栏)。最好的解决方法是暂时避免转换,如果您要从内部使用固定。
  • 不会将 CSS 顶部属性设置为任何有效的 window.scrollHeight 吗?您可能也必须绝对定位它,但是这样的事情应该是可行的,不是吗? (现在懒得实际测试了)
  • @bradorego 你是对的,我刚刚添加了我使用的代码。
  • 据我所知,这仍然在规范中不断变化。见Bug 16328 - Use of "containing block" does not match CSS2.1 definition
【解决方案2】:

按照 Bradoergo 的建议,只需获取窗口 scrollTop 并将其添加到绝对位置顶部,如:

function fix_scroll() {
  var s = $(window).scrollTop();
  var fixedTitle = $('#fixedContainer');
  fixedTitle.css('position','absolute');
  fixedTitle.css('top',s + 'px');
}fix_scroll();

$(window).on('scroll',fix_scroll);

无论如何这对我有用。

【讨论】:

  • 有效!但不是绑定到“窗口”,而是绑定到正在滚动的 div。此外,固定元素闪烁。
  • jQuery 在这里要做什么?
  • 这本可以做到,但就像提到的@train 一样,它会闪烁。
  • 是的,它的更新速度不够快,以至于我的使用不够干净:-/ 好主意
  • 这是非常不好的做法,不要用js做样式改变
【解决方案3】:

当页面中的项目使用转换时,我的固定顶部导航出现闪烁,以下应用于我的顶部导航解决了跳跃/闪烁问题:

#fixedTopNav {
    position: fixed;
    top: 0;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
}

Thanks to this answer on SO

【讨论】:

    【解决方案4】:

    在 Firefox 和 Safari 中,您可以使用 position: sticky; 代替 position: fixed;,但它在其他浏览器中不起作用。为此,您需要 javascript。

    【讨论】:

    • 粘性定位是相对定位和固定定位的混合体,它真的是实验性的,我强烈建议避免这种情况,因为它还不是标准的。
    • 在 Firefox 和 Safari 上的 AFAIK,您可以简单地使用 position:fixed,它仍然可以按预期工作。
    • @oriadam 不,当父母使用 translate3d 并且在某些情况下孩子的固定位置飞来飞去时,我遇到了问题。将尝试使用sticky,而它已经被主要浏览器支持:caniuse.com/#feat=css-sticky
    • sticky 可能是一个解决方案,它适用于现代浏览器。
    【解决方案5】:

    在我看来,解决这个问题的最佳方法是应用相同的翻译,但将需要修复的子元素从其父(已翻译)元素中分离出来;然后将翻译应用到 position: fixed 包装器内的 div。

    结果看起来像这样(在你的情况下):

    <div style='position:relative; border: 1px solid #5511FF; 
                -webkit-transform:translate3d(0px, 20px , 0px); 
                height: 100px; width: 200px;'> 
    
    </div>
    <div style='position: fixed; top: 0px; 
                box-shadow: 3px 3px 3px #333; 
                height: 20px; left: 0px;'>
        <div style='-webkit-transform:translate3d(0px, 20px, 0px);'>
            Inner block
        </div>
    </div>
    

    JSFiddle:https://jsfiddle.net/hju4nws1/

    虽然这对于某些用例可能并不理想,但通常如果您正在修复一个 div,您可能不太关心它的父元素/它在 DOM 中的继承树中的位置,并且似乎可以解决大多数问题头痛 - 同时仍然允许translateposition: fixed 生活在(相对)和谐中。

    【讨论】:

      【解决方案6】:

      我遇到了同样的问题。唯一的区别是我的“位置:固定”元素的“顶部”和“左侧”样式属性是从 JS 设置的。所以我能够应用修复:

      var oRect = oElement.getBoundingClientRect();
      

      oRect 对象将包含 real(相对于视口)顶部和左侧坐标。所以你可以调整你的实际 oElement.style.top 和 oElement.style.left 属性。

      【讨论】:

      • 这适用于 IE 和 Chrome,但不适用于 Android 标准浏览器。左边是一个数字,但它总是绘制在位置 0
      【解决方案7】:

      我有一个使用 -webkit-transform: translate3d 的画布侧边栏。这使我无法在页面上放置固定页脚。我通过在侧边栏初始化时添加到标签中的 html 页面上的一个类解决了这个问题,然后编写一个 css :not 限定符来声明“-webkit-transform: none;”当 html 标记上不存在该类时,该 html 标记。希望这可以帮助解决同样问题的人!

      【讨论】:

        【解决方案8】:

        尝试对子元素应用相反的变换:

        <div style='position:relative; border: 1px solid #5511FF; 
                    -webkit-transform:translate3d(0px, 20px , 0px); 
                    height: 100px; width: 200px;'> 
            <div style='position: fixed; top: 0px; 
                        -webkit-transform:translate3d(-100%, 0px , 0px); 
                        box-shadow: 3px 3px 3px #333; 
                        height: 20px; left: 0px;'>
                Inner block
            </div>
        </div>
        

        【讨论】:

          【解决方案9】:

          在元素变换时添加一个动态类。$('#elementId').addClass('transformed')。 然后继续在css中声明,

          .translat3d(@x, @y, @z) { 
               -webkit-transform: translate3d(@X, @y, @z); 
                       transform: translate3d(@x, @y, @z);
                //All other subsidaries as -moz-transform, -o-transform and -ms-transform 
          }
          

          然后

          #elementId { 
                -webkit-transform: none; 
                        transform: none;
          }
          

          然后

          .transformed {
              #elementId { 
                  .translate3d(0px, 20px, 0px);
              }
          }
          

          现在position: fixed 在子元素上提供topz-index 属性值时可以正常工作并保持不变,直到父元素转换​​。当转换被恢复时,子元素会再次以固定方式弹出。如果您实际使用的导航侧边栏会在单击时切换打开和关闭,并且您有一个标签集,当您向下滚动页面时应该保持粘性,这应该可以缓解这种情况。

          【讨论】:

            【解决方案10】:

            解决这个问题的一种方法是对固定元素应用相同的变换:

            <br>
            <div style='position:relative; border: 1px solid #5511FF; 
                        -webkit-transform:translate3d(0px, 20px , 0px); 
                        height: 100px; width: 200px;'> 
                <div style='position: fixed; top: 0px; 
                            -webkit-transform:translate3d(0px, 20px , 0px); 
                            box-shadow: 3px 3px 3px #333; 
                            height: 20px; left: 0px;'>
                    Inner block
                </div>
            </div>
            

            【讨论】:

            • 在 IE 上的 bug 首先不存在
            猜你喜欢
            • 1970-01-01
            • 2017-08-11
            相关资源
            最近更新 更多