wandres.dev
RECORTE Y MÁSCARA · clipPath y mask en SVG

Elegir entre recorte y máscara

La tabla de decisión completa: borde, eventos, coste, animabilidad, exportación e impresión. Y las combinaciones donde hacen falta los dos.

⏱ 15 min

Recorte y máscara resuelven el mismo problema aparente (mostrar una parte de algo) por caminos tan distintos que la elección casi nunca es cuestión de gusto. Hay seis dimensiones donde se comportan de forma opuesta, y en cuanto sabes cuál de las seis importa en tu caso, la decisión está tomada. Y hay situaciones donde la respuesta es usar los dos, uno dentro del otro.

🎯 Al terminar esta lección sabrás
  • Comparar recorte y máscara en las seis dimensiones que los diferencian.
  • Elegir la herramienta correcta para cinco casos concretos de interfaz.
  • Combinar recorte y máscara cuando ninguno de los dos basta.
  • Anticipar el comportamiento de ambos en impresión y en exportación.

Las seis dimensiones

Dimensión clipPath mask
Valor por píxel Binario, dentro o fuera Continuo, 0 a 1
Borde Duro, con antialiasing de un píxel Tan suave como quieras
Eventos de puntero Recorta el área sensible No la toca
Coste de composición Bajo, es una región de recorte Alto, dos búferes y una multiplicación
Aislamiento No crea grupo aislado Crea grupo aislado
Animabilidad Interpolable entre formas compatibles Se anima el contenido, no la propiedad

Cada fila decide un caso.

Los cinco casos

Uno: una foto con forma de hexágono. Borde duro, sin transparencia parcial, y quieres que solo el hexágono responda al clic. Recorte. Además es más barato y se imprime bien.

Dos: una lista con scroll que se difumina en los bordes. Transición continua, y el texto difuminado debe seguir siendo seleccionable. Máscara, con un degradado. El recorte produciría un corte en seco.

Tres: un texto relleno con una imagen. Binario, la forma la dan los glifos. Recorte con text dentro del clipPath, o background-clip: text si estás en HTML, que es más simple y tiene mejor soporte para este caso concreto.

Cuatro: un logotipo que aparece con una barrida de izquierda a derecha. La transición es continua y hay que animarla. Máscara con un degradado cuyo x1/x2 se anima, o con una máscara de CSS animando mask-position. El recorte también funcionaría (animando inset()) y da un borde duro; la elección depende de si el diseño quiere un borde nítido de barrido o uno difuso.

Cinco: un panel modal que oscurece el fondo salvo un agujero circular sobre un elemento destacado. El agujero tiene que dejar pasar los clics al elemento de debajo. Aquí ninguna de las dos sirve por sí sola, y es el caso de la combinación.

Combinar los dos

En el caso cinco, el velo oscuro se dibuja con una máscara que tiene un agujero (para que el borde del agujero sea suave), pero además hay que resolver los eventos. La máscara no los corta, así que el velo bloquea los clics del agujero.

La solución es un velo compuesto por dos elementos:

<div class="velo" aria-hidden="true"></div>
.velo {
  position: fixed;
  inset: 0;
  background: rgb(0 0 0 / .7);
  pointer-events: none;                    /* deja pasar todo */
  mask:
    radial-gradient(circle 90px at var(--x) var(--y),
                    transparent 0 70%, #000 100%);
}

El pointer-events: none hace que el velo no capture nada, y la máscara le da el agujero suave. La zona oscura tampoco captura clics, lo que en un modal de verdad no sirve; para eso se añade un segundo elemento con clip-path que sí capture, con el agujero recortado. Pero para un resaltado de onboarding, donde solo quieres que el usuario pueda pulsar el elemento destacado y el resto de la interfaz sea navegable, el velo pasivo es exactamente lo correcto.

Otro caso de combinación frecuente: recortar para la geometría y enmascarar para el desvanecimiento.

.tarjeta-foto {
  clip-path: inset(0 round 16px);   /* esquinas duras y limpias */
  mask: linear-gradient(to top, transparent, #000 40%);
}

El recorte da las esquinas redondeadas con borde nítido y corta los eventos; la máscara desvanece la parte inferior para que el texto superpuesto se lea. Las dos operaciones se aplican en cadena y no interfieren.

En impresión y en exportación se comportan de forma distinta, y eso decide más de lo que parece

Hay una séptima dimensión que no aparece en las listas y que en algunos proyectos manda sobre todas las demás.

Impresión. Un clipPath es una operación vectorial: el motor de impresión y el generador de PDF la reproducen como un trazado de recorte nativo, que es una primitiva de PostScript. El resultado se imprime nítido a cualquier resolución. Una mask no tiene equivalente vectorial: para imprimirla hay que rasterizar el elemento enmascarado a una resolución concreta y meter un mapa de bits en el PDF. El resultado pesa más y puede salir borroso o pixelado según la resolución que elija el motor. Si tu documento se imprime o se exporta a PDF, el recorte es la opción que se comporta.

Exportación a imagen desde el navegador. El mismo razonamiento con otro final: al dibujar un SVG en un lienzo para generar un PNG, la máscara se rasteriza correctamente porque el destino ya es un mapa de bits. Aquí no hay diferencia.

Renderizado en servidor. Las bibliotecas que convierten SVG a imagen fuera del navegador tienen soporte desigual de mask y bueno de clipPath, porque el recorte es más simple de implementar. Si tu gráfico se genera en el servidor para meterlo en un correo o en un informe, comprueba el soporte de máscara de tu biblioteca antes de depender de ella; el recorte es la apuesta segura.

La regla que resume las tres: el recorte es geometría y viaja bien; la máscara es composición y solo existe donde hay un compositor. Cuando el destino no es una pantalla, prefiere el recorte.

Cuándo ninguno de los dos es la respuesta

Tres casos donde la gente llega a este nivel buscando la herramienta y la herramienta es otra.

Ocultar la mitad de un elemento por un cambio de estado. Si el corte es rectangular y alineado con los ejes, overflow: hidden en un contenedor es más simple, más barato y se comporta mejor con el scroll.

Un borde con degradado. La técnica de dos máscaras con mask-composite: exclude funciona, y border-image con un linear-gradient es más directa y no crea grupo aislado. Comprueba primero si tu caso la admite.

Redondear las esquinas de un elemento. border-radius, siempre. Recorta el contenido, recorta los eventos, se imprime bien y es la primitiva que el motor tiene más optimizada. Un clip-path: inset(0 round 16px) hace lo mismo con más coste y sin la resolución proporcional de radios adyacentes.

Y una advertencia general: tanto clip-path como mask crean, en muchos motores, una capa de composición propia. Diez elementos enmascarados en una lista con scroll pueden multiplicar la memoria de vídeo y hacer que el scroll se entrecorte. Si el efecto es puramente decorativo y afecta a muchos elementos, mide antes de darlo por bueno.

⚔️ Reto práctico

Construye un resaltado de onboarding que oscurezca la página con un agujero circular sobre un botón concreto, y verifica tres cosas: que el borde del agujero es suave, que el botón resaltado se puede pulsar, y que el resto de la interfaz también responde. Después cambia la máscara por un recorte y comprueba qué se rompe y qué mejora. Anota cuál de las seis dimensiones ha sido decisiva.