CSS-Filter on parent breaks child positioning

牧云@^-^@ 提交于 2019-11-26 01:54:51

问题


I am currently working on a website and encountered this weird behaviour. I am not sure if it is a bug or how to deal with it so I\'m asking you guys for help.

So I have this title-screen \"animation\" that has the title centered in 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 behaviour, 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);.

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>

回答1:


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 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>

It behaves exactly the same way as transform: 'transform3d' not working with position: fixed children



来源:https://stackoverflow.com/questions/52937708/css-filter-on-parent-breaks-child-positioning

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!