Tuesday, May 10, 2016

Masking in the Browser with CSS and SVG

Masking is a technique that lets you display selected portions of an element or an image on the screen while hiding the rest. Web developers can use this technique in the browser via the mask property and the SVG mask element. These features allow you to display masking effects on images and other elements in the browser without using any kind of image editing software.

In this article, I'm going to show CSS and SVG masking capabilities in action, also making sure to include some info about current browser support issues.

At the time of writing, most code samples work only in WebKit browsers while SVG-based masks seem to enjoy wider browser support. Therefore, if you'd like to try out the examples, I recommend you use a WebKit browser like Chrome.

Masking on the Web

You can achieve masking effects on the web using clipping or masking.

Clipping involves laying a closed vector shape, like a circle or a polygon, on top of an image or an element. Any parts of the image behind the shape will be visible, while any parts outside the boundaries of the shape will be hidden. The shape's boundary is called the clip path, and you create it using the clip-path property.

Masking is done using a PNG image, CSS gradient, or an SVG element to hide some parts of an image or other element on the page. You can accomplish this using the CSS mask property.

In this article, I will focus exclusively on masking with the CSS mask property and the SVG <mask> element.

The CSS mask Property

mask is the CSS shorthand property for a whole bunch of individual properties. Let's take a closer look at some of them in more detail.

The mask-image Property

You can use the mask-image property to set the mask layer image of an element.

The value none is not the same as setting no value at all. On the contrary — it still counts as a transparent black image layer.

You can set mask-image to a URL value. This can be the path to a PNG image file, an SVG file, or a reference to an SVG <mask> element. You can set more than one mask image layer by adding a corresponding number of URL values separated by a comma.

Here are a few examples:

/* masking with two comma-separated values */
.masked-element {
  mask-image: url(mask.png), none;
}


/* using external svg graphic as mask */
.masked-element {
  mask-image: url(mask.svg);
}

This is how you reference an SVG <mask> element with an id of mask1:

.masked-element {
  mask-image: url(#mask1);
}

A gradient image is also a suitable value for the mask-image property:

.masked-element {
  mask-image: linear-gradient(black 0%, transparent 100%);
}

The mask-mode Property

With mask-mode you can set the mask layer image to be either an alpha mask or a luminance mask.

An alpha mask is an image with an alpha channel. In more detail, the alpha channel is the transparency information contained in each pixel's data. Masking operations with the mask-mode property set to alpha will use the image's alpha values as the mask values.

A handy example of an alpha channel is a PNG image with black and transparent areas. The masked element will show through the black portions of the mask image, which have an alpha value of one. Everything else beneath the transparent portions, which have an alpha value of zero, will be hidden.

I'm going to use this PNG image as my alpha mask:

Example of image to be used as alpha mask.

and perform a masking operation on the JPG image below:

Image to be masked.

This is where the magic happens:

.masked-element {
  mask-image: url(alpha-mask.png);
  mask-mode: alpha;
}

and here's what the result looks like in the browser:

Image masked using alpha or luminance mask-mode.

A luminance mask uses an image's luminance values as mask values. A PNG image like the one above — but in white — is a good example of a luminance mask:

Example of PNG image you can use as luminance mask.

The areas of the element you want to mask, which are covered by the mask's white pixels, will show through. The portions of the masked element covered by the mask's transparent pixels will be hidden.

Setting the mask-mode property to luminance and using the image above as my mask, will display the same result as before.

Here's the code:

.masked-element {
  mask-image: url(luminance-mask.png);
  mask-mode: luminance;
}

The mask-repeat Property

mask-repeat works pretty much like the background-repeat property. It controls the tiling of mask layer images after you've set their size and position.

Possible values are:

  • no-repeat: the mask layer image is not repeated across the available space.
  • repeat-x: the mask layer image is repeated along the X coordinate.
  • repeat-y: the mask layer image is repeated down the Y coordinate.
  • space: the mask layer image is repeated and spaced out throughout the available area.
  • round: the mask layer image is repeated a whole number of times across the available area. If a whole number doesn't fit in the available space, the image is scaled until it does.

For instance, this is the image I intend to use as my mask:

Example of mask layer image to use with mask-repeat property.

The code snippet below sets the mask-repeat property to a value of space:

.masked-element {
  mask-image: url(imgs/trapeze.png);
  mask-repeat: space;
}

resulting in the following masking effect:

Example of mask-repeat property set to the value of space as rendered in the browser.

The mask-position Property

You can position a mask layer image using the mask-position property. You can set this property to the same values you would use for the more familiar CSS background-image property. Its initial value is center.

For instance, if you want to place the mask image layer on the top left corner of the viewport, set the mask-position property to a value of 0 0:

.masked-element {
  mask-position: 0 0;
}

This is what the code above looks like in the browser:

Mask layer image positioned to the top left of the container.

Changing the value of the mask-position property above to 100% 100%, displays the mask layer image on the bottom right of the viewport:

Mask layer image placed on the bottom right of the viewport.

The mask-size Property

You can quickly set the size of your mask layer image using the mask-size property, which accepts the same values as the more familiar CSS background-size property.

For example, setting mask-size to 50% displays the mask layer image at 50% of its full width:

Mask layer image at half its full width using mask-size.

Setting mask-size to contain will scale the mask layer image to the largest size so that both its width and height can fit inside the mask positioning area:

Mask layer image sized using the contain keyword value.

You can see these demos live in action on CodePen below:

See the Pen CSS Mask Examples by SitePoint (@SitePoint) on CodePen.

Compositing Mask Layers

As explained above, you can use more than one mask layer on the same element by separating each value of the mask-image property with a comma. The layers get stacked one on top of the others with the last layer displaying first on the screen.

For instance:

.masked-element {
  mask-image: url(mask1.png), url(mask2.png);
}

Continue reading %Masking in the Browser with CSS and SVG%


by Maria Antonietta Perna via SitePoint

No comments:

Post a Comment