putting a inset box shadow on an image or image within a div

31,519

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

Demo

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

Image with Box Shadow Overlay

View the accompanying JSFiddle.

Share:
31,519

Related videos on Youtube

Matt Murphy
Author by

Matt Murphy

Updated on June 08, 2020

Comments

  • Matt Murphy
    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
    Fabian Schmengler over 9 years
    The 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
    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 and z-index: -1... why doesn't it work if you use a positive z index on the container instead?
  • ahnbizcad
    ahnbizcad over 9 years
    I'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, is display:block necessary? I read elsewhere that it makes a difference. If so, why?
  • ahnbizcad
    ahnbizcad over 9 years
    is .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
    Fabian Schmengler over 9 years
    No, 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
    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 specify vertical-align and line-height to not have margins above or below the image.
  • ahnbizcad
    ahnbizcad over 9 years
    So 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
    Fabian Schmengler over 9 years
    The latter. Only the direct parent must become a stacking context
  • ahnbizcad
    ahnbizcad over 9 years
    Ah, 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
    ahnbizcad about 9 years
    why 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
    Fabian Schmengler about 9 years
    Yes, 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
    kamelkev over 7 years
    It would be very helpful if you had a fiddle demonstrating this solution, the discussion here is confusing.
  • Velojet
    Velojet about 4 years
    position: fixed will also do the trick, if you're wanting the main div to stay in place when scrolling

Related