How to have an image with css filter:blur and sharp edges?
Asked Answered
css
S

5

8

I would like to blur an image when hovering.

The problem is that the edges of the image also blur unpleasantly. In the Fiddle you can see it clearly with the green background.

If I'd scale the image i.e. 1.2, it would fix the problem in the end, but during the transition the blurry edges still appear.

Any ideas how to have sharp edges with this effect?

http://jsfiddle.net/d8Njs/

html:

<div class="item">
   <img src="http://placekitten.com/300"/>
</div>

css:

.item {
overflow: hidden;
width:300px;
height: 300px;
background: green;
}

.item img{
transition:all .5s ;
}

.item img:hover{
-webkit-filter: blur(5px);
/*skaling the image would help, but it still looks bad during the transition
-webkit-transform:scale(1.2); */
}
Superinduce answered 20/6, 2013 at 11:54 Comment(3)
Fascinating problem - bug in Webkit methinks.Stricklin
Same question at #12224820 for reference.Allium
Scaling with -webkit-transform:scale(1.0) seems like it ought to be more effective than 1.2... but although it does keep the edges crisp, it doesn't do anything about the unpleasant green effect that forms around the image during the transition.Author
A
5

The techniques I know about, nicely explained at http://demosthenes.info/blog/534/Crossbrowser-Image-Blur:

1..If you have an image that has the same color on all the outside edges, as in the example above, you could set the background-color of the body or a container element to the same color. (FYI; doesn't really apply to you, at least not in your fiddle).

2..Use the clip property to trim the edges of the image. clip is always stated in the following order:

clip: rect( top, offset of right clip from left side, offset of bottom from top, left)

For the example above, the image is 367px wide × 459 pixels high and the blur 2 pixels, so the clip would be stated as:

clip: rect(2px,365px,457px,2px);

(Note that clip is only applied to elements that have position: absolute applied to them. If you wanted to gain support in IE8 and earlier, remember to drop the px on the end of the values). (No idea if you're laying out photos in a stack, a grid, or just callouts, etc. Could be appropriate if you can swallow the absolute positioning.)

3..Wrap the image in a containing element (a , for example) that is slightly smaller than the image, applying overflow: hidden to the outer element and moving the image to the left and up slightly to eliminate the visible blur on those edges.

--

Also, throwing a border around the image seems to help at least in Webkit, but I haven't tested it extensively.

.item img{
    transition:all .5s ;
    border:1px solid #000;
}
Allium answered 20/6, 2013 at 12:5 Comment(3)
Thank you! Unfortunately the blurry edges appear during the transition, even if they disappear in the end because of clipping or a container smaller than the image etc.Superinduce
Adding the border does remove the blurry edges.Sarthe
+1 for adding the border. Note the border can be set to transparent and still works the same.Interject
H
4

A bit of SVG:

<svg width="200" height="200" viewBox="10 10 280 280">
<filter id="blur">
 <feGaussianBlur stdDeviation="10"/>
</filter>
<image id="kitten" x="0" y="0" width="300" height="300" xlink:href="http://placekitten.com/300"/>
</svg>

And some CSS:

 #kitten:hover { filter:url(#blur); }  

Should produce the desired effect. http://jsfiddle.net/5Jk6p/

#kitten:hover {
  filter:url(#blur);
}
<svg width="200" height="200" viewBox="10 10 280 280">
  <filter id="blur">
    <feGaussianBlur stdDeviation="10" />
  </filter>
  <image id="kitten" x="0" y="0" width="300" height="300" xlink:href="http://placekitten.com/300" />
</svg>
Hypercorrect answered 23/12, 2013 at 7:48 Comment(0)
S
3

Seems that setting a clip solves more or less the issue. However, there is an strange effect at the end of the transition. Forcing th GPU (via a translateZ hack) seems to solve the problem.

CSS

div {
    width:300px;
    height:300px;
    position: absolute;
}
.no {
    left: 400px;
    top: 10px;
}

.box img {
   transition: 2s -webkit-filter;
   position:absolute;
   left: -3px;
   top:-3px;
    clip: rect(5px 295px 295px 5px);
    -webkit-transform: translateZ(0px);
}
div img {
   transition: 2s -webkit-filter;
   position:absolute;
   left: -3px;
   top:-3px;
    clip: rect(5px 295px 295px 5px);
}

div img:hover{
    -webkit-filter: blur(8px);
}

demo with a comparative with and without the transform

Spindell answered 23/12, 2013 at 18:38 Comment(0)
S
2

After spending the day on this, I was able to create a crappy, ugly, hacky solution. Probably won't be using it in the real project, mut maybe it could inspire someone else to use something in my solution but make it a little less ugly. At least the end result looks the way I'd like it to!

Using a white border and box-sizing: border-box, and then some margins I was able to get the end result have sharp edges, and 3/4 edges to not show the green background during the transition. If someone would find out why some edges fade with the background during the transition, that would probably help.

http://jsfiddle.net/fVNqm/2/

html:

<div class="box">
    <img src="http://placekitten.com/300" />
   <div class="tophack"></div>
</div>

CSS:

.box{
box-sizing: border-box;
position:relative;
border:3px solid white;
overflow: hidden;
background:green;
width:300px;
height:300px;
}

div img {
transition:.2s all;
position:absolute;
left: -3px;
top:-3px;
}

div img:hover{
filter: blur(2px);
-webkit-filter: blur(2px);
-moz-filter: blur(5px);
-o-filter: blur(5px);
-ms-filter: blur(5px);
}

.tophack{ 
background:white;
width:300px;
height:3px;
z-index:10;
position:absolute;
top: 0px;
}

Still hoping for something better!

Superinduce answered 20/6, 2013 at 20:47 Comment(0)
A
0

add this to your css

.item img{margin:0px 0px 0px -1px;} 
Ancell answered 20/6, 2013 at 12:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.