Next-gen CSS: How to use CSS filters, CSS shaders and CSS text effects – Part 1

Discover how to use tomorrow’s top CSS styling techniques today


Even though HTML5 and CSS3 still haven’t landed fully in all browsers, the W3C and browser developers are already looking to the future. Historically, the web has always been a work in progress, and code stability and true cross-browser standardisation have always been more of an exception than a hard-and-fast rule.  

“Don’t think of the future as an excuse for more and better eye candy – think of CSS as part of a standard web toolkit you can use to build all kinds of new experience”

From that angle, the current proposals are more of the same. The difference is that the emphasis is shifting from fixed media decorated with CSS effects, to open-ended designs that are rendered live and look suspiciously like low-level game coding and animation – but instead it’s applied to text and images, rather than game characters.

So the big change is that CSS is no longer just about design. Google and Mozilla Corp are touting full browser-based operating systems, and products such as the Google Chromebooks are breaking web technologies out of the desktop and mobile browser ghettos and into much more custom hardware. There will be more of this in the future, and CSS will become even more of a generic app development environment than it is already. So don’t think of the future as an excuse for more and better eye candy – think of CSS as part of a standard web toolkit you can use in order to build all kinds of new experiences.

The catch is that for now, it’s not so standard. Some of the possible developments are still being drafted and debated. Browser support is somewhere between experimental and non-existent – and with many designers still playing catch up with CSS3 and HTML5, there’s still plenty of scope for creative surprises with established technologies that have been around for a couple of years.
To give you both sides, we’ll look at the best of the old and the new.

There are three main areas to watch with CSS; 3D effects and image filtering, text effects, and layout. 3D has already made an appearance with CSS3 3D transitions – and the good news is that WebGL and browser support for these transitions is good.  Although, WebGL is still catching up, because it’s technically tricky and waiting for rock-solid driver support.

CSS 3D effects embeds a WebGL API in CSS to give you powerful new possibilities. The programming model will be unfamiliar to most web designers, so the learning curve isn’t trivial. But once you master it you can animate, explode, relight and distort entire <div>s, or warp entire pages. You can also create unique custom transitions and animations, and embed them in the usual CSS/DOM event framework to create new UI models. CSS filters give you a set of 2D image effects, such as blurring, brightness and contrast, and hue/saturation, for images. These effects are virtually identical to many of Photoshop’s most basic filters, but with only some slightly tricky programming, you are able to animate them. On top of that, you can combine them with various other next-gen CSS techniques to give yourself countless more options to experiment with.

The latest text effects expand the potential for stylish typography and more sophisticated letter stylings. For example, now designers are able to create cool 3D and embossed/debossed looks. You’ll have seen some of these online already, but they’re so good they’re always worth a deeper look. Because this is CSS, you can apply animated effects to individual letters buried in a <span> to create slicker and more sophisticated versions of those old animated Flash text effects.
The new layout options are possibly the most experimental of all, and as a result have the least reliable browser support. The aim is to make layout code smart and responsive, removing the need for pixel-level position hacking. Elements place themselves around a page with built-in intelligence and with platform-specific awareness. You can start to write CSS that fits the content into many different mobile and desktop form factors with automated reflow and positioning.

Browser support race


Red = No | Yellow = Partial | Green = Yes

What are CSS Filters and Shaders?


CSS filters have been in WebKit since 2011. They’re an easy way to create basic photo editing effects with a few of lines of code. You can control blur, grayscale, drop-shadow, sepia, brightness, contrast, hue, saturation, opacity, and colour inversion. If you’re new to filters, visit the Adobe CSS FilterLab at to experiment live with filters, and to see how little CSS you need to create impressive results.
CSS shaders take filters a step further by giving you an entry point for you to create your own custom filter code. Instead of one of the pre-made filters, you use a new kind of filter called custom. Embedding the filter is easy – you add some boilerplate code to set it up, and it should work in most WebKit browsers.

Chrome, which now uses Blink, needs some special setting up before you can get any custom filters to work. Type chrome://flags into the address bar, and enable everything you can find that mentions WebGL or experimental CSS. The flag names change between releases, so there’s no standard go-to way to make sure that shaders are working. Even then, support also depends on your graphics card and drivers – some smaller Macs don’t support shaders, even though in theory Chrome does.

But what are shaders? How do you create code for them? You need to embed links into two files to set them up. 3D coding is complex, but the simple summary is that everything is made of a mesh of triangles. The .vert or .vs vertex shader calculates the positions of each triangle vertex. It uses a 4D vector format that simplifies rotations. The .frag or .fs fragment shader adds textures, colours, and lighting to the triangles. The CSS blends the two and the browser does the difficult calculations needed to create a 2D view into a 3D scene.

/* Simple overdone WebKit filter example     */
.anelement {
drop-shadow(5px 5px 5px rgba(0, 0, 0, 0.5))

/* Custom opacity filter example */
.anelement {     
-webkit-filter: custom(url(shaders/    vshader.    vert)    /* The vertex shader file */ 

/* The fragment shader file */
normal source-atop),             
/* Don’t change this */    
50 50, /* The number of     triangles */
opacity 1);            /* You can change this */

/* Save this as vshader.vert  it does     nothing     to the vertices */ 
void main() {
gl_Position = projectionMatrix *
modelViewMatrix *
 vec4(position,1.0);    /* Don’t     change the     position */

/* Save this as fshader.frag  it reads     the     opacity and applies     it to the color     matrix */
uniform float opacity;        /* A     uniform is applied to     the whole scene */
void main() {
gl_FragColor = vec4(1.0,  / R028

Working with text effects


Although you could potentially use custom shaders to texture text, the effort would not be a small one. Likewise, you could pre-render the text in Photoshop and drop it in as an image but keeping the text as text. Applying a texture will score you a number of wins, not least in responsive designs.

The secret is to create a PNG24 file with transparency and apply it as an empty <span> on the <div> with the text. The rendering engine doesn’t clip the span, as you’d expect. Instead it loads the image and blends it with the text, because it’s actually rendering the two superimposed elements twice, in order. If you use a PNG with black/white and no grey, the text is textured, but the background isn’t. Otherwise, you get an interesting blend.
The image can be expanded to fill the text box, but if it’s too big it will show over the edges of the text unless you clip it. The code here uses simple absolute pixel dimensions. Production code would include extra logic to make it intelligent and responsive.

/* First the HTML, with a dummy span */
<div class=”textured”>

/* Now the CSS */
.textured {
	background: #000;
	width: 700px;

.textured h1 {
	font: bold 1000%/100% “Helvetica”, Arial, sans-serif;
	position: relative;
	margin: 0;
	color: #fff;
	letter-spacing: -6px;

.textured h1 span {
	background: url(text2.png); /* Load the texture PNG */
	position: absolute;
	display: block;
	width: 700px;
	height: 160px;