An Introduction to CSS Custom Filters — Shader Basics

The last couple of weeks I’ve been walking through the css filter effect spec as best as I could. First was a look at named filter functions, which was followed by a look at filter primitives. There’s one last css filtering topic to cover and that’s custom filters or css shaders.

Like filter primitives, shaders are a complex subject and there’s much more to cover than a single post or my understanding could do justice. Instead I want to cover the general concepts in the hopes of helping you understand what’s going on. Then I’ll point you to some additional resources that explain things in more depth along with some with demos so you can see what’s possible.

Chrome and Webkit Nightly lead the way in browser support, though there’s a long way to go before custom filters are supported everywhere.

series of graphics showing an element being processed with shaders
(Top row) The original element gets a source texture and a default vertex mesh. (Bottom row) The mesh is made finer, a vertex shader is applied, a fragment shader is applied.

CSS Shader Basics (Types and Process)

Custom filters are a way to extend the named filter functions we looked at a couple of weeks back. They were originally a separate spec on css shaders, but that spec has now been incorporated into the filter effects spec.

If you’ve worked with 3D graphics, you should be familiar with shaders. If you’re like me, you probably aren’t familiar with them. Shaders are basically small programs that manipulate the geometry and painting of objects.

CSS shaders hook into the browser’s rendering process so you can modify the shape and look of an element before it’s drawn by the browser. You use the OpenGL Shading Language (GLSL) for writing shaders

There are the 2 types of shaders available in custom filters.

  1. Vertex shaders — are about geometry and deforming and displacing objects in space (file type .vs)
  2. Fragment shaders — are about painting the surfaces of objects and modifying how pixels look (file type .fs)
The css shader process

The general process for applying shaders can be seen in the image directly above and in more detail in the image at the top of this post. It’s described below.

  1. An html or svg element is placed on a mesh.
  2. The mesh is then processed with a vertex shader, which distorts and deforms the element in 3D space.
  3. A fragment shader is invoked for every pixel inside the mesh to produce the final pixel color at each location.
  4. The rasterized output is displayed on the screen or the output becomes input for the next filter primitive.

To make more sense of what’s happening let’s consider the mesh.

The Vertex Mesh

The mesh is based on triangulated geometry. At a minimum it’s a single rectangle divided in half to form two triangles. The corners of the triangles are vertices, which we can manipulate with vertex shaders.

A single rectangle, double triangle mesh isn’t too interesting. Fortunately the mesh can be further subdivided into more and smaller rectangles and triangles, which then offer more possibilities for manipulation.

Default one rectangle, two triangle vertex mesh and the mesh refined
The default vertex mesh (left) is a single rectangle split into two triangles. It can be further subdivided to create a more refined mesh (right).

By moving the vertices around, the triangles inside are deformed or displaced in different ways. There are 2 types of grid geometry that can be created through css using the geometry descriptor.

  1. Detached — The triangles do not share adjacent edges so when a vertex is moved it doesn’t affect adjacent triangles. In other words you can break the mesh into individual components

  2. Attached — The triangles do share adjacent edges so moving a single vertex means all connected triangles are deformed. The gird itself is deformed instead of broken apart into separate components.

Fragment Shaders

Fragment shaders work more like the filters we’ve seen up to this point. They allow us to blur an element, saturate it, or rotate its hue. The difference is you’ll be defining these things in a custom shader or using one someone else created.

Just as with named filters these can be combined and chained. Ultimately they work the same way, with the key difference being these aren’t defined in css and needed to be defined and included to work.

Input Parameters

Both vertex and fragment shaders can take input parameters of 3 general kinds.

  1. uniform parameters — have a single value for all vertices and pixels of the mesh
  2. attribute parameters — have their own values for every vertex of the mesh
  3. varying parameters — are passed from vertex shader to fragment shader. They’re set on each vertex and the values for points inside the triangle are interpolated

An example of uniform parameters would be a solid color. Position would be an example of an attribute parameter. The play of light over a surface would be an example of a varying parameter.

Additional Resources

As I said at the start, this isn’t a topic I have a lot of experience with and the spec wasn’t the best source to improve my understanding. The articles below all did a much better job helping me learn the basics of custom filters and shaders and they offer more detail than I have here.

I also found some demos, which helped illustrate what shaders and custom filters can do. Remember you’ll need to use a browser that supports css shaders to see these demos, which will generally mean Chrome Canary or Webkit Nightly.

Closing Thoughts on CSS Filter Effects

CSS filter effects aren’t quite ready for production, though in some instances you might still use them for non-critical communication. Hopefully this multi-week look at filter effects has shown their potential. They may not be production ready now, but it’s hard to imagine them not being used once they are.

Of the 3 ways to add a filter, named functions are by far the easiest to use. Filter primitives require a bit more understanding about SVG, but aren’t too difficult to work with either. Shaders were the most complicated for me at first, though a few articles later I had decent understanding of what they’re all about, even if I haven’t yet experimented with them.

What I mostly hope you’ll take away from these 3 posts, as well as previous posts about future css, is that there’s some very powerful css coming and in some cases, probably not that far into the future. Front end development will get a bit more complicated, but a lot more interesting. These posts have been to encourage you to start exploring sooner in order to reduce some of the complicated when we are using these technologies in production.

Download a free sample from my book, Design Fundamentals.


    • I don’t think the shaders ever made their way into browser and I think they may have been dropped. CSS filters in general exist, but the shader stuff I talked about in this article never found its way into any browser.

Leave a Reply

Your email address will not be published. Required fields are marked *