Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS: Don't apply multiple drop shadows on top of each other

Is there a way to not apply multiple drop shadows on top of each other? I am trying to use drop shadow to simulate stroke around an element. I needed to use drop shadow because I needed it to work when we had masks or images with transparent spots in it and I couldn't find another way to accomplish the same thing. The other alternative of using a background color didn't work for png images with transparency.

The problem is that when I define a drop shadow for the left and top sides for example, instead of making a nice overlap it actually applies extra drop shadow to the element where there was overlap. This ends up with flat edges instead of rounded ones like they should have been. Note that while this is a rounded image, we allow users to define their own masks and upload png's so it could be just about any shape.

Here is a jsfiddle example of the problem: https://jsfiddle.net/a67fqne2/17/

The code itself:

<div style="width: 391.6px; height: 369.6px; left: 239.6px; top: 28.9px; position: absolute; cursor: default; z-index: 52;">
  <div class="imageOuterStyleWrapper">
    <div class="imageMiddleStyleWrapper" style="filter: drop-shadow(rgb(139, 69, 19) 19.6px 0px 0px) drop-shadow(rgb(139, 69, 19) 0px 19.6px 0px) drop-shadow(rgb(139, 69, 19) -19.6px 0px 0px) drop-shadow(rgb(139, 69, 19) 0px -19.6px 0px); width: calc(100% - 39.16px); height: calc(100% - 39.16px); padding: 19.58px;">
      <div class="imageInnerStyleWrapper" style="clip-path: url(&quot;#Mask-2&quot;);"><img style="width: 100%; height: 133.083%; left: 0%; top: -16.5415%;" src="https://plicimgstaging-d6d.kxcdn.com?url=https%3A%2F%2Fplic-staging.s3.amazonaws.com%2Fphotos%2F4dbf8644-0751-4e9f-afaf-f5c4a00f6bae%2Foriginal%2FAbdulKarim-Naeemah-01195-00007.JPG%3FX-Amz-Algorithm%3DAWS4-HMAC-SHA256%26X-Amz-Credential%3DAKIAIZ3GLWGI2FROIRRA%252F20180712%252Fus-east-1%252Fs3%252Faws4_request%26X-Amz-Date%3D20180712T165503Z%26X-Amz-SignedHeaders%3DHost%26X-Amz-Expires%3D604800%26X-Amz-Signature%3Dd32c01d8dd7f82206b5f15028fc90a1ff6d5aadd71738648d8e477799e27816b&amp;op=resize,rotate&amp;deg=auto&amp;mode=clip&amp;filter=bilinear&amp;q=90&amp;w=450&amp;plic-ref=plic-books-dev&amp;sig=4ee24d37aa0356fe61c9500d370ca81944338fe5"></div>
    </div>
  </div>
</div>

<svg width="0" height="0" id="globalMaskDefinitions">
  <defs>
    <clipPath id="Mask-2" clipPathUnits="objectBoundingBox">
      <circle x="0" y="0" width="1" height="1" cx=".5px" cy=".5px" r=".5px"/>
    </clipPath>
  </defs>
</svg>
like image 261
Floss Avatar asked Jul 12 '18 17:07

Floss


1 Answers

The issue is related to the shape which is a circle in this case so stacking all these drop-shadow with different positions will not keep a circle shape.

Here is a better illustration of the issue if you change the colors:

div,
img {
  width: 100%;
  height: 100%;
  box-sizing: content-box;
}

.imageOuterStyleWrapper {
  width: 391.6px;
  height: 369.6px;
}

.imageMiddleStyleWrapper {
  filter: drop-shadow(red 19.6px 0px 0px) 
          drop-shadow(blue 0px 19.6px 0px) 
          drop-shadow(green -19.6px 0px 0px) 
          drop-shadow(yellow 0px -19.6px 0px);
  width: calc(100% - 39.16px);
  height: calc(100% - 39.16px);
  padding: 19.58px;
}
.imageInnerStyleWrapper {
  clip-path: url("#Mask-2");
}
<div class="imageOuterStyleWrapper">
  <div class="imageMiddleStyleWrapper">
    <div class="imageInnerStyleWrapper" style=""><img src="http://wiesmann.codiferes.net/share/bitmaps/test_pattern.svg"></div>
  </div>



  <svg width="0" height="0">
  <defs>
    <clipPath id="Mask-2" clipPathUnits="objectBoundingBox">
      <circle x="0" y="0" width="1" height="1" cx=".5px" cy=".5px" r=".5px"/>
    </clipPath>
  </defs>
</svg>

But if the shape was square you won't have this issue and it will work perfectly:

div,
img {
  width: 100%;
  height: 100%;
  box-sizing: content-box;
}

.imageOuterStyleWrapper {
  width: 391.6px;
  height: 369.6px;
}

.imageMiddleStyleWrapper {
  filter: drop-shadow(red 19.6px 0px 0px) 
          drop-shadow(blue 0px 19.6px 0px) 
          drop-shadow(green -19.6px 0px 0px) 
          drop-shadow(yellow 0px -19.6px 0px);
  width: calc(100% - 39.16px);
  height: calc(100% - 39.16px);
  padding: 19.58px;
}
<div class="imageOuterStyleWrapper">
  <div class="imageMiddleStyleWrapper">
    <div class="imageInnerStyleWrapper" style=""><img src="http://wiesmann.codiferes.net/share/bitmaps/test_pattern.svg"></div>
  </div>

An idea of fix would be to use SVG and rely on stroke to obtain what you want:

<svg width="200" height="200">
  <defs>
  <pattern id="img" patternUnits="userSpaceOnUse" width="200" height="200">
    <image  xlink:href="http://wiesmann.codiferes.net/share/bitmaps/test_pattern.svg" x="0" y="0" width="200" height="200" />
  </pattern>
  </defs>
  <circle fill="url(#img)" cx="100px" cy="100px" r="80px" stroke="rgb(139, 69, 19)" stroke-width="10"/>
</svg>

I used a circle here but you can easily use any kind of shape:

<svg width="200" height="200">
  <defs>
  <pattern id="img" patternUnits="userSpaceOnUse" width="200" height="200">
    <image  xlink:href="http://wiesmann.codiferes.net/share/bitmaps/test_pattern.svg" x="0" y="0" width="200" height="200" />
  </pattern>
  </defs>>
  <polygon points="190,10 60,100 160,190" fill="url(#img)" stroke="rgb(139, 69, 19)" stroke-width="10" />
</svg>
like image 147
Temani Afif Avatar answered Sep 29 '22 13:09

Temani Afif