
Estaba trabajando en un proyecto que tenía este borde dentado en la parte inferior de una imagen de banner.
Luciendo nítido… en más de un sentido.
¡Es algo que me hizo pensar por un segundo y aprendí algo en el proceso! Pensé en escribir cómo lo abordé para que puedas usarlo en tus propios proyectos.
Empecé con una buena imagen HTML pasada de moda en un elemento contenedor:
<div class="jagged-wrapper">
<img src="https://css-tricks.com/using-css-masks-to-create-jagged-edges/path-to-image.jpg" />
</div>
Luego usé su ::after
pseudo elemento para colocar una imagen de fondo repetitiva en él:
.jagged-wrapper::after {
content: "";
background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1" preserveAspectRatio="none"><polygon style="fill:white;" points="1,0 1,1 0,1 "/></svg>');
background-size: 30px 30px;
width: 100%;
height: 30px;
position: absolute;
bottom: 0px;
right: 0;
z-index: 2;
}
esa imagen de fondo? Es un código SVG convertido a un URI de datos. Aquí está el código SVG original. Chris tiene un buen video donde explica esa conversión.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1" preserveAspectRatio="none">
<polygon style="fill: white;" points="1,0 1,1 0,1 "/>
</svg>
“¡Aquí vamos!” Yo pensé.
Si bien eso ciertamente funciona, caramba, eso es una gran molestia. Es difícil leer el marcado SVG en CSS así. Además, es molesto tener que acordarse de citarlos (p. ej. url('data:image/svg+xml'...)
). Claro, podemos codificar en base64 el SVG para evitar eso, pero eso es aún más molesto. Además, el SVG debe rellenarse con el mismo color de fondo que la imagen (o donde sea que se use), o de lo contrario no funcionará.
Espera, ¿no es para esto para lo que sirve el enmascaramiento? ¡Sí! Sí, para eso está el enmascaramiento.
Eso me llevó a un nuevo enfoque: usar una imagen como la de arriba como una máscara CSS para que los bits “faltantes” de la imagen del banner realmente no aparezcan. En lugar de dibujar triángulos del color de fondo en la parte superior del banner, debemos enmascarar esos triángulos del banner por completo y dejar que se vea el fondo real. De esa manera, ¡funciona en cualquier fondo!
El enmascaramiento es prácticamente compatible en todas partes, al menos de la manera simple de la que estoy hablando aquí. También estamos hablando de algo que se puede implementar con una mejora progresiva; si las máscaras no son compatibles con un navegador determinado, simplemente no obtendrá el efecto de diente de sierra. Definitivamente no es el fin del mundo.
Estos datos de soporte del navegador son de Caniuse, que tiene más detalles. Un número indica que el navegador admite la función en esa versión y en adelante.
Escritorio
Cromo | Firefox | ES DECIR | Borde | Safari |
---|---|---|---|---|
100* | 53 | No | 97* | TP * |
Móvil / Tableta
Android cromo | Android Firefox | Androide | iOSSafari |
---|---|---|---|
96 * | 95 | 96 * | 15.2* |
Una forma en que funciona una máscara CSS es proporcionar una imagen con un canal alfa como mask-image
. El elemento subyacente, el que se está enmascarando, se vuelve (semi) transparente en la medida en que el canal alfa del mask-image
dicta Entonces, si su imagen de máscara es una tetera blanca sobre un fondo transparente, entonces el elemento enmascarado se cortará con la forma de la tetera y todo lo que esté afuera se ocultará.
El enmascaramiento puede ser un concepto difícil de asimilar. Sarah Drasner tiene un artículo que profundiza en el enmascaramiento, incluso en qué se diferencia del recorte. Las máscaras pueden hacer mucho más de lo que estamos cubriendo aquí. Consulte las especificaciones, caniuse y MDN para obtener aún más información.
Lo que necesitamos es una sola imagen similar a un “diente de sierra” similar al SVG de arriba, donde la mitad superior izquierda se llena de blanco y la parte inferior izquierda se deja semitransparente. E, idealmente, esa imagen no sería un SVG real, ya que eso nos llevaría de vuelta al feo lío de URI de datos en el que estábamos antes.
En este punto, podría estar pensando: “Oye, simplemente incrusta el SVG en el CSS directamente, define una máscara en él, luego apunta el CSS a la ID de la máscara en el SVG”.
¡Buena idea! Y ciertamente es factible, si puede editar el HTML. Sin embargo, para mi proyecto específico, estaba trabajando en WordPress y realmente quería limitar mis cambios a CSS puro en lugar de inyectar partes adicionales en el HTML. Eso hubiera sido mucho más trabajo. No creo que esto sea raro; para un cambio de presentación como este, es útil no tener que editar el HTML. En general, estamos de acuerdo con la idea de evitar elementos envolventes sin valor semántico solo para proporcionar ganchos de estilo, pero creo que eso también se aplica a agregar el marcado SVG completo al documento… o incluso una plantilla de WordPress.
En su lugar, podemos usar un degradado lineal CSS para crear una forma de triángulo:
.el {
linear-gradient(
to bottom right,
white,
white 50%,
transparent 50%,
transparent
);
}
Aquí eso está en un fondo radial, para que puedan ver que es realmente transparente:
¡Estupendo! Podemos usar eso como un mask-image
en nuestro banner, ¿verdad? Necesitamos establecer mask-size
, que es como background-size
, y mask-repeat
, me gusta background-repeat
, y estamos bien?
Lamentablemente no. No tan bien.
La primera razón es que, a menos que esté usando Firefox, es probable que no vea ninguna máscara en el ejemplo anterior. Esto se debe a que Blink y WebKit todavía solo admiten el enmascaramiento con un prefijo de proveedor en el momento de escribir este artículo. Eso significa que necesitamos -webkit-
versiones prefijadas de todo.
Dejando de lado el prefijo del proveedor, lo que estamos haciendo también es conceptualmente incorrecto. Si limitamos la máscara a solo la franja inferior de la imagen con mask-size
, entonces el resto de la imagen no tiene mask-image
en absoluto, lo que lo enmascara por completo. Como resultado, no podemos usar el diente de sierra solo como máscara. Lo que necesitamos es un mask-image
eso es un rectángulo del tamaño de la imagen con solo un diente de sierra en la parte inferior.
Algo como esto:
Hacemos eso con dos imágenes degradadas. La primera imagen es el mismo triángulo de diente de sierra que arriba, que está configurado para repeat-x
y posicionado en el bottom
para que se repita solo a lo largo del borde inferior de la imagen. La segunda imagen es otro degradado que es transparente para los 30 px inferiores (para no interferir con el diente de sierra), opaco arriba (que se muestra yendo de negro a blanco en la demostración) y ocupa todo el tamaño del elemento. .
Así que ahora tenemos esta pieza en forma de cuña, con un solo diente de sierra triangular en la parte inferior, y ocupa toda la altura de nuestra imagen de banner en dos piezas separadas. Finalmente, podemos usar estas piezas con mask-image
repitiéndolos horizontalmente a través de nuestra imagen, y debería tener el efecto que queremos:
¡Y ahí lo tenemos!