Rounded corners and legacy gradient filters

When you use legacy gradient filters to fill elements that have had their corners rounded using the border-radius property, the gradient bleeds past the border of the element. Here's how to prevent this from happening.

Consider this scenario: You create a div element and apply a gradient fill to it using the legacy Gradient Filter. You then apply the border-radius property to it, creating rounded corners.

You might see that the gradient ignores the rounded corners of the div element and "bleeds" outside of it to the original boundaries of the element.

This behavior can be observed starting with Windows Internet Explorer 9 when the document mode is IE9 Standards mode.

There are two ways to work around this issue.

First, you can wrap the element (with the gradient background) in a container element, round the container element's corners using the border-radius property, and set the overflow property to "hidden". (For an example, see the Example section of this topic.) While this renders the element as you would expect, it also requires that you add a wrapper element to every element that exhibits this problem. It also continues to rely on a legacy Cascading Style Sheets (CSS) filter, which doesn't offer the performance improvements of more modern solutions. Therefore, this solution might not be ideal.

The better workaround is to use a Scalable Vector Graphics (SVG) background to fill the element with a gradient. Instead of using a filter property on the element, use the background-image property and set it to a SVG linearGradient or radialGradient element. After this initial declaration, add background-image property declarations set to a CSS gradient, using the appropriate browser vendor prefix for each browser you want to support. For an example, see the Example section of this topic.

Tip  To easily and automatically create gradients in SVG, try the SVG Background Gradient Maker on the IE Test Drive.

 

This code example includes an element that illustrates the problems described in Symptoms.

<!doctype html>
<html>

<head>
<meta content="IE=EmulateIE9" http-equiv="X-UA-Compatible">
<style type="text/css">
#test1 {
  margin: 10px;
  width: 200px;
  height: 200px;
  border: 2px solid black;
  border-radius: 50%;
  filter: progid:DXImageTransform.Microsoft.gradient( 
    startColorstr='#0065a4',endColorstr='#a0cf67',GradientType=0 );
  background-image: -moz-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Older Firefox */
  background-image: -o-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Opera */
  background-image: -webkit-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Chrome, Safari */
  background-image: linear-gradient(to bottom, #0065A4 0%, #A0CF67 100%); /* Firefox, IE10 */
}
</style>
</head>

<body>

<div id="test1">
</div>

</body>

</html>

This image shows how this code is displayed in Internet Explorer 10 in IE9 Standards mode. It appears identically in Internet Explorer 9 (also in IE9 Standards mode).

This next example uses the first workaround for this issue. A new wrapper element has been added (mask), the sizing and border-radius properties have been moved to the wrapper element, and its overflow property has been set to "hidden".

<!doctype html>
<html>

<head>
<meta content="IE=EmulateIE9" http-equiv="X-UA-Compatible">
<style type="text/css">
#mask {
  margin: 10px;
  width: 200px;
  height: 200px;
  border: 2px solid black;
  border-radius: 50%;
  overflow: hidden;
}
#test {
  width: 100%;
  height: 100%;
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0065a4',endColorstr='#a0cf67',GradientType=0 );
  background-image: -moz-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Older Firefox */
  background-image: -o-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Opera */
  background-image: -webkit-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Chrome, Safari */
  background-image: linear-gradient(to bottom, #0065A4 0%, #A0CF67 100%); /* Firefox, IE10 */
}
</style>
</head>

<div id="mask">
  <div id="test">
  </div>
</div>

</body>

</html>

The preferred solution is shown in the next example. Notice that the only change we've made is to remove the CSS filter declaration and add a new background-image declaration set to the URL of a SVG file.

Note  You don't have to create a separate SVG file to make this work; you can embed the SVG in your HTML page. We've chosen to create a new file to make this demonstration easier to follow.

 

<!doctype html>
<html>

<head>
<meta content="IE=EmulateIE9" http-equiv="X-UA-Compatible">
<style type="text/css">
#test {
  margin: 10px;
  width: 200px; 
  height: 200px;
  border: 2px solid black;
  border-radius: 50%;

  background-image: url('./background.svg'); /* IE9 */
  background-image: -moz-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Older Firefox */
  background-image: -o-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Opera */
  background-image: -webkit-linear-gradient(top, #0065A4 0%, #A0CF67 100%); /* Chrome, Safari */
  background-image: linear-gradient(to bottom, #0065A4 0%, #A0CF67 100%); /* Firefox, IE10 */
}
</style>
</head>

<body>

<div id="test">
</div>

</body>

</html>

The SVG file is very simple. Inside the svg element are two elements: the linearGradient element specifies the linear gradient, and the rect element makes the gradient fill the page (or, as in this case, the element that this file provides the background for).

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
  <linearGradient id="g791" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%">
    <stop stop-color="#0065A4" offset="0"/>
    <stop stop-color="#A0CF67" offset="1"/>
  </linearGradient>
  <rect x="0" y="0" width="1" height="1" fill="url(#g791)" />
</svg>

Because Internet Explorer 9 doesn't support the gradient functions, it picks up on the background-image declaration set to the URL of our SVG file and ignores all the subsequent gradient declarations. Other browsers, including Internet Explorer 10, pick up on the last declaration that they support. This means the browser will pass over the first background-image declaration in favor of the one set to whichever prefixed gradient function they support. Internet Explorer 10 supports the linear-gradient function with no vendor prefix, which is specified in the last declaration.

Both solutions produce an identical output, shown here:

SVG Background Gradient Maker