La renderización de HTML se basa en el modelo de caja, pero la vida (y el diseño web) son mucho más que rectángulos. CSS admite varias formas de cambiar las áreas de un elemento que se renderizan, lo que les da a los desarrolladores la libertad de crear diseños que admitan todas las formas y tamaños. El recorte permite formas geométricas, mientras que el enmascaramiento afecta la visibilidad a nivel de píxel.
Rutas y formas
CSS usa funciones para definir formas. En el módulo de funciones de CSS, se incluye información general sobre las funciones. En esta sección, aprenderás a crear formas en CSS. Todos los siguientes ejemplos usan las formas que creas con la propiedad clip-path
, lo que reduce el área visible solo a lo que está dentro de la forma. Esto permite que los elementos difieran visualmente de la caja del elemento. Más adelante, analizaremos el recorte con mayor detalle.
Las formas definidas en CSS pueden ser formas básicas (como círculos, rectángulos y polígonos) o rutas (que pueden definir formas complejas y compuestas).
Formas básicas
circle()
y ellipse()
Las funciones circle()
y ellipse()
definen formas redondas y ovaladas con radios relativos a un elemento. La función circle()
acepta un solo tamaño o porcentaje como argumento. De forma predeterminada, ambas funciones posicionan la forma en relación con el centro del elemento. Ambas aceptan una posición opcional después de la palabra clave at
, que se puede expresar como longitudes, porcentajes o palabras clave posicionales.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: circle(50%);
}
En el ejemplo anterior, se muestra una ruta de recorte circular con la función circle()
. Ten en cuenta que un radio de 50%
crea un círculo con el ancho completo del elemento. La función ellipse()
acepta dos argumentos que representan los radios horizontales y verticales de la forma.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: ellipse(50% 25%);
}
En el ejemplo anterior, se muestra una ruta de recorte elíptica con la función ellipse()
. Ten en cuenta que un radio del 50% crea una elipse con el ancho completo del elemento. En el siguiente ejemplo, se muestra la misma elipse posicionada con su centro en la parte superior del elemento.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: ellipse(50% 25% at center top);
}
rect()
y inset()
Las funciones rect()
y inset()
proporcionan diferentes formas de definir un rectángulo estableciendo la posición de sus lados en relación con los lados de un elemento. Esto te permite crear rectángulos que difieren visualmente del cuadro predeterminado del elemento. Opcionalmente, aceptan la palabra clave round
para crear un rectángulo con esquinas redondeadas, con la misma sintaxis que la propiedad abreviada border-radius
.
La función rect()
define la posición de los lados superior e inferior del rectángulo en relación con el borde superior del elemento, y los lados izquierdo y derecho en relación con el borde izquierdo del elemento. Esta función acepta cuatro unidades de tamaño o porcentaje como argumentos que definen los lados superior, derecho, inferior e izquierdo. Puedes elegir la función rect()
cuando quieras un rectángulo que no se ajuste cuando cambia el tamaño del elemento o uno que mantenga las mismas proporciones a medida que cambia el elemento.
.my-element {
width: 80px;
height: 60px;
background: blue;
clip-path: rect(15px 75px 45px 10px);
}
En el ejemplo anterior, se muestra una ruta de recorte rectangular definida con la función rect()
. Las dimensiones son relativas a los bordes superior e izquierdo del elemento, como se muestra en el diagrama.
La función inset()
define la posición de los lados de un rectángulo según la distancia hacia adentro desde cada uno de los lados de un elemento. Esta función acepta de una a cuatro unidades de tamaño o porcentaje como argumentos, lo que te permite definir varios lados a la vez. Puedes elegir la función inset()
cuando quieras un rectángulo que se ajuste al tamaño del elemento o un rectángulo que tenga una distancia fija desde los bordes del elemento.
.my-element {
width: 80px;
height: 60px;
background: blue;
clip-path: inset(15px 5px 15px 10px);
}
En el ejemplo anterior, se muestra una ruta de recorte rectangular definida con la función inset()
. Las dimensiones son relativas a los lados del elemento.
Las funciones rect()
y inset()
aceptan de forma opcional la palabra clave round
para crear un rectángulo con esquinas redondeadas, con la misma sintaxis que la propiedad abreviada border-radius
. En el siguiente ejemplo, se muestran versiones redondeadas de los rectángulos que se mostraron anteriormente.
.rounded-rect {
width: 80px;
height: 60px;
background: blue;
clip-path: inset(15px 5px 15px 10px round 5px);
}
.rounded-inset {
width: 80px;
height: 60px;
background: blue;
clip-path: inset(15px 5px 15px 10px round 5px);
}
polygon()
Para otras formas, como triángulos, pentágonos, estrellas, etcétera, la función polygon()
te permite crear formas conectando varios puntos con líneas rectas. La función polygon()
acepta una lista de pares que constan de dos unidades de longitud o porcentaje. Cada par describe un punto del polígono: el primer valor es la distancia desde el borde izquierdo del elemento, y el segundo es la distancia desde el borde superior del elemento. No es necesario que cierres el polígono, ya que se completará conectando el último punto con el primero.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: polygon(
50% 0,
0 100%,
100% 100%
);
}
En el ejemplo anterior, se crea una ruta de recorte triangular definiendo tres puntos.
De forma predeterminada, la función polygon()
renderiza las áreas superpuestas como rellenadas. Puedes cambiar este comportamiento con un primer argumento opcional llamado regla de relleno. Para alternar entre áreas completas y no completas, establece la regla de relleno en evenodd
. Para usar la regla de relleno predeterminada, configúrala en nonzero
.
En el ejemplo anterior, se muestra la función polygon()
con funciones trigonométricas para crear polígonos regulares y formas de estrella. Esto no crea el polígono regular más grande posible que quepa dentro de un elemento ni lo centra. Te dejamos eso como ejercicio para que lo intentes. Las formas de estrella de este ejemplo también demuestran las reglas de relleno nonzero
y evenodd
.
Formas complejas
Cuando las funciones de forma básica no son suficientes para describir una forma compleja, CSS proporciona funciones que usan una sintaxis más sofisticada para describir características como curvas y líneas. Estas funciones también son útiles para las formas compuestas (formas que se componen de varias formas, como un círculo con un agujero).
path()
La función path()
acepta una cadena de sintaxis de ruta de SVG para describir una forma. Esto permite crear formas complejas con instrucciones que describen las líneas y las curvas que componen la forma. Editar directamente la sintaxis de SVG puede ser complicado, por lo que te recomendamos que consideres usar un editor visual específico que pueda exportar la sintaxis cuando crees formas con la función path()
.
La función path()
no usa unidades de tamaño de CSS, y todos los valores se interpretan como píxeles. Esto significa que las formas creadas con la función path no responden al tamaño del elemento o contenedor. Recomendamos usar path()
solo para formas que tengan dimensiones fijas.
shape()
La función shape()
usa una sintaxis de comando para describir una forma, similar a la función path()
. Sin embargo, los comandos de la función shape()
son CSS nativos y pueden usar unidades de tamaño de CSS. Esto permite que las formas definidas con la función shape()
se dimensionen de forma responsiva.
En el ejemplo anterior, se usan las funciones path()
y shape()
para definir una forma de corazón y un círculo con un agujero en el centro. En el ejemplo, se usa el mismo valor en píxeles para ambas funciones, pero las funciones shape()
también podrían haber usado otras unidades de tamaño de CSS, como porcentajes o unidades relativas al contenedor.
Recorte
El recorte define qué áreas de un elemento son visibles, de manera similar a cuando se recorta una imagen de una revista. La propiedad clip-path
establece la ruta de acceso que se usa para definir el área de recorte.
Como viste en los ejemplos de la sección anterior, cualquiera de las funciones básicas de forma o ruta se puede usar como clip-path
. La propiedad clip-path
también admite rutas definidas en un elemento clipPath
SVG, que puede estar incorporado o en un archivo separado.
En el diagrama anterior, se muestra cómo la adición de un clip-path
a un elemento de imagen cambia el área visible de la imagen. La ruta de recorte superior usa la función circle()
, mientras que la inferior usa un clipPath
de SVG. Ten en cuenta que el círculo creado con la función circle()
se centra en el elemento de forma predeterminada.
La propiedad clip-path
solo acepta una sola ruta de acceso. Para recortar un elemento con varias formas que no se superponen, usa las funciones path()
o shape()
para definir una ruta compuesta, o bien usa un clipPath
SVG. Otra opción para situaciones complejas es usar el enmascaramiento en lugar del recorte, lo que se abordará en una sección posterior.
Recorte con formas
Para realizar el recorte con una forma básica o una función de ruta, establece la propiedad clip-path
en el valor que devuelve la función, como en los ejemplos anteriores. Cada función posicionará la forma de recorte de manera diferente en relación con el elemento, por lo que debes consultar la referencia de cada función.
En el ejemplo anterior, se aplicó un clip-path
circular a dos elementos con la clase .clipped
. Ten en cuenta que el clip-path
se posiciona en relación con cada elemento y que el texto dentro del clip-path
no se redistribuye para seguir la forma.
Caja de referencia de una ruta de recorte
De forma predeterminada, la ruta de recorte de un elemento incluye su borde. Cuando usas una de las funciones de forma básica, puedes establecer el cuadro de referencia de la ruta de recorte para que incluya solo el área del elemento dentro del borde. Los valores válidos para la caja de referencia son stroke-box
(el valor predeterminado) y fill-box
(para incluir solo el área dentro del borde).
En el ejemplo anterior, se muestran elementos con un borde grande (20px
), cada uno con la función inset()
para establecer el clip-path
. El elemento que recorta en relación con el borde del elemento aún muestra una parte del borde. Los elementos que se recortan en relación con el área dentro del borde no muestran ningún borde y son más pequeños, incluso con el mismo valor de inserción.
Recorte con gráficos
Se puede definir una ruta de recorte en un documento SVG, ya sea incorporada en el documento HTML o a la que se haga referencia de forma externa. Esto puede ser útil para definir trazados de recorte complejos creados en programas de gráficos o trazados de recorte que combinan varias formas.
<img id="kitten" src="kitten.png">
<svg>
<defs>
<clipPath id="kitten-clip-shape">
<circle cx="130" cy="175" r="100" />
</clipPath>
</defs>
</svg>
<style>
#kitten {
clip-path: url(#kitten-clip-shape);
}
</style>
En el ejemplo anterior, el clipPath
con un id
de kitten-clip-shape
se aplica al elemento <img>
. En este caso, el documento SVG está incorporado en el HTML. Si el documento SVG es un archivo externo llamado kitten-clipper.svg
, entonces se haría referencia a clipPath
como url(kitten-clipper.svg#kitten-clip-shape)
.
Enmascaramiento
El enmascaramiento es otro método para definir qué áreas de un elemento se muestran o se ocultan. Mientras que el recorte usa formas o rutas básicas, el enmascaramiento usa los píxeles de una imagen o un gradiente para determinar la visibilidad. A diferencia del recorte, el enmascaramiento permite que las áreas de un elemento sean parcialmente transparentes. Se pueden aplicar varias imágenes de máscara a un elemento para producir una variedad de efectos.
Para aplicar una máscara, establece la propiedad mask-image
. Esta propiedad acepta una o más imágenes, degradados o referencias a elementos <mask>
en un documento SVG. Se pueden aplicar varias imágenes de máscara separándolas con comas.
.my-element {
mask-image: url(my-mask.png),
linear-gradient(black 0%, transparent 100%);
}
En el ejemplo anterior, .my-element
se enmascara con una imagen PNG, seguida de un gradiente lineal. De forma predeterminada, se suman varias máscaras para crear la máscara final.
En el ejemplo anterior, se muestra una imagen con una o más máscaras aplicadas. Activa o desactiva cada máscara para ver cómo se combinan y producen el efecto final.
Máscara alfa en comparación con la máscara de luminancia
Puedes aplicar una máscara con el alpha
o el luminance
de la imagen. Cuando se enmascara en función de alpha
, la transparencia de cada píxel de la imagen de máscara se aplica al elemento, y se ignora la información de color de ese píxel. Cuando se aplica una máscara basada en luminance
, tanto la transparencia como el valor de cada píxel (qué tan brillante u oscuro es) se aplican al elemento. El enmascaramiento por luminancia trata los colores más brillantes como visibles y los más oscuros como invisibles.
Para establecer el modo de enmascaramiento, usa la propiedad mask-mode
. De forma predeterminada, la propiedad mask-mode
se establece en match-source
, lo que establece un modo basado en el tipo de imagen de máscara. En el caso de las imágenes y los gradientes, el valor predeterminado será alpha
. En el caso de las máscaras SVG, el valor predeterminado será el valor de la propiedad mask-type
del elemento <mask>
o luminance
, si no se define ningún mask-type
.
En el ejemplo anterior, se usa un patrón de prueba que muestra diferentes valores de color y alfa como máscara. Si activas o desactivas el botón de activación mask-mode
, puedes ver cómo el modo alpha
se basa en la transparencia, mientras que el modo luminance
se basa en el brillo y la transparencia del color.
Propiedades de enmascaramiento adicionales
CSS proporciona propiedades adicionales para ajustar el comportamiento de tus máscaras. Cada una de las propiedades acepta una lista de valores separados por comas, que se compararán con la lista de máscaras establecida por la propiedad mask-image
. Si hay menos valores que máscaras, la lista se repetirá hasta que se haya establecido un valor para cada máscara. Si hay más valores que máscaras, se descartan los valores excedentes.
Propiedad | Descripción |
---|---|
mask-clip |
Establece a qué caja de referencia de las máscaras de elementos se aplican. La configuración predeterminada es |
mask-composite |
Establece la interacción entre máscaras cuando se aplican varias máscaras al mismo elemento. La configuración predeterminada es |
mask-origin |
Establece el cuadro de referencia que actúa como origen de una máscara. La configuración predeterminada es |
mask-position |
Establece la posición de una máscara en relación con el |
mask-repeat |
Establece cómo se repite una máscara si el elemento enmascarado es más grande que la máscara. La configuración predeterminada es |
mask-size |
Establece cómo se cambia el tamaño de una máscara en relación con el tamaño del elemento enmascarado. La configuración predeterminada es |
La abreviatura de la máscara
Puedes establecer varias propiedades de máscara a la vez con la abreviatura de máscara. Esto puede simplificar la configuración de varias máscaras agrupando todas las propiedades de cada máscara. La abreviatura de máscara equivale a configurar estas propiedades en el siguiente orden: mask-image
, mask-mode
, mask-position
, mask-size
, mask-repeat
, mask-origin
, mask-clip
y mask-composite
. No es necesario incluir todas las propiedades, y las que no se incluyan se restablecerán a su valor inicial. Con la compatibilidad de hasta ocho propiedades por máscara, puede ser útil tener una referencia completa disponible.
.longhand {
mask-image: linear-gradient(white, black),
linear-gradient(90deg, black, transparent);
mask-mode: luminance, alpha;
mask-position: bottom left, top right;
mask-size: 50% 50%, 30% 30%;
}
.shorthand {
mask: linear-gradient(white, black) luminance bottom left / 50% 50%,
linear-gradient(90deg, black, transparent) alpha top right / 30% 30%;
}
En el ejemplo anterior, cada clase tiene dos máscaras aplicadas. El primero usa propiedades individuales, mientras que el segundo usa la abreviatura mask
. Ambos estilos son equivalentes.
Texto que fluye alrededor de elementos flotantes
Cuando recortas o enmascaras un elemento, solo cambias el área visible dentro de su caja, pero la caja en sí permanece sin cambios. Esto significa que un elemento flotante afectará el flujo del documento según su cuadro delimitador original, no las partes visibles del elemento. Para definir el flujo alrededor de un elemento, usa la propiedad shape-outside
junto con la ruta de recorte.
La propiedad shape-outside
define la forma alrededor de la cual fluirá el contenido de un elemento. Esta forma puede ser cualquiera de las funciones de forma básica, pero no las formas definidas con las funciones path()
o shape()
, ni un clipPath
definido en un documento SVG.
La propiedad shape-outside
también acepta una imagen o un degradado. Al igual que con el enmascaramiento, los límites de la forma se determinarán según la transparencia de la imagen o el degradado. La propiedad shape-image-threshold
establece qué niveles de transparencia se consideran dentro de la forma.
Formas en la animación
Cómo animar clip-path
Puedes animar la propiedad clip-path
, combinando formas. Debes usar la misma función de forma para cada fotograma clave y producir animaciones fluidas. Cuando se usan las funciones polygon()
o shape()
, se debe usar la misma cantidad de puntos en cada fotograma clave.
En el ejemplo anterior, el clip-path
de un elemento realiza una transición entre un pentágono y una forma de estrella definidos con la función polygon()
. En el ejemplo, se usa la regla de relleno evenodd
para mostrar cómo los puntos de animación crean áreas superpuestas.
Cómo animar con offset-path
También puedes animar elementos a lo largo de las rutas creadas con estas funciones de forma. La propiedad offset-path
establece la forma que se usará como ruta, y offset-distance
establece la posición a lo largo de esa ruta. También puedes usar la función ray()
con la propiedad offset-path
para animar a lo largo de una línea recta.
En el ejemplo anterior, se muestra el uso del mismo polígono para un clip-path
y un offset-path
. La animación usa offset-distance
para mover las estrellas más pequeñas a lo largo del mismo polígono que la estrella grande usa como su clip-path
.
Verifica tus conocimientos
¿Cuáles de las siguientes son funciones de forma válidas?
circle()
square()
hexagon()
polygon()
rectangle()
inset()
Verdadero o falso: Las formas definidas con la función path()
se pueden definir con porcentajes.
Verdadero o falso: Establecer la ruta de recorte de un elemento no cambiará el flujo de texto alrededor de él.
¿Cuál de las siguientes opciones se puede usar como ruta de recorte?
clipMask
SVG¿Cuál de las siguientes opciones se puede usar como máscara?
circle()
o rect()