为什么在父对象上应用CSS过滤器会破坏子对象的位置? [英] Why does applying a CSS-Filter on the parent break the child positioning?

查看:33
本文介绍了为什么在父对象上应用CSS过滤器会破坏子对象的位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有这个标题屏幕的动画"标题居中显示在全屏页面上,向下滚动时标题变小并保留在页面顶部.这是一个具有预期行为的可行示例,从中我剥离了所有不必要的代码以使其最小化:

So I have this title-screen "animation" that has the title centered on a fullscreen page and when you scroll down it becomes smaller and remains at the top of the page. Here is a working example with the expected behavior, from which I stripped all unnecessary code to make it minimal:

$(window).scroll( () => {
    "use strict";
    let windowH = $(window).height();
    let windowS = $(window).scrollTop();
    let header  = $("#header").height(); 
    
    if (windowS < windowH-header) {
        $("#title").css("transform", "scale("+(2-(windowS/($(document).outerHeight()-windowH))*2.7)+")");
        $("#header").css("transform", "translateY(0)");
        $("#inside, #content").css({
            "position": "static",
            "margin-top": 0
        });
    } else {
        $("#inside").css({
            "position": "fixed",
            "margin-top": -windowH+header
        });
        $("#content").css("margin-top", windowH);
    }
  
    $("#header").css("position", windowS > (windowH-header)/2 ? "fixed" :"static");
});

.fixed {
    position: fixed!important;
}
.wrapper {
    width: 100%;
    text-align: center;
}
.wrapper:before {
    display: table;
    content: " ";
}
.wrapper:after {
    clear: both;
}
#inside {
    width: 100%;
    height: 100vh;
    background-color: lightcoral;
    display: flex;
    align-items: center;
    justify-content: center;
}
#header {
    height: 90px;
    top: 0;
    position: sticky;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.5s;
}
#title {
    width: 100%;
    color: #fff;
    transform: scale(2);
}
#content {
    height: 1000px;
    background-color: lightblue;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>  
    <div class="wrapper">
        <div id="inside">
            <div id="header">
                <h1 id="title">Title</h1>
            </div>
        </div>
    <div id="content"></div>
</body>

接下来是完全相同的代码段,但有一个附加代码段:我应用了一个滤镜,就我而言,这纯粹是修饰性的: filter:Brightness(1.3); .

Next up is the exact same snippet but with one addition: I applied a filter, which is, as far as I'm concerned, purely cosmetic: filter: brightness(1.3);.

如您在下面滚动到动画"菜单中途时所看到的那样.标题就消失了.当您检查元素时,它仍然具有其所有属性,但是以某种方式消失了.在Firefox和Chrome中这是相同的,我不知道为什么.如果有人可以在应用了过滤器的情况下发布有效的代码段并解释为什么以前不起作用,我将不胜感激.

As you can see below when you scroll half-way through the "animation" the title just disappears. When you inspect the element it still has all its properties but somehow it's gone. This is the same in Firefox and Chrome and I have no idea why. I would appreciate it a lot if someone could post a working snippet with the filter applied and explain why it didn't work before.

$(window).scroll( () => {
    "use strict";
    let windowH = $(window).height();
    let windowS = $(window).scrollTop();
    let header  = $("#header").height(); 
    
    if (windowS < windowH-header) {
        $("#title").css("transform", "scale("+(2-(windowS/($(document).outerHeight()-windowH))*2.7)+")");
        $("#header").css("transform", "translateY(0)");
        $("#inside, #content").css({
            "position": "static",
            "margin-top": 0
        });
    } else {
        $("#inside").css({
            "position": "fixed",
            "margin-top": -windowH+header
        });
        $("#content").css("margin-top", windowH);
    }
  
    $("#header").css("position", windowS > (windowH-header)/2 ? "fixed" :"static");
});

.fixed {
    position: fixed!important;
}
.wrapper {
    width: 100%;
    text-align: center;
}
.wrapper:before {
    display: table;
    content: " ";
}
.wrapper:after {
    clear: both;
}
#inside {
    width: 100%;
    height: 100vh;
    background-color: lightcoral;
    filter: brightness(1.3);        /*<<<<<<<<<<<<<<<<*/
    display: flex;
    align-items: center;
    justify-content: center;
}
#header {
    height: 90px;
    top: 0;
    position: sticky;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.5s;
}
#title {
    width: 100%;
    color: #fff;
    transform: scale(2);
}
#content {
    height: 1000px;
    background-color: lightblue;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>  
    <div class="wrapper">
        <div id="inside">
            <div id="header">
                <h1 id="title">Title</h1>
            </div>
        </div>
    <div id="content"></div>
</body>

推荐答案

如果我们引用规范,我们可以阅读:

If we refer to the specification we can read:

对于filter属性,除none以外的其他值都会导致创建一个包含绝对位置和固定位置的块后代,除非其适用的元素是文档根当前浏览上下文中的元素.功能列表是按提供的顺序应用.

A value other than none for the filter property results in the creation of a containing block for absolute and fixed positioned descendants unless the element it applies to is a document root element in the current browsing context. The list of functions are applied in the order provided.

这意味着您的 position:fixed 元素将相对于过滤后的容器而不是视口放置.换句话说,它仍然是固定的,但是在其 new 包含块(过滤后的容器)

This means that your position:fixed element will be positioned relatively to the filtred container and no more the viewport. In other words, it's still fixed but inside its new containing block (the filtred container)

这是一个简化的版本来说明此问题:

Here is a simplified version to illustrate the issue:

.container {
  display: inline-block;
  width: 200px;
  height: 200vh;
  border: 1px solid;
}

.container>div {
  position: fixed;
  width: 100px;
  height: 100px;
  background: red;
  color: #fff;
}

<div class="container">
  <div>I am fixed on scroll</div>
</div>

<div class="container" style="filter:grayscale(1);">
  <div>I move with the scroll</div>
</div>

要解决此问题,请尝试将过滤器移到固定元素而不是容器:

To fix the issue try to move the filter to the fixed element instead of its container:

.container {
  display: inline-block;
  width: 200px;
  height: 200vh;
  border: 1px solid;
}

.container>div {
  position: fixed;
  width: 100px;
  height: 100px;
  background: red;
  color: #fff;
  filter: grayscale(1);
}

<div class="container">
  <div>I am fixed on scroll</div>
</div>

以下是属性的非穷尽性 1 列表,这些属性导致为绝对和固定位置的后代创建一个包含块

Here is a non-exhaustive1 list of the properties that results in the creation of a containing block for absolute and fixed positioned descendants

  • 过滤器
  • transform 参考
  • perspective ref
  • 包含 参考
  • 转换样式 ref
  • 与以上值之一一起使用时,
  • 将更改
  • filter
  • transform ref
  • backdrop-filter ref
  • perspective ref
  • contain ref
  • transform-style ref
  • will-change when used with one of the above values

如果属性的任何非初始值都会导致该元素为绝对定位的元素生成一个包含块,则在will-change中指定该属性必须导致该元素为绝对定位的元素生成一个包含块. 参考

1 :将尝试使此列表保持最新状态.

1: Will try to keep this list up to date.

这篇关于为什么在父对象上应用CSS过滤器会破坏子对象的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆