In a recent web-dev project, a design required scooped corners on some images.
This problem has been tackled many times before. But even so, it took some time to find a solution that worked for the project I was working on.
In case someone walks down this path again, I thought I’d write about what methods I researched and how I arrived at my chosen solution.
The target effect was an image with scooped corners and a uniform border, something like this:
The main restrictions in my case were:
- These images were added through a WYSIWYG. All I could apply to the
imgtag from the backend was a class. The rest had to be done in the frontend.
- IE 10+ support is required, and IE9+ support is preferred.
With those stipulations, lets look at some solutions!
Method 1: Mad gradient hax
The first method I found is arguably the most popular (according to Google, anyway).
Lea Verou uses four CSS gradients to replicate each beveled corner individually, with the gradients going immediately from full colour to transparent in one stop to give a hard edge to the shape.
This method doesn’t work for me however because gradient backgrounds don’t really work on images.
Method 2: Instead of images, use… Images?
One of the obvious approaches to custom borders is to use
border-image, as done by this fiddle (apologies to the creator as I can’t find a source).
The restrictions on border width and inflexibility in border colour don’t work well for my case, however.
Method 3: Needs more jQuery
There is, as always, the
Nuclear jQuery option.
jQuery Corners has been around for some time and while it does have great browser support, the limitations on border size and the bloat associated with this approach (extra JS plugin + a lot of extra markup) make it unworkable for me.
Here is a codepen demonstrating the issues this method presents (you may need to explicitly load non-HTTPS scripts in your browser):
Method 4: Mad gradient hax part duex
Lea Verou has also made a second take on using gradients for an inset border effect.
This method uses a pseudo element to apply the gradient on top of the element instead of it being used in the background of the element (The gradient wrapping shown in this demo is super cool and I didn’t know that CSS gradients worked in this way).
While this method does get pretty close to achieving my goals, if does fall short. I can live with a wrapper element to get this to work on images (which don’t support pseudo elements), but the mediocre browser support (no support on IE9 and icky aliasing on Chrome) and not being able to apply a uniform border to the entire element mean it won’t work for me.
Here is a codepen demonstrating the issues this method presents:
Method 5: A :psuedo solution
The most promising solution is a relatively simple one coming from Mike Behnke. His method is somewhat similar to the previous method except it uses four separate pseudo elements with
This method checks all the boxes for me. Pretty good browser support, flexible and uniform border options, and a nice smooth corner (even on Chrome) make it almost the ideal solution.
The major issue, however, is the extra wrapper tags needed to make this method work.
A Happy Medium
In order to use Mike Behnke’s solution I need to overcome the hard restriction of only a single
img tag being sent down to the pipe.
While I would have liked to avoid using JS at all to achieve this effect, a little dash of jQuery (
.wrap(), to be precise) made this a much easier process.
Here is a demo of the solution I used for the project:
A Final Solution?
This little journey has been fun and all, but I would have much rather just use something like the proposed
corner-shape. Lea Verou has been championing this proposed property and has made a good demonstration of how
corner-shape would work.
I for one would love to see this property become standard but unfortunately it seems progress on it has stalled.
Have any thoughts or corrections? Let me know!