“Bordes” apilados | Programar Plus

Hace un tiempo, estaba en el proceso de agregar estilos de enfoque al sitio web de An Event Apart. Parte de eso fue aplicar diferentes efectos de enfoque en diferentes áreas del diseño, como anillos blancos en el encabezado y pie de página y anillos naranjas en el texto principal. Pero en un lugar, quería anillos que fueran más obvios, algo así como apilar dos bordes uno encima del otro, para crear formas inusuales que llamaran la atención.

Una fila de cuatro imágenes, la segunda de las cuales incluye un borde rojo discontinuo.

Jugué con la idea de anidar elementos con bordes y algunos márgenes negativos para colocar un borde encima de otro, o anidar un borde dentro de un contorno y luego usar márgenes negativos para no desequilibrar el diseño. Pero nada de eso se sintió satisfactorio.

Resulta que hay una serie de trucos para crear el efecto de apilar un borde sobre otro al combinar un borde con otros efectos CSS, o incluso sin requerir el uso de ningún borde. Exploremos, ¿de acuerdo?

Contorno y caja-sombra

Si lo que se va a tener con varios bordes es un rectángulo, ya sabes, como casi todos los elementos de bloque, entonces mezclar un contorno y una sombra de caja dura extendida puede ser justo lo que necesitas.

Comencemos con la sombra del cuadro. Probablemente estés acostumbrado a encuadrar sombras como esta:

.drop-me {
  background: #AEA;
  box-shadow: 10px 12px 0.5rem rgba(0,0,0,0.5);
}

Un cuadro turquesa que contiene las palabras texto div y una sombra de cuadro pesado.

Eso te da una sombra borrosa debajo y a la derecha del elemento. ¡Sombras paralelas, tan pasadas del milenio! Pero hay espacio y apoyo para un cuarto valor de longitud en box-shadow que define una distancia de propagación. Esto aumenta el tamaño de la forma de la sombra en todas las direcciones por la longitud dada, y luego se vuelve borrosa. Asumiendo que hay un desenfoque, eso es.

Entonces, si le damos a una sombra de cuadro sin desplazamiento, sin desenfoque y un poco de extensión, se dibujará alrededor del elemento, pareciendo un borde sólido sin ser realmente un borde.

.boxborder-me {
  box-shadow: 0 0 0 5px firebrick;
}

Un cuadro rojo que contiene un borde rojo grueso.

Este “borde” de sombra de cuadro se dibuja justo fuera del borde exterior del elemento. Ese es el mismo lugar donde se dibujan los contornos alrededor de las cajas de bloques, así que todo lo que tenemos que hacer ahora es dibujar un contorno sobre la sombra. Algo como esto:

.boxborder-me {
  box-shadow: 0 0 0 5px firebrick;
  outline: dashed 5px darkturquoise;
}

Un cuadro que contiene un borde rojo discontinuo con un fondo turquesa que llena los espacios entre guiones.

Bingo. Un “borde” multicolor que, en este caso, ni siquiera altera el tamaño del diseño, porque las sombras y los contornos se dibujan después de calcular el tamaño del elemento. El contorno, que se encuentra en la parte superior, puede usar prácticamente cualquier estilo de contorno, que es el mismo que la lista de estilos de borde. Por lo tanto, los contornos punteados y dobles son posibilidades. (Al igual que todos los demás estilos, pero no tienen partes transparentes, por lo que la sombra sólida solo se puede ver a través de colores translúcidos).

Si desea un efecto de tres tonos en el borde, se pueden crear varias sombras de cuadro usando una lista separada por comas y luego colocar un contorno sobre eso. Por ejemplo:

.boxborder-me {
  box-shadow: 0 0 0 1px darkturquoise,
              0 0 0 3px firebrick,
              0 0 0 5px orange,
              0 0 0 6px darkturquoise;
  outline: dashed 6px darkturquoise;
}

Un cuadro que contiene un borde discontinuo donde los guiones se duplican con rojo y dorado y un fondo turquesa que llena los espacios entre guiones.

Volviendo a los efectos más simples, combinando un dashed el contorno sobre una sombra de cuadro extendida con un borde sólido del mismo color que la sombra de cuadro crea otro efecto más:

.boxborder-me {
  box-shadow: 0 0 0 5px firebrick;
  outline: dashed 5px darkturquoise;
  border: solid 5px darkturquoise;
}

Un cuadro con un borde rojo discontinuo y un fondo turquesa que no solo llena los espacios del tablero, sino que desborda el borde rojo hacia el borde interior del cuadro.

La ventaja adicional aquí es que, aunque se usa una sombra de cuadro, no rellena el fondo del elemento, por lo que puede ver el fondo a través de él. Así es como siempre se comportan las sombras de cuadro: solo se dibujan fuera del borde del borde exterior. El “resto de la sombra”, la parte que puede suponer que siempre está detrás del elemento, no existe. Nunca se dibuja. Entonces obtienes resultados como este:

Un cuadro con un borde turquesa y una sombra de cuadro gruesa hacia el borde inferior derecho que se encuentra sobre un fondo turquesa.

Este es el resultado del lenguaje explícito en el Módulo CSS Background and Borders, Nivel 3, sección 7.1.1:

Una sombra de cuadro exterior proyecta una sombra como si el cuadro de borde del elemento fuera opaco. Suponiendo una distancia de propagación de cero, su perímetro tiene exactamente el mismo tamaño y forma que el cuadro del borde. La sombra se dibuja solo fuera del borde del borde: se recorta dentro del cuadro de borde del elemento.

(Énfasis añadido.)

Borde y sombra de cuadro

Hablando de bordes, tal vez haya una manera de combinar bordes y sombras de cuadro. Después de todo, las sombras de cuadro pueden ser algo más que simples sombras paralelas. También se pueden encastrar. Entonces, ¿qué pasa si giramos la sombra anterior hacia adentro y colocamos un borde sobre ella?

.boxborder-me {
  box-shadow: 0 0 0 5px firebrick inset;
  border: dashed 5px darkturquoise;
}

Un cuadro con un borde turquesa discontinuo y un borde rojo sólido que se encuentra en el interior del borde discontinuo.

Eso… no es lo que buscábamos. Pero así es como funcionan las sombras insertadas: se dibujan dentro del borde de relleno exterior (también conocido como el borde del borde interior) y se recortan más allá:

Una sombra de caja interna proyecta una sombra como si todo lo que está fuera del borde del relleno fuera opaco. Suponiendo una distancia de propagación de cero, su perímetro tiene exactamente el mismo tamaño y forma que la caja de relleno. La sombra se dibuja solo dentro del borde de relleno: se recorta fuera del cuadro de relleno del elemento.

(Ibíd.; énfasis añadido).

Por lo tanto, no podemos apilar un borde encima de una sombra de cuadro insertada. ¿Tal vez podríamos apilar un borde encima de otra cosa…?

Frontera y múltiples fondos

Las sombras insertadas pueden estar restringidas al borde del relleno exterior, pero los fondos no. El fondo de un elemento, por defecto, llenará el área hasta el borde del borde exterior. Rellene el fondo de un elemento con un color sólido, dele un borde discontinuo grueso y verá el color de fondo entre las partes visibles del borde.

Entonces, ¿qué pasa si apilamos algunos fondos uno encima del otro y dibujamos el color sólido que queremos detrás del borde? Aquí está el paso uno:

.multibg-me {
  border: 5px dashed firebrick;
  background:
    linear-gradient(to right, darkturquoise, 5px, transparent 5px);
  background-origin: border-box;
}

Un cuadro con un borde rojo discontinuo y un fondo turquesa que llena los espacios entre guiones a lo largo del borde izquierdo del cuadro.

Podemos ver, allí en el lado izquierdo, el fondo azul visible a través de las partes transparentes del borde rojo discontinuo. Agregue tres más así, uno para cada borde del cuadro del elemento, y:

.multibg-me {
  border: 5px dashed firebrick;
  background:
    linear-gradient(to top, darkturquoise, 5px, transparent 5px),
    linear-gradient(to right, darkturquoise, 5px, transparent 5px),
    linear-gradient(to bottom, darkturquoise, 5px, transparent 5px),
    linear-gradient(to left, darkturquoise, 5px, transparent 5px);
  background-origin: border-box;
}

Un cuadro con un borde rojo discontinuo y un fondo turquesa que llena los espacios entre guiones.

En cada caso, el degradado de fondo se ejecuta durante cinco píxeles como un fondo turquesa oscuro sólido y luego tiene una parada de color que cambia instantáneamente a transparente. Esto permite que el “telón de fondo” se muestre a través del elemento sin dejar de brindarnos un “borde apilado”.

Una gran ventaja aquí es que no estamos limitados a gradientes lineales sólidos: podemos usar cualquier gradiente de cualquier complejidad, solo para animar un poco las cosas. Tome este ejemplo, donde el borde punteado se ha hecho casi transparente para que podamos ver los cuatro gradientes diferentes en su totalidad:

.multibg-me {
  border: 15px dashed rgba(128,0,0,0.1);
  background:
    linear-gradient(to top,    darkturquoise, red 15px, transparent 15px),
    linear-gradient(to right,  darkturquoise, red 15px, transparent 15px),
    linear-gradient(to bottom, darkturquoise, red 15px, transparent 15px),
    linear-gradient(to left,   darkturquoise, red 15px, transparent 15px);
  background-origin: border-box;
}

Un diagrama que muestra el mismo cuadro con un borde rojo discontinuo y un fondo turquesa, pero con transparencia para mostrar cómo se superponen los bordes apilados.

Si observa las esquinas, verá que los degradados de fondo son rectangulares y se superponen entre sí. No se juntan ordenadamente, como lo hacen las esquinas fronterizas. Esto puede ser un problema si su borde tiene partes transparentes en las esquinas, como sería el caso de border-style: double.
Además, si solo desea un color sólido detrás del borde, esta es una forma bastante torpe de unir ese efecto. Seguramente debe haber un mejor enfoque?

Recorte de bordes y fondos

¡Sí hay! Se trata de cambiar los cuadros de recorte por dos capas diferentes del fondo del elemento. Lo primero que puede venir a la mente es algo como esto:

.multibg-me {
  border: 5px dashed firebrick;
  background: #EEE, darkturquoise;
  background-clip: padding-box, border-box;
}

Pero eso no funciona, porque CSS requiere que solo el último fondo (y por lo tanto el más bajo) se establezca en un <color> valor. Cualquier otra capa de fondo debe ser una imagen.

Así que reemplazamos ese color de fondo gris muy claro con un degradado de ese color a ese color: esto funciona porque los degradados son imágenes. En otras palabras:

.multibg-me {
  border: 5px dashed firebrickred;
  background: linear-gradient(to top, #EEE, #EEE), darkturquoise;
  background-clip: padding-box, border-box;
}

Un cuadro con un borde rojo punteado, un fondo turquesa para rellenar los espacios entre guiones y un fondo gris claro dentro del cuadro.

El “degradado” gris claro llena toda el área de fondo, pero se recorta al cuadro de relleno usando background-clip. El turquesa oscuro llena toda el área y se recorta en el cuadro del borde, como siempre lo han sido los fondos de forma predeterminada. Podemos alterar los colores y la dirección del degradado a lo que queramos, creando un degradado visible real o cambiándolo a todo blanco o cualquier otro efecto lineal que deseemos.

La desventaja aquí es que no hay forma de hacer que el fondo del área de relleno sea transparente de modo que el fondo del elemento se pueda ver a través del elemento. Si el degradado lineal se hace transparente, todo el fondo del elemento se rellenará con un turquesa oscuro. O, más precisamente, podremos ver el turquesa oscuro que siempre estuvo ahí.

En muchos casos, no importará que el fondo del elemento no sea transparente, pero sigue siendo una limitación frustrante. ¿No hay alguna manera de obtener el efecto de los bordes apilados sin trucos extravagantes y capacidades perdidas?

Imágenes de borde

De hecho, ¿qué pasaría si pudiéramos tomar una imagen del borde apilado que queremos ver en el mundo, cortarlo y usarlo como borde? Como, digamos, ¿esta imagen se convierte en este borde?

Una imagen de dos cajas apiladas, la parte superior es una caja cuadrada con un borde rojo punteado y un fondo con rayas turquesas y doradas que llena los espacios entre las rayas.  El cuadro inferior es una demostración que utiliza el cuadro superior como imagen de borde para el cuadro inferior.

Aquí está el código para hacer exactamente eso:

.borderimage-me {
  border: solid 5px;
  border-image: url(triple-stack-border.gif) 15 / 15px round;
}

Primero, establecemos un borde sólido con algo de ancho. También podríamos establecer un color con fines alternativos, pero en realidad no es necesario. Luego apuntamos a una URL de imagen, definimos la(s) inserción(es) de corte en 15 y el ancho del borde a ser 15px, y finalmente el patrón repetido de round.

Hay más opciones para las imágenes de borde, que son un poco demasiado complejas para entrar aquí, pero el resultado es que puede tomar una imagen, definir nueve cortes de ella usando valores de compensación y hacer que esas imágenes se usen para sintetizar un borde completo alrededor. una imagen. Eso se hace definiendo compensaciones desde los bordes de la propia imagen, que en este caso es 15. Dado que la imagen es un GIF y, por lo tanto, está basada en píxeles, las compensaciones están en píxeles, por lo que las “líneas de corte” se establecen 15 píxeles hacia adentro desde los bordes de la imagen. (En el caso de un SVG, las compensaciones se miden en términos del sistema de coordenadas del SVG). Se ve así:

Un diagrama que describe cómo se corta y coloca la imagen del borde a lo largo de los bordes, las esquinas y los desplazamientos del cuadro.

Cada corte se asigna a la esquina o lado de la caja del elemento que le corresponde; es decir, la división de la esquina inferior derecha se coloca en la esquina inferior derecha del elemento, la división superior (central) se usa a lo largo del borde superior del elemento, y así sucesivamente.

Si uno de los cortes del borde es más pequeño que el largo del borde del elemento, lo que casi siempre sucede, y ciertamente es cierto aquí, entonces el corte se repite en una de varias maneras. Elegí round, que completa tantas repeticiones como puede y luego las escala lo suficiente para completar el borde. Por lo tanto, con un corte de 70 píxeles de largo, si el borde tiene 1337 píxeles de largo, habrá 19 repeticiones del corte, cada una de las cuales tiene una escala de 70,3 píxeles de ancho. O, más probablemente, el navegador genera una sola imagen que contiene 19 repeticiones de 1330 píxeles de ancho y luego amplía esa imagen los 7 píxeles adicionales.

Puede pensar que el inconveniente aquí es la compatibilidad con el navegador, pero resulta que ese no es el caso.

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
56 50 11 12 9.1

Móvil / Tableta

Android cromo android firefox Androide iOSSafari
96 95 96 9.3

Solo tenga cuidado con los pocos errores (en realidad, los límites de implementación) que persisten en un par de implementaciones, y estará bien.

Conclusión

Si bien puede ser una circunstancia rara en la que desee combinar múltiples efectos de “borde” o apilarlos uno encima del otro, es bueno saber que CSS proporciona varias formas de hacer el trabajo, y que la mayoría de ellos ya son ampliamente utilizados. soportado. ¿Y quien sabe? Tal vez algún día haya una forma sencilla de lograr este tipo de efectos a través de una sola propiedad, en lugar de mezclar varias. Hasta entonces, ¡feliz apilamiento de bordes!

(Visited 1 times, 1 visits today)