Sickdesigner

My name is Radu Chelariu, I'm a web designer and here you can get to know me better.

Pure CSS Vignette

Our latest posts have mostly been about design, so today we’re going full on code monkey with a cool CSS3 technique: Vignettes! The technique involves a few divs, a bit of simple CSS, and a whole lot of fun. So click the pic and read on.

Of course, there are those of you just looking for the quick fix so, without further ado, here’s the link to the demo page:

DEMO

So, what’s this puppy about?

For those of you who don’t know, a vignette effect is a discoloration on the edges of an image. This effect usually appears in photography and it can be either accidental or intentional. It can also be either light or dark, depending on the situation. Like this:

Good, now that that’s out of the way, let’s continue to the actual tutorial.

We’ll be dividing the vignette into four div elements as shown in the diagram above.

Using absolute positioning we’ll be telling the four divs to sit in their respective corners and using a combination of CSS Gradients and RGBA we’ll fade the discoloration towards the center.

One should be careful not to overdo it with the vignette. A black vignette on a white background will look really cheap, mostly due to universal browser dithering problems, so a subtle approach is key to a successful effect.

We’ll also set the height/width of the divs using percentages. This way we’ll get a proportional vignette according to the user’s screen size. The trick with this technique is using just the right amount of height/width. Too much, and the content will become unselectable on account of the divs having a high z-index value. Too little and the effect is barely noticeable. I did a few experiments and the widest range of usable heights/widths is somewhere around 12%-17%. In this tutorial I used 15% which seems to work fine for resolutions from 1024×768 up to 1920×1080.

The HTML

The HTML part is really, really straight forward – just four empty divs, in no particular order:

<div id="top"></div>
<div id="right"></div>
<div id="bottom"></div>
<div id="left"></div>

The CSS

Here where the magic really happens:

/* First we set the four elements of our vignette
to be on top no matter what and set their initial
width and height which we'll overwrite in the next declarations.
*/
#top, #bottom, #left, #right{
height: 100%;
position: absolute;
z-index: 999;
width: 100%; }


/* Overwriting the default 100% */
#top, #bottom{
height: 15%; }


#left, #right{
width: 15%; }


/* We set the gradient with CSS3 from a solid gray to
a 100% transparent color which should be the same as
the body background color, to have a nice, clean falloff.
And we're also setting the position of the vignette elements.
*/
#top{
background-image: -moz-linear-gradient(100% 100% 90deg, rgba(255, 255, 255, 0), #e1e1e1 );
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#e1e1e1), to(rgba(255, 255, 255, 0)));
top: 0; }


#bottom{
background-image: -moz-linear-gradient(100% 100% 90deg, #e1e1e1, rgba(255, 255, 255, 0) );
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, 0)), to(#e1e1e1));
bottom: 0; }


#left{
background-image: -moz-linear-gradient(100% 100% 180deg, rgba(255, 255, 255, 0), #e1e1e1 );
background-image: -webkit-gradient(linear, left center, right center, from(#e1e1e1), to(rgba(255, 255, 255, 0)));
left: 0; }


#right{
background-image: -moz-linear-gradient(100% 100% 180deg, #e1e1e1, rgba(255, 255, 255, 0) );
background-image: -webkit-gradient(linear, right center, left center, from(#e1e1e1), to(rgba(255, 255, 255, 0)));
right: 0; }

The code may look a bit stuffy at first but it’s quite easy to maintain as only the hex values of the gradient and perhaps the height/width values need adjustment.

Browser compatibility

All in all I’d say it’s a pretty useful and usable technique, but if you must extend it’s compatibility to Opera and IE7 and above you could use fixed heights/widths and a repeating transparent PNG image. A lot less cool, but you get the point.

I hope you enjoyed this little technique and if you ever get the chance to use it somewhere, I’d appreciate dropping a line and showing off.

by Radu Chelariu

45 Comments

  1. FIRST! LOL, Anyway, this is a very cool technique. I don’t know that I would use it much but it does give me some ideas! The page transition is pretty cool. Good job! He what is the code plugin you are using?

  2. :) I guess a FIRST is in order every now and then, right? If my technique has shocked your creative center and gave you a better idea, then I couldn’t be happier!
    As for the code plugin, it’s called WP-SynHighlighter and you can find it at http://wordpress.org/extend/plugins/wp-synhighlight/ It’s pretty ok, but you have to have enough patience to dig through about 10 directories and 5 css files to tweak it.

  3. Ok. I might give that plugin a try. I am going to play around with this vignette and see what I can come up with! It is pretty slick.

  4. Excelent! Let me know how it turns out!

  5. Tim says:

    Not sure how useful this is: http://fetchak.com/ie-css3/ basically it adds CSS3 support to internet explorer, might it work for some of this? (I have only skimmed the article so far (looks really good), but thought I would mention it anyway :D )

  6. Hi Tim, that’s a great idea. I’ll do a few tests to see if it works and if it does actually provide support for both Opera and IE, I’ll update the post. Great find!
    - Later edit: this script does provide text-shadow support for IE, but only that, it doesn’t add support for RGBA or Gradients, so it’s a no go. Sorry, Tim!

  7. Tim says:

    Oh well, worth a shot :)

  8. Your efforts, however, are much appreciated, Tim!

  9. This is just awesome stuff! Thanks fro sharing.

  10. Beben says:

    wow, its pure of CSS…
    i cant believe it, its like use script…great
    thanks for share

  11. Mary Lou says:

    Oh, I love this effect! Thanks for sharing it!

  12. Chris says:

    Nice man, really useful I’ve indexed at toptuts.com to share with everyone else :)

  13. @everyone: thanks for the great responses and the appreciation!

  14. Brennan says:

    I achieved the same effect years ago by stretching a background that had the gradient. Needless to say it was really inefficient and nasty.

    This, I imagine, would be much more efficient.

  15. Hi Brennan, that’s actually pretty clever, but I imagine browser rendering turned it into a freaky pixel nightmare. The technique in this post is efficient and easy to maintain/modify but it’s not without it’s downsides; most of which come from the fact that CSS3 has only yet hit puberty. In about a year or so I imagine we’ll be able to fully use CSS3 in production without any major issues.

  16. Hugh Guiney says:

    Pretty cool, but I’m not too keen on the use of non-semantic divs. I wonder if there’s another way to achieve the same effect.

  17. Kevin Rapley says:

    Could this not be achieved with box-shadow: inset 0 0 1em black; ? I am not a big fan of using extraneous markup to achieve visual design. The HTML should be semantic with style kept separate. Markup should never be edited to assist styling. I am pretty sure box-shadow that I mentioned can be used either directly to the image tag (not tested) or on just one div absolutely positioned over the image. We should always strive to avoid tag soup.

  18. @Hugh: good point.
    @Kevin: you know what? I think it could be done! With an inverse box-shadow directly on the body tag, one could, theoretically, create the same effect without extra divs. I’ll give your idea a bash and if it works out, I’ll post an update. Nice catch!

  19. Hey,
    I had just a thought for IE. Isn’t it possible to do the gradient-stuff with a filter?

    filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr=’#bed6ce’,endColorstr=’#8ccbb6′);

    This works with > IE 6. I don’t know how it supports transparencies.
    It’s not perfect but it’s better than leaving IE totally out.

  20. Nice, but why do we need it, if it doesn’t work even in ie8?

  21. @Hans: I am aware of the proprietary IE filter properties but I decided to not include them in this tutorial. The reason is simple: it’s not valid. Also, if I’m not mistaking, the filter properties apply only to IE versions 7 an below. Though I could be mistaking.

  22. @Denis: because one browser shouldn’t hinder progress; because IE9 is just around the corner; because we’ve been catering to IE for far too long; because other browsers are gaining ground, user wise, by the minute. Just a few days ago, Opera hit 100 milion users, for example. Just a few ideas.

  23. Kevin Rapley says:

    @Denis/Radu you can also add the argument for progressive enhancement. Why not do it? All Webkit browsers and Mozilla can render these styles, and likely are future browsers. IE and older browsers will have a lesser user experience, yes, but they still receive an experience (they get to see the photos/images) and an experience they are use to. Many IE users are unaware that websites have rounded corners and drop-shadows in more modern browsers.

  24. Adam says:

    It’s a cheap look that does not work in FireFox or IE – the 2 major browsers of the net (atleast didnt work in your example). Do you want to know a nice cross browser solution? Do the effect in photoshot. And that’s coming from a Photographer and Designer.

  25. @Adam: that wouldn’t work out as well, since the vignette would either be fixed in size or the images would be stretched out. Also, that would require the use of 9 images, which isn’t very nice to maintain.
    What version of Firefox are you using? It should work ok for anything above 3.0.
    Congratulations on being a Photographer and Designer, both with capitals.

  26. Eric says:

    Neat little effect. Another one to hold on to! Thanks.

  27. Sean says:

    Very nice.

    FYI it works in Win Firefox 3.6.3 but not in Linux Firefox 3.5.9 (but it degrades fine).

    Just found your site, looks great, will be back.

  28. Great tutorial thanks, its perfect for an effect I’m trying to get on my site redesign. Would it be possible to use one Radial Gradients instead of 4 Linear ones?

    • @Chris Armstrong: Hi Chris, I’m glad you like the vignette effect! Yes, you could use a Radial Gradient but you’d have to have apply it behind the content. If you’d position this Radial Gradient div above all the content, users couldn’t select anything, because you’d essentially have another layer above everything on your site. This is why I prefer the 4 div approach. Sure, there’s a bit too much markup but it ensures that the design doesn’t get in the way of usability. Still, your call!

  29. I put it to use one my site here http://chris-armstrong.com/ (still a work in progress). Have a few suggestions…
    - Make it position:fixed instead of position:absolute
    - add top:0; to #left and #right

  30. Chris: thanks for using the Vignette technique on your website, it’s great! Also, very good pointer with using position:fixed ;)

  31. Bud says:

    I just love how your website is designed & structure. very creative & great articles. BLESS YOU

  32. MyWhirledView says:

    This worked for me in a couple browsers:

    body {
    margin:0; padding:0;height:100%;
    box-shadow:inset 0 0 200px rgba(0,0,0,.7);
    -moz-box-shadow:inset 0 0 200px rgba(0,0,0,.7);
    -webkit-box-shadow:inset 0 0 200px rgba(0,0,0,.7);
    background-image:url(http://t2.gstatic.com/images?q=tbn:UkkysNWvrTEZdM);
    }

  33. dancave says:

    I made a version of this that works across the ‘main modern browsers’, resizes, scrolls, and has the nice curved adges this one doesnt… feel free to pull the code apart and use it if you know how…

    Its basiclly CSS2, HTML 4, and some borrowed javascript to calculate some positions so that it works on scroll to.

    http://www.colourpool.com/newtest/

    The site is just something im working on. If you use it and feel like linking to http://www.colourpool.com then I would apreciate it. If not, thats fine too.

    • Good implementation! Yes, there’s a but. Actually two:
      1) It’s a bit buggy if you scroll medium-fast, in Mozilla. The vignettes get a bit jittery.
      2) It’s got Javascript :( The whole point of my post was that it’s about a pure CSS vignette. Not sure why you’d prefer using the JS version, especially since you get a few extra divs in there (not that my four are any better).

      • dan cave says:

        Thank you. I just read my comment back and it didn’t come across quite as light hearted as I meant it to :(

        I always commend standards developers, especially you guys who push things forwards and then share with the rest of us.

        I just made my vignette as quickly as I could with my out of date CSS.

        Thank you for pointing out the jitteryness, I would love to fix it, but alas my script-fu is weak.

  34. Hi Radu, I got to your site via the Masonry CSS post, then saw this, which got my attention ’cause I’d been working on something similar.

    Anyway, getting to the point, I’m wondering if you could be able to achieve a similar result using a radial gradient (black to transparent) applied to an absolutely positioned :after pseudo element attached to the html element, and make the body a lower z-index. Haven’t tried but it may offer a way of avoiding all the divs?

    I have some nice vignetted buttons that you may find interesting here

  35. Ben says:

    why make 4 divs when you can make it in one?
    That’s the beauty of inset box shadow in CSS3.
    Here’s the code:
    min-height: 100%;
    min-width: 100%;
    background-color: #DDD;
    -moz-box-shadow: inset 0 0 150px 5px rgba(0,0,0,0.5);
    -webkit-box-shadow: inset 0 0 150px 5px rgba(0,0,0,0.5);
    box-shadow: inset 0 0 150px 5px rgba(0,0,0,0.5);

  36. oldskull says:

    Great tutorial, thank you!

  37. Anna says:

    Hej!
    wonderful thing.. searched for it for a while!
    but i have two problems..

    first: in safari there is a small border on the top.. i cant get rid of it…

    second.. is the main problem: i want to do a div layer with the next “above” this vignette but it’s always under the vignette which looks really weird.. why is that? or am i just.. planless… :(

Speak your mind

RSS Twitter Facebook Dribbble LoveDSGN Flickr