¿Por qué la aplicación de un filtro CSS en el padre rompe el posicionamiento del niño?
Entonces tengo esta "animación" de la pantalla de título que tiene el título centrado en una página de pantalla completa y cuando te desplazas hacia abajo se vuelve más pequeño y permanece en la parte superior de la página. Aquí hay un ejemplo funcional con el comportamiento esperado, del cual eliminé todo el código innecesario para hacerlo mínimo:
Mostrar fragmento de código
El siguiente es exactamente el mismo fragmento pero con una adición: apliqué un filtro que, en lo que a mí respecta, es puramente cosmético: filter: brightness(1.3);
.
Como puede ver a continuación, cuando se desplaza a la mitad de la "animación", el título simplemente desaparece. Cuando inspeccionas el elemento, todavía tiene todas sus propiedades pero de alguna manera ha desaparecido. Esto es lo mismo en Firefox y Chrome y no tengo idea de por qué. Apreciaría mucho si alguien pudiera publicar un fragmento funcional con el filtro aplicado y explicar por qué no funcionó antes.
Mostrar fragmento de código
Si nos referimos a la especificación podemos leer:
Un valor distinto de none para la propiedad de filtro da como resultado la creación de un bloque contenedor para descendientes posicionados absolutos y fijos , a menos que el elemento al que se aplica sea un elemento raíz del documento en el contexto de navegación actual. La lista de funciones se aplica en el orden proporcionado.
Esto significa que su position:fixed
elemento se ubicará en relación con el contenedor filtrado y no más con la ventana gráfica. En otras palabras, todavía está arreglado pero dentro de su nuevo bloque contenedor (el contenedor filtrado)
Aquí hay una versión simplificada para ilustrar el problema:
Mostrar fragmento de código
Para solucionar el problema, intente mover el filtro al elemento fijo en lugar de a su contenedor:
Mostrar fragmento de código
Aquí hay una lista no exhaustiva de las propiedades que resultan en la creación de un bloque contenedor para descendientes posicionados absolutos y fijos.
filter
transform
árbitrobackdrop-filter
árbitroperspective
árbitrocontain
árbitrocontainer
árbitrotransform-style
árbitrocontent-visibility
árbitrowill-change
cuando se utiliza con uno de los valores anteriores
Si cualquier valor no inicial de una propiedad haría que el elemento generara un bloque contenedor para elementos absolutamente posicionados, especificar esa propiedad en will-change debe hacer que el elemento genere un bloque contenedor para elementos absolutamente posicionados. árbitro
1 : Intentaré mantener esta lista actualizada.
Puedes hacerlo realidad usando before
. en lugar de asignarlo filter: brightness(1.3);
directamente al elemento secundario. asigne color y filtro a before
este elemento secundario. entonces tu código debería ser así:
#inside:before{
filter: brightness(1.3);
content: "";
background-color: lightcoral;
top: 0;
left: 0;
width: 100%;
height: 100%;
position: absolute;
}
Esto arreglará el problema.
También debes editar parte de tu código para que esto funcione completamente:
#inside{
position: relative;
}
Haga que la posición del padre sea relativa para asegurarse de que se before
ajuste dentro de su padre.
Esta solución también funciona con otros filtros como backdrop-filter
.
Si desea desenfocar o aplicar escala de grises a toda la página excepto un elemento, utilice backdrop-filter
en lugar de filter
. Al momento de escribir este artículo, Firefox solo necesita enviarlo de forma predeterminada.
No funciona:
<!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>
Laboral:
<!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>
Para evitar un mantenimiento complicado y una implementación diferente para cada navegador, puede utilizar una función recursiva de recorrido de árbol que marca la posición de los nodos "fijos" y luego aplica el filtro necesario correctamente sin destruir las posiciones.
Utilicé este código para aplicar la propiedad 'filtro invertido' globalmente, sin codificarla en elementos principales específicos.