jueves, 27 de octubre de 2022

Cinta plegada CSS totalmente receptiva

En esta publicación, crearemos una cinta totalmente receptiva sin ancho ni alto codificados. El tamaño y la posición se ajustarán dinámicamente según el contenido y no vamos a usar una tonelada de HTML o JS. ¡Solo CSS!

Estructura del código:

  
<div class="container" data-ribbon="Ribbon content"></div>

  

Sí, solo uno div con el contenido de la cinta como atributo de datos.

  .container {
  --d:6px;  /* folded part */
  --c:blue; /* color */
  --f:16px; /* ribbon font-size */
  position: relative;
}
.container::before {
  content: attr(data-ribbon);
  font-size:var(--f);
  /* I : position & coloration */
  position: absolute;
  top: 0;
  right: 0;
  transform: translate(29.29%, -100%) rotate(45deg);
  transform-origin: bottom left;
  padding: 5px 35px calc(var(--d) + 5px);
  background: linear-gradient(rgba(0,0,0,0.5) 0 0) bottom/100% var(--d) no-repeat var(--c);
  /* II : clipping */
  clip-path: polygon(0 0,100% 0,100% 100%,calc(100% - var(--d)) calc(100% - var(--d)),var(--d) calc(100% - var(--d)) , 0 100%);
  /* III : masking */
  -webkit-mask: 
      linear-gradient( 135deg, transparent calc(50% - var(--d)*0.707),#fff 0) bottom left,
      linear-gradient(-135deg, transparent calc(50% - var(--d)*0.707),#fff 0) bottom right;
  -webkit-mask-size:300vmax 300vmax;
  -webkit-mask-composite: destination-in;
   mask-composite: intersect;
}

 

Posición y coloración

Coloreamos nuestro elemento usando dos capas. El color principal y una superposición negra en la parte inferior para la parte doblada. Luego lo colocamos en la esquina superior derecha.

ribbon

Ahora aplicamos una transformación para tener la ubicación correcta y la magia de la capacidad de respuesta está aquí (sí, es el 29.29% valor)

ribbon

Un poco de geometría para entender el 29.29%

ribbon

De lo anterior tenemos las siguientes fórmulas:

cos(45deg) = a/w ¿ Dónde westá el ancho de nuestro elemento?

x = w - a = w - w*cos(45deg) = w*(1-cos(45deg) = w*(1-0.70710678)

Asi que x = 0,29289322*w ~ 29.29%

Recorte

Usaremos clip-pathpara crear la parte doblada en la parte inferior

 
  clip-path: 
   polygon(
       0 0, /* a */
       100% 0, /* b */
       100% 100%, /* c */
       calc(100% - var(--d)) calc(100% - var(--d)), /* x */
       var(--d) calc(100% - var(--d)), /* y */
       0 100% /* d */
   );
   

ribbon

Enmascaramiento

El toque final es cortar las esquinas usando dos capas de máscara. El truco aquí es considerar un cuadrado grande con un gradiente diagonal en el interior y cortamos 50% considerando la parte doblada.

Una ilustración para explicar una esquina:

ribbon

Hacemos lo mismo para la otra esquina y consideramos la intersección de ambas capas de máscara usando mask-composite: intersect

¡Eso es todo!

Simplemente ajuste las variables y el contenido para controlar la cinta. Podemos moverlo fácilmente hacia el lado izquierdo ajustando ligeramente la transformación y la posición.

.left::before {
  left:0;
  right:auto;
  transform: translate(-29.29%, -100%) rotate(-45deg);
  transform-origin: bottom right;
}

Estoy agregando un borde transparente y usando un clip de fondo para evitar que aparezca un contorno incorrecto alrededor de la forma.



Fuentes de consulta: https://dev.to/ (inglés)



¡¡Aprender es interesante y divertido!!


Salu2 y bendiciones,
Atte, Angel Paz
Duda con el Efecto rayo 71pkhu