Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I work around a Safari bug that allows a filter to escape bounds even with overflow hidden?

I'm trying to use a CSS filter to blur an image. In all browsers, the blur filter results in the blur going outside the bounds of the image for whatever value you set the blur to (expected). But I want the edges to be defined (and the image to have a box shadow), so I wrap the image with another div with overflow set to hidden. This works in all browsers.

However, due to some app-specific constraints, I need to update the size of the wrapper with JavaScript on load and resize. This works in all browsers except Safari. Changing the size of the wrapper element randomly triggers a painting bug where the filter begins to escape the bounds of the wrapper. It doesn't always, but it seems to increase in likelihood on MobileSafari and/or based on the size of the DOM.

Here's a fiddle with a small demo. Using Safari, resize the window repeatedly and you'll trigger the bug. Sometimes it will repaint and fix itself, sometimes it will not. (Use Chrome or Firefox and it will work fine.)

(Screenshot of the blur escaping the wrapper.)

It should be noted that unlike this fiddle, in the application I am only setting the new width and height when they change, and Safari still fluctuates between the blur escaping and not escaping even when the width and height are NOT being set during the resize event.

Things I've tried (that haven't worked):

  • Delaying the calculation and setting of the wrapper width until the resize event is complete using clearTimeout/setTimeout
  • Unsetting and resetting overflow: hidden on both the wrapper and the image with JavaScript after changing the size
  • Calling window.getComputedStyle(wrapper) (and on the image, and on the parent element)
  • All sorts of shenanigans to promote the wrapper to a composite element (e.g. translateZ(0) transforms), which does stop some of the blur overflow, but not enough. (Screenshot.) Setting a timer to disable the transform simply returns the page to full blur escape.
  • Setting white-space: nowrap on the wrapper
  • Setting the width and height via document.styleSheets[x].cssRules[x].style.setProperty() rather than object.style.width/height
  • Rounding the pixel values to multiples of 2 / 5 / 10 (yes, I'm desperate)

I'm pretty stuck at the moment, and would greatly appreciate any help you can provide. Thank you!

like image 977
Brock Batsell Avatar asked Mar 02 '16 19:03

Brock Batsell


2 Answers

you can give a fluid width to your wrapper in CSS which will have the same effect as your JS code right now, and that might fix your bug, you can also change your width of img to max-width

#image_wrapper {
  overflow: hidden;
  margin: 30px auto;
  box-shadow: rgba(0, 0, 0, 0.5) 0 5px 14px;
  width:95% /* whatever fits you better here */
}
#image {
  -webkit-filter: blur(50px);
  filter: blur(50px);
  max-width: 100%;
  
}
  <div id="image_wrapper">
    <img id="image" src="https://scratch.brockbatsell.com/black-wallpaper-13.jpg">
  </div>
like image 101
dippas Avatar answered Oct 06 '22 00:10

dippas


The bug seems to be averted if you add a -webkit-mask-image to the image:

#image {
  -webkit-filter: blur(50px);
  filter: blur(50px);
  width: 100%;
  -webkit-mask-image: linear-gradient(to right, #fff, #fff);
}

https://jsfiddle.net/pqjh2471/

-webkit-mask-image is not particularly well supported, but it is supported in Safari from 4.0 on.

like image 27
tiffon Avatar answered Oct 05 '22 23:10

tiffon