Saltar al contenido

mask: alfa y luminancia

Las máscaras trabajan con valores continuos, y por defecto los sacan de la luminancia y no del alfa. Qué significa eso, cómo se cambia con mask-type, y el desvanecimiento que solo la máscara permite.

Luminancia por omisión

Un elemento mask contiene marcado que se renderiza en un búfer aparte. De ese búfer se saca, para cada píxel, un valor entre 0 y 1 que multiplica la opacidad del elemento enmascarado.

Cómo se saca ese valor lo decide mask-type, cuyo valor inicial en SVG es luminance. En ese modo, el valor de la máscara es la luminancia del color multiplicada por su alfa. Es decir: blanco opaco da 1, negro opaco da 0, y un gris medio da algo intermedio. El alfa también cuenta: un blanco al 50 por ciento da 0,5.

HTML
<svg viewBox="0 0 200 100" width="400">  <defs>    <mask id="m">      <rect width="200" height="100" fill="#000" />      <circle cx="100" cy="50" r="40" fill="#fff" />    </mask>  </defs>  <rect width="200" height="100" fill="#89b4fa" mask="url(#m)" /></svg>

Solo se ve el círculo. El rectángulo negro de fondo de la máscara es lo que oculta el resto; sin él, el fondo de la máscara es transparente, cuya luminancia efectiva es cero, y el resultado sería el mismo. Pero conviene ponerlo explícito porque deja clara la intención y porque en modo alfa el comportamiento sí cambia.

La consecuencia práctica de la luminancia: los colores importan y no solo la opacidad. Un #ff0000 opaco tiene una luminancia de aproximadamente 0,21 en el cálculo estándar, así que como máscara oculta casi todo. Un #00ff00 tiene 0,72 y deja pasar casi todo. Si construyes una máscara con la ilustración a color, el resultado es una transparencia que sigue el brillo de los colores, y eso rara vez es lo que querías.

Regla: dentro de una máscara en modo luminancia, usa solo blanco, negro y grises. Cualquier color introduce una variable que no controlas.

mask-type y el modo alfa

mask-type es una propiedad CSS que se aplica al elemento mask, no al elemento enmascarado. Acepta luminance (inicial) y alpha.

HTML
<mask id="ma" style="mask-type: alpha">  <circle cx="100" cy="50" r="40" fill="#000" /></mask>

En modo alfa, el valor de la máscara es directamente el canal alfa. El color deja de importar: un círculo negro opaco muestra lo que hay debajo exactamente igual que uno blanco opaco.

Cuándo usar cada uno:

Luminancia cuando la máscara es un degradado en escala de grises, una textura o una imagen. Es el modo pensado para eso, y es el que da control fino con un solo canal.

Alfa cuando la máscara son formas dibujadas. Es más intuitivo (pintar una forma la hace visible, sin importar el color), evita el error del color, y es lo que hacen las herramientas de diseño. Si vienes de Figma o de un editor de imagen, mask-type: alpha es el modo que reconoces.

Hay una tercera pieza en el juego: la propiedad mask-mode, que se aplica al elemento enmascarado y permite sobrescribir el modo para esa aplicación concreta. Su soporte ha sido desigual entre motores, así que la vía fiable es mask-type en el propio mask, que es donde el modo pertenece de todas formas.

El desvanecimiento

El uso más frecuente de la máscara, y el que no tiene alternativa con recorte, es el desvanecimiento de un borde:

HTML
<svg viewBox="0 0 220 90" width="440">  <defs>    <linearGradient id="fade" x1="0" y1="0" x2="1" y2="0">      <stop offset="0"    stop-color="#fff" />      <stop offset="0.7"  stop-color="#fff" />      <stop offset="1"    stop-color="#000" />    </linearGradient>    <mask id="mfade">      <rect width="220" height="90" fill="url(#fade)" />    </mask>  </defs>  <g mask="url(#mfade)">    <rect width="220" height="90" fill="#313244" />    <text x="12" y="55" font-size="28" fill="#cdd6f4"          font-family="system-ui, sans-serif">Texto que se desvanece</text>  </g></svg>

El grupo entero se desvanece hacia la derecha. Fíjate en que la máscara se aplica al g: si se aplicara a cada hijo por separado, el fondo y el texto se desvanecerían de forma independiente y el resultado sería otro.

El mismo patrón en CSS se escribe con mask-image: linear-gradient(...) y es una de las cosas que más se usan de todo este nivel: la lista con scroll que se difumina en los bordes, la marquesina que entra y sale, el texto truncado con degradado en lugar de puntos suspensivos.

Una precisión sobre el degradado de la máscara: como la máscara está en modo luminancia, la parada final tiene que ser negro, no transparente. Si pones transparent, funciona igual (luminancia cero, alfa cero, producto cero) pero la zona intermedia arrastra el problema de la interpolación hacia negro que se explicó en el nivel 20, y el desvanecimiento no es lineal. Con negro explícito, la transición es la que dice el gradiente.

Máscaras con textura

Como el contenido de la máscara es marcado SVG completo, dentro puede ir cualquier cosa: una imagen, un patrón, un filtro de ruido.

HTML
<defs>  <filter id="ruido">    <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="3" />    <feColorMatrix type="saturate" values="0" />  </filter>  <mask id="desgaste">    <rect width="200" height="100" fill="#fff" />    <rect width="200" height="100" filter="url(#ruido)" style="mix-blend-mode: multiply" />  </mask></defs>

Un ruido fractal desaturado multiplicado sobre blanco produce una máscara moteada, y el elemento enmascarado sale con aspecto de tinta gastada. Las primitivas de filtro que aparecen ahí son el tema del nivel 22.