putting a inset box shadow on an image or image within a div
Solution 1
Box-shadow inset will not work on image, you need to create a div and give box-shadow to that div and put image inside that div.
You can also use a negative z-index on the img element, and use the box-shadow with inset value on the div element.
div {
position: relative; /* Not required now */
margin: 10px;
float: left;
box-shadow: inset 0 0 12px blue;
border-radius: 50%;
}
div img {
display: block;
height: 100px;
width: 100px;
border-radius: 50%;
position: relative;
z-index: -1;
}
Solution 2
Most of the solutions posted here have problems with the parent elements, a simple solution to this, is using pseudo elements:
.box-shadow
{
background-color: #fff;
height: 235px;
margin: 32px 24px;
text-align: center;
width: 500px;
position: relative;
border-radius: 50%;
overflow: hidden;
}
.box-shadow::after
{
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
-webkit-box-shadow: inset 0 0 10px 10px #000;
-moz-box-shadow: inset 0 0 10px 10px #000;
box-shadow: inset 0 0 10px 10px #000;
border-radius: 50%;
overflow: hidden;
}
<div class="box-shadow">
<img src="http://www.google.com/logos/2012/addams11-hp.jpg" />
</div>
Solution 3
The other answers that propose z-index have an issue if put into context, in my case the image disappeared behind the main div. Preventing this involves setting z-index: 1;
(and non static position) to all of the ancestor elements, which is problematic, and may break a lot of existing layout.
I found a clean solution that doesn't require having to touch all ancestor elements.
I finally figured it out with the help of Understanding z-index - The Stacking Context
HTML
The markup stays like this:
<div class="box-shadow">
<img src="/images/graphic.jpg" />
</div>
The challenge is to put the wrapper div and the image into a single stacking context. For this you have to apply styles to the parent element.
Stacking Context CSS
According to the linked article, the following elements create a stacking context:
- the root element (HTML),
- positioned (absolutely or relatively) with a z-index value other than "auto",
- a flex item with a z-index value other than "auto",
- elements with an opacity value less than 1. (See the specification for opacity),
- elements with a transform value other than "none",
- elements with a mix-blend-mode value other than "normal",
- elements with isolation set to "isolate",
- on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is "auto"
- specifing any attribute above in will-change even you don't write themselves directly
If we focus on the options that make sense for this use case, we have these alternatives, assuming the parent element of the .box-shadow
element is #parent
:
1. Positioning and z-index:
This is what I would choose if possible:
#parent {
position: relative;
z-index: 0;
}
2. Opacity
If the parent element needs to have a different position attribute or adding z-index has unwanted side effects, you can use an opacity value that's almost 1, so that it has no visible effect but still creates a stacking context:
#parent {
opacity: 0.999;
}
Finally, the shadow CSS
Then you can apply the shadow on the div and move the img behind it with z-index:
.box-shadow {
box-shadow: 0 0 10px 6px white inset;
}
.box-shadow img {
display: block;
position: relative;
z-index: -1;
}
Solution 4
Here’s a clean, simple and modern approach of CSS pseudo-elements to place a box shadow “on top of an image”, since img
tags themselves don’t support pseudo-elements.
HTML:
<div class="box-shadow">
<img src="http://i.stack.imgur.com/8LzBY.jpg" />
</div>
CSS:
.box-shadow {
position: relative;
text-align: center;
}
.box-shadow::after {
box-shadow: inset 0 0 10px 10px #000;
bottom: 0;
content: "";
display: block;
left: 0;
height: 100%;
position: absolute;
right: 0;
top: 0;
width: 100%;
}
.box-shadow img {
max-width: 100%;
width: auto;
}
View the accompanying JSFiddle.
Related videos on Youtube
Matt Murphy
Updated on June 08, 2020Comments
-
Matt Murphy almost 4 years
I have an image on my page which i want to put an inset box shadow on. I have tried doing this with the image both in, and out, of a div. Can anyone help me to get an inset box shadow to display?
HTML:
<body> <div id="logo"> <img src="images/key.jpg" width="3%" height="3%"/> </div> <a href="scene2.html" class="next">Next</a> <a href="abduction.html" class="back">Back</a> <img src="images/scene1.jpg" width="650" height="650" class="backing"/> </body> </html>
CSS
.backing { position:relative; z-index:-10; float:left; margin-left:12%; box-shadow: 0 0 -50px -50px #FFF; -moz-box-shadow: 0 0 -50px -50px #FFF; -webkit-box-shadow: 0 0 -50px -50px #FFF; } .next { position:relative; margin-left:8%; z-index:200; } .back { position:relative; margin-left:2%; z-index:220; }
-
Fabian Schmengler over 9 yearsThe important bit here seems to be
position:relative
, otherwise the image cannot be placed behind its parent. But unfortunately the image moves behind all other parent objects, if those do not have a negative z-index as well. -
ahnbizcad over 9 years@fschmengler all parent objects... that's gonna break a lot of things. you have to make ALL of the image's parents
position: relative/absolute/fixed
andz-index: -1
... why doesn't it work if you use a positive z index on the container instead? -
ahnbizcad over 9 yearsI'm confused. is the
#parent
element.box-shadow
? if so, then why isn't there opacity, position, and z-index:0 in the.box-shadow
element? Or is the#parent
element a wrapper of.box-shadow
? If so, this is not specified. Also, isdisplay:block
necessary? I read elsewhere that it makes a difference. If so, why? -
ahnbizcad over 9 yearsis .box-shadow the #parent? I'm not clear on whether that connection was implied, or if #parent is a third element that wraps .box-shadow.
-
Fabian Schmengler over 9 yearsNo, parent is the parent element of .box-shadow. This can be an existing element or if this doesn't work, an additional wrapper.
-
Fabian Schmengler over 9 years
display: block
is not necessary for the box shadow to work but for exact positioning. I think this is because as an inline-element (i.e. without display:block), you'd have to specifyvertical-align
andline-height
to not have margins above or below the image. -
ahnbizcad over 9 yearsSo this is a cleaner way than specifying position relative z-index: -1 to every ancestor element, but it still does not get around having to address every ancestor element. Is this correct? Or does the buck stop with the direct parent of .box-shadow, so to speak?
-
Fabian Schmengler over 9 yearsThe latter. Only the direct parent must become a stacking context
-
ahnbizcad over 9 yearsAh, so that's the elegance behind this solution. It was not apparent to me when you said "The challenge is to put the wrapper div and the image into a single stacking context." This makes it the "correct" solution. I think some marketing is in order to highlight the benefits and elegance of this solution.
-
ahnbizcad about 9 yearswhy did you choose opacity over the other options? isolation seems to be designed for this. Does it have issues with browser support? I couldn't get very good google results for this css property. Is it a deprecated relic that roamed once upon a time?
-
Fabian Schmengler about 9 yearsYes, as soon as there is better support, isolation is the best option (should have mentioned that). At the moment, it's not the case: developer.mozilla.org/en-US/docs/Web/CSS/…
-
kamelkev over 7 yearsIt would be very helpful if you had a fiddle demonstrating this solution, the discussion here is confusing.
-
Velojet about 4 years
position: fixed
will also do the trick, if you're wanting the maindiv
to stay in place when scrolling