This post looks at a way to add a subtle noise effect to HTML elements using CSS. Using this technique is of interest because it doesn’t require use of an image editor, weighs in at just a little over 2K and doesn’t generate any extra HTTP requests.
Demo
Download (CSS code snippet, 2.2K)
How To Use It
The simplest implementation is to paste the code into your existing CSS, then give any HTML elements that you want to apply noise to a class="noise" attribute. Yes, I know that’s an unsemantic use of markup, but there is a workaround that I will detail later.
If you want to apply noise to the body element, use class="body-noise" instead.
How It Works
A quick look at the source will reveal that the trick here is a simple one, namely a data uri. This has been generated from a 50 x 50 pixel repeating tile PNG image of monochromatic noise that I made using Photoshop.
It is layered over elements using the :before pseudo selector using the technique outlined by Nicolas Gallagher and the opacity property. This means that no additional elements are required, and the noise is placed over the top of any existing background colour or image that the element might possess, but sits behind the element’s nested content.
Because the properties used are CSS 2.1 and not 3 then there is pretty good browser support too (breakdown below). Yet because this added progressively, browsers that aren’t supported won’t break, they just don’t get any noise.
Why ???
Adding a subtle amount of noise to aspects of an interface design is becoming more common, since it gives the designer the ability to create a more natural and less ‘digital’ looking aesthetic for interface elements that can be apparent when working with flat colours and gradients alone. Using noise also allows for an enhanced contrast in texture between figure/ground and between distinct areas of a layout.
This of course is already possible using sliced image files, but requires use of an image editor and some experience to create a tile in-keeping with the design in question, and generates an additional HTTP request for each linked image used.
There is a JavaScript based alternative, but this needs to create an additional <canvas> element for it to work, and is quite processor-intensive if used a lot, so although interesting, isn’t that practical.
Adding noise using CSS could be seen as an extension to the popular practice of dynamically adding drop shadows, rounded corners and gradients, etc, using the new CSS3 properties.
Using noise may be just a current ‘trend’, but is generic and understated enough (unlike, say, ‘brushed metal’ or ‘grunge corners’) for me to believe it will here for a while and warrants some sort of CSS solution.
As a side-note, I first tried to see if this was possible using CSS3 gradients, as inspired by Lea Verou’s CSS Pattern Gallery. I thought perhaps that it could be done using a combination of gradients and Alex Walker’s Cicada Principle. As you can see below, things didn’t quite work out as a ridiculous amount of code is required for something that looks less than satisfactory:
Better Semantics
As mentioned above, including a “noise” class to your HTML elements is convenient, but no better than adding color="red" or font="bold" attributes, in terms of semantics and the separation of content and presentation.
If you want to avoid this, then group the selectors of the elements that you want to add noise to, like so:
#myFirstElement, #mySecondElement, #myThirdElement {
position: relative;
z-index: 1;
}
#myFirstElement:before, #mySecondElement:before, #myThirdElement:before body:before {
//noise code here...
}
Grouping selectors avoids you having to declare the noise code more than once. This approach is slightly harder to set up since you need to work out the selectors for each element, but still isn’t that onerous.
If you want to add the body selector to the list, only include it in the second :before declaration, as demonstrated, because giving body a relative position and z-index messes things up.
The code shouldn’t interfere with or break any other declarations being called on the selected elements, unless you are heavily using generated content already. You could theoretically put this anywhere in your stylesheet, but because it’s so big and ugly it makes sense to put it at the bottom for ease of maintainability and bug-testing.
Don’t be tempted to separate out the code into it’s own stylesheet though, or you’ll be generating another HTTP request and defeating the point of the whole exercise.
Make Your Own
The downside of using a Data URI is that it is fairly inflexible; you can’t edit the visual characteristics of the noise on-the-fly. For the sake of compatibility, you can’t even play around with it’s opacity either, becauseĀ IE8 won’t apply it’s proprietary alpha() filter to generated content (I’m guessing MS filters only work on DOM elements?).
So, if you want a slightly different looking noise, you need to create a new Data URI. As a reference, here’s how to replicate the one I created:
1. In the bitmap-editor of your choice, create a new 50×50 px document (Through experimenting I discovered that anything larger than this tends to make the resulting URI too large to make it beneficial over using a linked image. Making it any smaller tends to create a noticeable repeat in the tiled pattern, so 50×50 seems the optimum size).

2. Create a new layer and fill it with 50% grey. In Photoshop this is achieved by selecting EDIT > FILL. from the main menu.

3. Apply a noise filter. In Photoshop this is found by selecting FILTER > NOISE > ADD NOISE from the menu. I found that uniform, monochromatic noise of about 5 – 6% works best.

4. Increase the contrast of the noise slightly. I did this in Photoshop by adding an Adjustment Layer and increasing the contrast by ’50′ with ‘Use Legacy’ selected.

5. Because noise is randomly generated, you will find there are some overly dark or light ‘clumps’ in the pattern. When the tile is repeated, these will become noticeable, so they need to be smoothed out as much as possible. I did this by using the Clone Stamp to copy over the offending areas with other bits of noise that were more uniform.

6. Reduce the opacity of the noise and delete any unwanted background layers so that the image is translucent. I did this by grouping the adjustment layer and the noise layer together and changing the opacity of the group to 25%.

7. Save for Web. You must use the PNG-24 format to retain the translucency and because it’s compression is lossless. In Photoshop, make sure that the ‘Transparency’ tick box is checked.

8. The resulting PNG can be compressed further by running it through Opti-PNG. On a Mac you can use the excellent ImageOptim which I first wrote about back in April 2010 and provides a nice drag-and-drop GUI for Opti-PNG and some other PNG compressors. It should reduce the file size by about half. It also tells you the size of the resulting image file, which is useful for step (10).

9. Turn the image into a Data URI using one of the many online tools available. I used the one found on dopiaza.org but there are plenty others out there.

10. Data URIs will contain more data than the binary of the original image. Check the size of the resulting URI using bytesizematters.com. You should be trying to aim for a size as close to the original image as possible, otherwise the benefits of saving an extra HTTP request or two will be cancelled out.

Browser Support
A good range of browsers support this, specifically:
Internet Explorer 8+, FireFox 3.5+, Chrome 1+, SafariĀ 4+, Opera 9+
Final Notes
This project is a bit rough around the edges and could definitely do with some further tweaking, so if anyone has any improvements to contribute, please let me know.
The concept could be applied to other frequently-used textures too, such as paper, stone or cloth. I’m certainly going to have a go at some of these and if anyone has some examples of their own, leave a link in the comments.

August 5, 2011 at 1:53 am
Neat result; I was using data URI’s as replacements for Photoshopped PNG’s a while ago, never used them as a replacement for noise though. To be honest I don’t know why Data URI images haven’t taken off in popularity; espcially with them being so useful for applications in CSS.
September 25, 2011 at 8:09 pm
I read the book “High Performances Web Sites” and it has a great section going into the pros and cons of Data URIs.
Pros:
- Reduce the number of HTTP requests and headers.
- Works is most modern browsers (but not fully in IE8 and earlier, see cons below)
- Since the image is stored in HTML or CSS, it can be compressed with GZIP by the server
- Helps reduce overhead on HTTPS sites.
- More difficult to filter with security software.
- Encapsulate all content into a single file (may be useful for locally stored WebApps on the iPhone, maybe even rely on the cache.manifest less)
Cons
- encoded data is not cached, so it is re-downloaded with every page it is embedded in
- Encoded images are 1/3rd larger due to Base64 encoding.
- IE7 and previous do not support them either, and IE8 has a 32KB limit (IE9+ has no limit).
- does not carry a filename, so the default save name is based on MIME type.
- images must be re-encoded if you make changes to it, rather than just uploading the file.
- More difficult to filter with security software.
Its a balancing act for sure.
September 25, 2011 at 10:37 pm
Thanks for the info Rob.
Regarding caching though, this concern mostly applies to data embedded within an HTML doc, as this is reloaded every time a new page is visited or the page is refreshed. As I understand it, if the data URI is placed within an externally linked CSS file, which is cached, this shouldn’t be a problem.
August 9, 2011 at 2:30 am
Using IE10pp2, I can use -ms-linear-gradient(black, transparent) and -ms-radial-gradient(white 0px, transparent 1px). http://jsfiddle.net/B2EFG/34/
Please include -ms prefix in your jsFiddle example.
August 11, 2011 at 10:11 am
Seems like a lot of code, with similar issues to my gradient attempt. Do you have a screen grab of the result, as I don’t have a copy of IE10 to hand?
August 24, 2011 at 1:45 am
Hi! When I try to use this on a div it only affects the right half of the div and the effect is very dramatic and sharp. Is this correct? Because it’s not useable in this fashion for me and I like the idea VERY much.
Thanks,
Otis!
August 24, 2011 at 9:46 am
Hi Otis, my mistake, I left the code as it appears in the demo to show ‘before’ and ‘after’.
Have updated the download, or you can change it yourself by setting the ‘left’ property in the second declaration to ’0′ instead of ’50%’:
.noise:before, .body-noise:before {
…
left: 0;
…
}
September 24, 2011 at 1:10 pm
Is Data URI always lower in size then image? will it even work if image is disabled in browser?
September 25, 2011 at 3:00 pm
Hi Jitendra, Data URIs are usually slightly bigger in size that the source image, but the speed benefit comes from reducing the number of HTTP requests the browser needs to make when loading the page. Does seem to work still even if images are disabled, although I haven’t tested this extensively in all browsers.
September 24, 2011 at 1:15 pm
Good idea, good implementation and an even better explanation and write -up. Thanks a lot.
October 24, 2011 at 12:29 pm
Does not work if the content is more than the length of a page.
October 24, 2011 at 12:57 pm
Could you give an example?
February 21, 2012 at 4:24 pm
Take your demo, repeat the and repeat that block of code a bunch to extend the page.
The noise only appears in the first full view, as soon as you scroll the background is whatever it was set to (minus the noise).
November 5, 2011 at 5:52 pm
how to fix the fact that it does not work if the content is more than the length of a page.
November 7, 2011 at 12:32 am
@Sergey, @geizm,
hmm, see what you mean. Because the generated content is positioned absolutely, it is scaled to the browser viewport and not beyond.
Will see if I can find another way of doing this for the body element.
December 22, 2011 at 4:15 am
Hi,
Can u tell me how to put in body another background color but the same noise rest? I mean I set in css body {background-color: #212121}; and yet the color didnt show up if the noise. How can I change that to apply the color of the background by my own?