¿Por qué la aplicación de un filtro CSS en el padre rompe el posicionamiento del niño?

Resuelto leonheess asked hace 6 años • 4 respuestas

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

leonheess avatar Oct 23 '18 04:10 leonheess
Aceptado

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:fixedelemento 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 árbitro
  • backdrop-filter árbitro
  • perspective árbitro
  • contain árbitro
  • container árbitro
  • transform-style árbitro
  • content-visibility árbitro
  • will-changecuando 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.

Temani Afif avatar Oct 22 '2018 21:10 Temani Afif

Puedes hacerlo realidad usando before. en lugar de asignarlo filter: brightness(1.3);directamente al elemento secundario. asigne color y filtro a beforeeste 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 beforeajuste dentro de su padre.

Esta solución también funciona con otros filtros como backdrop-filter.

sajjad rezaei avatar Feb 03 '2022 09:02 sajjad rezaei

Si desea desenfocar o aplicar escala de grises a toda la página excepto un elemento, utilice backdrop-filteren 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>
Expandir fragmento

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

David Vielhuber avatar Sep 16 '2020 19:09 David Vielhuber

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.

Stavros Droutsas avatar Jul 16 '2020 19:07 Stavros Droutsas