gpt4 book ai didi

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

转载 作者:bug小助手 更新时间:2023-10-25 19:33:30 29 4
gpt4 key购买 nike



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>




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);.

接下来是完全相同的片段,但有一个添加:我应用了一个过滤器,就我而言,这纯粹是装饰性的:filter:brightness(1.3);。


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.

正如你在下面看到的,当你滚动到动画的一半时,标题就消失了。当你检查元素时,它仍然有它的所有属性,但不知何故它消失了。火狐和Chrome的情况也是一样,我不知道为什么。如果有人能发布一个应用了滤镜的工作片段,并解释为什么以前不起作用,我会非常感激的。




$(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:

如果我们参考规范,我们可以阅读:



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.



This means that your position:fixed element will be positioned relatively to the filtered container and no more the viewport. In other words, it's still fixed but inside its new containing block (the filtered 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>






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

以下是导致为绝对和固定定位的子体创建包含块的属性的非详尽列表1



  • filter

  • transform ref

  • backdrop-filter ref

  • perspective ref

  • contain ref

  • container ref

  • transform-style ref

  • content-visibility ref

  • will-change when used with one of the above values



If any non-initial value of a property would cause the element to generate a containing block for absolutely positioned elements, specifying that property in will-change must cause the element to generate a containing block for absolutely positioned elements. ref





1: I will try to keep this list up to date.

他说:我会努力使这份清单保持最新。



You can make it happen by using before. instead of assigning the filter: brightness(1.3); to the child element directly. assign color and filter to the before of this child element. so your code should be like this:

您可以通过使用之前来实现它。而不是直接将滤镜:Brightness(1.3);分配给子元素。将颜色和滤镜分配给此子元素的前面。因此,您的代码应该如下所示:


  #inside:before{
filter: brightness(1.3);
content: "";
background-color: lightcoral;
top: 0;
left: 0;
width: 100%;
height: 100%;
position: absolute;
}

This will fix the problem.

这将解决这个问题。


You should also edit some of your code to make this fully work:

您还应该编辑一些代码以使其完全正常工作:


#inside{
position: relative;
}

Make the parent position to be relative to make sure the before wrap inside its parent.

将父位置设置为相对位置,以确保前折回位于其父位置内。


This solution also works with other filters like backdrop-filter.

此解决方案也适用于其他滤镜,如背景滤镜。



If you want to blur or grayscale the entire page except one element, just use backdrop-filter instead of filter.
At the time of writing Firefox just needs to ship it by default.

如果你想模糊或灰度化整个页面,除了一个元素,只需使用backdrop-filter而不是filter。在写这篇文章的时候,Firefox只需要在默认情况下提供它。


Not working:

不起作用:




<!DOCTYPE html><html><head>
<style>
.overlay {
position:fixed;
right:10%;
top:10%;
bottom:10%;
left:10%;
background-color:red;
z-index:2;
}
.overlay ~ * {
filter: grayscale(50%) blur(5px);
}
</style>
</head>
<body>
<div class="overlay">I am not blurred</div>

<!-- position test -->
<div style="margin-top:100px;float:right;">
<div style="background-color:red;position:fixed;top:0;right:0;width:100px;height:100px;"></div>
</div>
</body>
</html>




Working:

工作:




<!DOCTYPE html><html><head>
<style>
.overlay {
position:fixed;
right:10%;
top:10%;
bottom:10%;
left:10%;
background-color:red;
z-index:2;
}
body:after {
content:"";
position:fixed;
z-index: 1;
top:0;
left:0;
width:100%;
height:100%;
backdrop-filter: grayscale(50%) blur(5px);
}
</style>
</head>
<body>
<div class="overlay">I am not blurred</div>

<!-- position test -->
<div style="margin-top:100px;float:right;">
<div style="background-color:red;position:fixed;top:0;right:0;width:100px;height:100px;"></div>
</div>
</body>
</html>





In order to avoid hard maintenance and different implementation for each browser, you can use a recursive tree traversal function which marks the position 'fixed' nodes and then apply the needed filter properly without destroying the positions.

为了避免繁琐的维护和每个浏览器不同的实现,可以使用递归树遍历函数,将位置标记为固定的节点,然后在不破坏位置的情况下正确应用所需的过滤器。


I used this code in order to apply the 'filter invert' property globally, without hard-coding it to specific parent elements.

我使用此代码是为了全局应用‘Filter Invert’属性,而不是将其硬编码到特定的父元素。


更多回答

Thank you! I still wonder why this is a thing. Wouldn't it be better if this wasn't the case?

谢谢!我仍然想知道为什么这是一件事。如果不是这样的话不是更好吗?

@MiXT4PE it's defined in the spec so it should be like that, you may probably ask why they define it this way .. I am pretty sure there is a reason (probably a complex one) behind this choice.

@MiXT4PE它是在规范中定义的,所以应该是这样的,你可能会问为什么他们这样定义它。我非常肯定,这一选择背后有一个原因(可能是一个复杂的原因)。

@ygoe first it's not bug, it's by design like many features that we don't like but we should work with (clear float, margin collapsing, etc) so you should adapt your code in order to overcome this. There is no universal solution but depending on your case there is for sure a solution. You may ask a question by adding your particular code in order to see if we can modify your logic to keep your requirement and fix the issue.

@ygoe首先它不是错误,它的设计就像我们不喜欢的许多功能一样,但我们应该使用(清除浮动、边距折叠等),所以你应该调整你的代码来克服这个问题。没有万能的解决方案,但根据你的情况,肯定有解决方案。您可以通过添加您的特定代码来提出问题,以查看我们是否可以修改您的逻辑以保留您的需求并解决问题。

Further context for your answer: this GitHub issue added the specification that a containing block is created when filter has a value other than none. The GitHub issue also has a link to the discussion where this was decided, and this code example (archive link) was used to illustrate the ambiguity the containing block was designed to fix.

您的答案的进一步上下文:这个GitHub问题增加了当Filter的值不是None时创建包含块的规范。GitHub的问题也有一个链接,链接到决定这个问题的讨论,这个代码示例(存档链接)用于说明包含块旨在解决的歧义。

Spec Issue 402. Firefox bug 1650522.

规范问题402。Firefox错误1650522。

Just a little update regarding Firefox: it appears it still has not been rolled-out, but may be rolled-out soon. For updates, see bugzilla.mozilla.org/show_bug.cgi?id=1578503

关于Firefox的一个小更新:它似乎还没有推出,但可能很快就会推出。有关更新,请参阅bugzilla.mozilla.org/show_bug.cgi?id=1578503

As @Temani Afif backdrop-filter has the same effect as filter

As@Temani Afif Backdown-Filter与Filter具有相同的效果

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com