Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a shadow around a background image

Tags:

css

background: url("images/main_bg.png") repeat;

Is a header/banner background image in style.css, but not sure how to get a shadow around it...

I tried

body {
    font-family: Arial,Helvetica,sans-serif;    
    font-size: 13px;
    color: #333333;
    background: url("images/main_bg.png") repeat;
    box-shadow: 0 0 5px 2px #282a2d;
    line-height: 1.4;
}

But that didn't work out...

like image 951
Damian Avatar asked Jul 07 '13 17:07

Damian


1 Answers

TL;DR:

In case you're satisfied with WebKit Chrome only support, use CSS Filters.

In case you're satisfied with polyfilled CSS Canvas Context and Canvas, you can support Mozilla and WebKit browsers, though, Chrome will have no blur for it's shadow.

If you can recreate your image in SVG, and your targeted browser do support it, that's also a viable option. Actually, this appears to be the best option in case you can get your background in SVG. Most major browsers show the same result, with the exception of Safari which appears to drop the filter.

You can read below about the process of how the options did evolve.


Original answer:

I doubt that what you're looking forward to is possible.

First of all, body takes up 100% height and 100% width of the page, the "outside" shadow of it will be always hidden.

If you set the property as follows:

box-shadow: inset 0 0 5px 2px #282a2d; /* mark the inset */

you should see the shadow, though, I doubt that's what you seek.

You could overcome the issue by wrapping the image in a new element, that's a child of body and is smaller than 100% of body's dimensions.

Also, you may make body's dimensions smaller than 100%, though, I do not encourage to do so - it may break in some browsers and so on.


My second guess, derived from that you're using a png, hence, transparent image, is that you wish to shadow the image around it's filled pixel edges, leaving the transparent untouched. While it sounds like a cool idea to do, that's not what CSS does.

The property is called box-shadow not simply shadow so it already states that it won't be possible.

I don't know if that's possible, but you could try using SVG and it's filters to do so. I'm no expert in SVG's - will not be able to provide example immediately (will look into it though).

One more possibility is to use canvas as background for your element, and apply the shadow programmatically (iterating through pixels and adding extra pixels).

Update: Didn't know that Canvas is smart enough to shadow through transparent images, the programmatical part is not necessary.

Keep in mind, that the last 2 variants will most definitely be poorly supported by browsers.


Updates:

CSS Filters:

Okay, there is one more possibility - CSS filters, though, as of writing, they are supported only by WebKit. Not sure actually if they work in all of WebKit browsers (Safari, Opera, Chrome), but they do in Chrome.

Checking with latest Safari for Windows, Opera and Chrome, proves, that the property only works on Chrome.

There is one "but", it is not supported on body either (jsfiddle.net), and I think that all of the cool stuff has left the body behind.

In case of child node, it works (jsfiddle.net)!

P.S. Eventually, we may see CSS filters implemented in every browser. That makes this the best option for such functionality.


Canvas:

Update:

I did some experiments with canvas. In general, it's a success and even works for body: http://jsfiddle.net/psycketom/3VBMJ/4/.

Though, I couldn't manage to make the shadowBlur property work. Might be it doesn't work on CSS Canvas Context.

And, Firefox natively doesn't support cssCanvasContext, so the -moz-background (It's actually -moz-element, but since there is no cssCanvasContext, it still fails) property is ignored. I think that could be hacked with an off-screen canvas.

Update 2:

The shadowBlur property works on Safari, doesn't on Chrome.

Update 3:

http://jsfiddle.net/psycketom/3VBMJ/6/ I did a test with off-screen canvas, but couldn't hack it together. I'm giving it a bit more of my time at the moment.

Update 4:

Off-screen canvas does work in Firefox - http://jsfiddle.net/psycketom/3VBMJ/12/, but, doesn't work in Webkit.
A dynamically generated canvas also does it, though, it has to be appended, and hidden afterwards.

Update 5 (worth to check):

I did a dirty polyfill, now, the Canvas background gets supported in both - Webkit and Mozilla browsers.

Update 6:

I did a quick compatibility test - Chrome (27.0.1453.116 m) works, Firefox (22.0) works, Safari (for Windows, 5.1.7 7534.57.2) works.

As for... IE (10.0.9200.16618) doesn't work, Opera (12.14 1738) doesn't work.


SVG:

First of all, SVG requires that you create your image in vectors.

Update:

Oh boy, oh boy... SVG... http://jsfiddle.net/psycketom/3VBMJ/18/. This is not really an background image, it's just SVG poured inside the HTML, and it's container element has pointer-events: none applied to it, to disable any mouse input.

Works in both, Firefox and Chrome, and probably others because it depends on SVG that is a bit more supported than CSS3/HTML5. Keep in mind though, that some parts of SVG are not supported, filters, possibly, being one of them.

Update 2:

By pouring everything what we had as inline html before into a file of it's own, we can use SVG as background-image. Checked in Chrome and Fox - works in both.

Update 3:

I did a quick compatibility test - Chrome (27.0.1453.116 m) works, Firefox (22.0) works, IE (10.0.9200.16618) works, Opera (12.14 1738) works.

As for Safari (for Windows, 5.1.7 7534.57.2) - it works, but doesn't display shadow at all.


This is what I meant with child element:

http://jsfiddle.net/psycketom/3VBMJ/21/


Additional information:

http://jsfiddle.net/psycketom/3VBMJ/17/ it appears, that the shadowBlur in Chrome is supported in general (the red box), but it lacks support for PNG's (smiley).

I'm confused, now, is it because of the recent switch to Blink or it has never been supported in Chrome?

like image 131
tomsseisums Avatar answered Sep 22 '22 14:09

tomsseisums