MightyMeta

css-noise-b

CSS Noise

| 36 Comments

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 50x50 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 50x50 seems the optimum size).

Create New 50x50 px Document

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

Fill 50% Grey

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.

Add Noise

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.

Increase Contrast

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.

Clumps!

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%.

Reduce Opacity

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.

Save As PNG-24

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).

ImageOptim

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.

Data URI Generation

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.

Bytesizematters.com

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.

If you enjoyed this post, please consider sharing it using the above buttons, leaving a comment or subscribing to the RSS feed.

36 Comments

  1. 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.

    • 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.

      • 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.

  2. 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.

    • 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?

  3. 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!

    • 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;

      }

  4. Is Data URI always lower in size then image? will it even work if image is disabled in browser?

    • 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.

  5. Good idea, good implementation and an even better explanation and write –up. Thanks a lot.

  6. Does not work if the content is more than the length of a page.

    • Could you give an example?

      • 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).

      • Yes, a few people have picked up on this. It is to do with how generated content is rendered.

        You could apply the noise layer to the body element using CSS3 multiple background declarations, and lose IE8 compatibility.

  7. how to fix the fact that it does not work if the content is more than the length of a page.

    • @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.

      • I’m having this same problem. Did you ever come up with a solution, or is there a different/better way nowadays?

      • Multiple background declarations may be a way to go, since approximately 80–85% of browsers in use now support this. Will write up when I have a chance.

      • You can actually fix this by adding ‘position:relative’ to the BODY tag.

        (You might need to reset the BODY’s margins, though)

  8. 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?

  9. Have you seen http://c.nath.is/FZwR ? Although it isn’t supported in IE8 and IE9, it doesn’t use up any of your psuedo elements.

  10. Since the retina displays come out, there we have another con for this method.

  11. Nice script, we’re using it with hover to set the noise opacity to 0% so our buttons/images with a link have the nice noise and on mouse over the noise gets removed with a delay. But its not easy to make a noise pattern that repeats in a good way, its almost not possible to repeat the noise on a 100% width coz you will see that its a repeat.

    • Sounds good, do you have a link?

      Regarding repeated noise, I spent a bit of time trying to reduce the obvious ‘clusters’ that give things away. If you look closely there is noticeable patterning, but at a glance it looks okay, I think.

  12. I’ve found that there’s an issue with this, when the site is larger than the height of the browser, the image doesn’t repeat on body-noise.

    My only quick fix is to make the :after:before position:fixed instead of absolute. The background won’t move, by it won’t stop having noise half way down

  13. Hey Itz awesome! working superbly! thank you yaar :{

  14. Wonderful idea, thank you very much for sharing it with us!

    @Andrew great tip, best way I’ve encountered to fix the missing noise issue.

  15. Hi

    Thank you for the idea, very handy. I’ve updated it further. I noticed that your noise picture would darken whatever you put under it, so I worked on a png that would randomly darken some pixels and lighten others, by a random amount.

    You can donwload my png here: http://img694.imageshack.us/img694/7308/betternoise.png

    Here is a comparison with yours: http://jsfiddle.net/7QnGZ/1/

    My noise is in the third column of each element. You will see that if you squint your eyes, the third column in all 3 elements (the solid color, the gradient and the picture) look identical to the first column, or just as if they had no noise. That was the goal.

    The process to make this kind of noise png is a bit convoluted, but it goes like this. (This procedure uses Gimp terminology, you’ll have to replace it with Photoshop equivalents if that’s what you use.)

    Start with a 50x50 picture filled with 50% gray. Add your favourite kind of noise (I chose a Gaussian noise with a standard deviation of 4 pixel values; don’t use the gamma correction option or it will darken the whole picture.) Duplicate the noise layer and add two 50% gray layers under each noise one. Set the mode of one noise layer to Lighten only, the other to Darken only. Merge down each noise layer onto the respective gray layer. Change the levels of the two layers: for the layer with light spots, set input black value and output white value to 128; for the layer with dark spots, input white value and output black value to 128. Add a layer mask to both layers, using a copy of the layer itself as the mask; invert the mask for the dark layer. Fill the dark layer with white, without touching the mask, and the other layer with black. Finally apply the masks and merge the layers.

    To test the new noise layer, add a new layer with a solid color (such as 50% gray) under the noise layer and use the color picker in Sample merged mode and Sample average to a large value (100px). You should pick the same color you put in the background layer. If you get a lighter or darker color, undo a few steps until you get back to the two layer masks and adjust the gamma setting of one of the two masks.

    Oh, and may the Force be with you!

      • @Tobia => Terrific result !!! Way much better as the original example by James (but have to give credit for excellent idea and quite a bit of work). Your PNG approach is more realistic and nicely blend with any color even when used with alpha transparency. Thanks to both of you @James & @Tobia !!!
        Awesome snippet !!!

      • That can get safely compressed down to 1.51kb from 2.27kb.

        data:image/png;base64,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

    • Nice! When I have a bit of time I’ll look into replacing the original code with this.

  16. Nice info thanks.

    Whilst playing around with this I came across this online tool which might save some time.

    http://www.noisetexturegenerator.com

    by Andrew Ckor

    it produces a png to download but also generates the data URI in the URL, it can also do transparent noise.

    • Hi Michelle. Just a bit of attribution would be nice. Some of the other commenters have provided improvements to the original noise texture, so you may also want to roll your own from those.

Leave a Reply

Required fields are marked *.


MightyMeta, 8 St Lawrence Lane, Ashburton, Devon, UK, TQ13 7DD

Powered by WordPress | Theme Derived From "Yoko" by by Elmastudio

Scroll To Top