
Aquí hay un truco de CSS divertido para mostrárselo a tus amigos: un título grande que cambia de un color sólido a un texto eliminado a medida que la imagen de fondo detrás de él se desplaza a su lugar. ¡Y podemos hacerlo usando HTML y CSS sencillos!
Este efecto se crea renderizando dos contenedores con <h1>
elementos. El primer contenedor tiene un fondo blanco con texto nocaut. El segundo contenedor tiene una imagen de fondo con texto en blanco. Luego, usando algunos trucos de recorte elegantes, ocultamos el texto del primer contenedor cuando el usuario se desplaza más allá de sus límites y viceversa. Esto crea la ilusión de que el fondo del texto está cambiando.
Antes de comenzar, tenga en cuenta que esto no funcionará en versiones anteriores de Internet Explorer. Además, las imágenes de fondo fijas pueden resultar engorrosas en los navegadores WebKit móviles. Asegúrese de pensar en el comportamiento alternativo para estas circunstancias.
Configurando el HTML
Comencemos por crear nuestra estructura HTML general. Dentro de una envoltura exterior, creamos dos contenedores idénticos, cada uno con un <h1>
elemento que está envuelto en un .title_wrapper
.
<header>
<!-- First container -->
<div class="container container_solid">
<div class="title_wrapper">
<h1>The Great Outdoors</h1>
</div>
</div>
<!-- Second container -->
<div class="container container_image">
<div class="title_wrapper">
<h1>The Great Outdoors</h1>
</div>
</div>
</header>
Observe que cada contenedor tiene tanto un global .container
class y su propia clase de identificador – .container_solid
y .container_image
, respectivamente. De esa manera, podemos crear estilos base comunes y también apuntar a cada contenedor por separado con CSS.
Estilos iniciales
Ahora, agreguemos algo de CSS a nuestros contenedores. Queremos que cada contenedor tenga la altura total de la pantalla. El primer recipiente necesita un fondo blanco sólido, que podemos hacer en su .container_solid
clase. También queremos agregar una imagen de fondo fija al segundo contenedor, lo que podemos hacer en su .container_image
clase.
.container {
height: 100vh;
}
/* First container */
.container_solid {
background: white;
}
/* Second container */
.container_image {
/* Grab a free image from unsplash */
background-image: url(/path/to/img.jpg);
background-size: 100vw auto;
background-position: center;
background-attachment: fixed;
}
A continuación, podemos diseñar el <h1>
elementos un poco. El texto dentro .container_image
puede ser simplemente blanco. Sin embargo, para obtener un texto eliminatorio para el <h1>
elemento interior container_image
, debemos aplicar una imagen de fondo y luego alcanzar la text-fill-color
y background-clip
Propiedades CSS para aplicar el fondo al texto mismo en lugar de los límites del <h1>
elemento. Note que el <h1>
El fondo tiene el mismo tamaño que el de nuestro .container_image
elemento. Eso es importante para asegurarse de que todo se alinee.
.container_solid .title_wrapper h1 {
/* The text background */
background: url(https://images.unsplash.com/photo-1575058752200-a9d6c0f41945?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ);
background-size: 100vw auto;
background-position: center;
/* Clip the text, if possible */
/* Including -webkit` prefix for bester browser support */
/* https://caniuse.com/text-stroke */
-webkit-text-fill-color: transparent;
text-fill-color: transparent;
-webkit-background-clip: text;
background-clip: text;
/* Fallback text color */
color: black;
}
.container_image .title_wrapper h1 {
color: white;
}
Ahora, queremos que el texto esté fijo en el centro del diseño. Agregaremos posicionamiento fijo a nuestro global .title_wrapper
class y fíjela al centro vertical de la ventana. Entonces usamos text-align
para centrar horizontalmente nuestro <h1>
elementos.
.header-text {
display: block;
position: fixed;
margin: auto;
width: 100%;
/* Center the text wrapper vertically */
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.header-text h1 {
text-align: center;
}
En este punto, el <h1>
en cada contenedor debe colocarse directamente uno encima del otro y permanecer fijo en el centro de la ventana mientras el usuario se desplaza. Aquí está el código completo y organizado con algunas sombras agregadas para ver mejor el posicionamiento del texto.
Recortando el texto y los contenedores
Aquí es donde las cosas empiezan a ponerse realmente interesantes. Solo queremos un contenedor <h1>
para ser visible cuando su posición de desplazamiento actual está dentro de los límites de su contenedor principal. Normalmente esto se puede resolver usando overflow: hidden;
en el contenedor principal. Sin embargo, con nuestros dos <h1>
elementos que utilizan un posicionamiento fijo, ahora se colocan en relación con la ventana del navegador, en lugar del elemento principal. En este caso usando overflow: hidden;
no tendrá ningún efecto.
Para que los contenedores principales oculten el contenido de desbordamiento fijo, podemos usar CSS clip
propiedad con posicionamiento absoluto. Esto le dice a nuestro navegador que oculte cualquier contenido fuera de los límites de un elemento. Reemplacemos los estilos por nuestro .container
class para asegurarse de que no muestren ningún elemento desbordado, incluso si esos elementos usan un posicionamiento fijo.
.container {
/* Hide fixed overflow contents */
clip: rect(0, auto, auto, 0);
/* Does not work if overflow = visible */
overflow: hidden;
/* Only works with absolute positioning */
position: absolute;
/* Make sure containers are full-width and height */
height: 100vh;
left: 0;
width: 100%;
}
Ahora que nuestros contenedores utilizan el posicionamiento absoluto, se eliminan del flujo normal de contenido. Y, debido a eso, necesitamos colocarlos manualmente en relación con su respectivo elemento padre.
.container_solid {
/* ... */
/* Position this container at the top of its parent element */
top: 0;
}
.container_image {
/* ... */
/* Position the second container below the first container */
top: 100vh;
}
En este punto, el efecto debería estar tomando forma. Puede ver que el desplazamiento crea una ilusión en la que el texto noqueado parece cambiar el fondo. Realmente, es solo nuestra máscara de recorte que revela una <h1>
elemento dependiendo de qué contenedor principal se superpone al centro de la pantalla.
Hagamos feliz a Safari
Si está utilizando Safari, es posible que haya notado que su motor de renderizado no actualiza la vista correctamente cuando se desplaza. Agregue el siguiente código al .container
class para forzar que se actualice correctamente.
.container {
/* ... */
/* Safari hack */
-webkit-mask-image: -webkit-linear-gradient(top, #ffffff 0%,#ffffff 100%);
}
Aquí está el código completo hasta este punto.
Es hora de limpiar la casa
Asegurémonos de que nuestro HTML siga las mejores prácticas de accesibilidad. Los usuarios que no utilizan tecnología de asistencia no pueden decir que hay dos <h1>
elementos en nuestro documento, pero aquellos que usan un lector de pantalla seguramente lo harán porque ambos encabezados están anunciados. Agreguemos aria-hidden
a nuestro segundo contenedor para que los lectores de pantalla sepan que es puramente decorativo.
<!-- Second container -->
<div class="container container_image" aria-hidden="true">
<div class="title_wrapper">
<h1>The Great Outdoors</h1>
</div>
</div>
Ahora, el mundo es nuestra ostra cuando se trata de estilismo. Somos libres de modificar las fuentes y el tamaño de las fuentes para hacer que el texto quede como queramos. Incluso podríamos llevar esto más lejos agregando un efecto de paralaje o reemplazando la imagen de fondo con un video. Pero bueno, en ese punto, asegúrate de trabajar un poco más en la accesibilidad para que aquellos que prefieren menos movimiento obtengan la experiencia adecuada.
Eso no fue tan difícil, ¿verdad?