While working on the diet branch, we found ourselves in need of a new solution for an old problem that affects Internet Explorer 9 if border-radius and a gradient filter background are applied to a DOM element.
Consider a div element with rounded corners:
#test { width: 200px; height: 100px; border-radius: 20px; border: 5px solid red; }
To give it a color gradient background, we add a CSS linear-gradient which is supported in most modern browsers (Firefox, Chrome, Opera, IE10):
background-image: linear-gradient(#0000FF 0%, #FFFF00 100%);
Internet Explorer 9 doesn’t support linear-gradient, but it features the proprietary Filters and Transitions API which we can use to achieve mostly the same result:
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#FF0000FF', EndColorStr='#FFFFFF00';);
And there’s the problem: The gradient filter doesn’t respect the border-radius property so the background overlaps the corners. A common solution for this is to wrap two elements, applying the border-radius to the outer element and the gradient to the inner element. qooxdoo’s decorators take this approach as well, but for diet our goal was to eliminate the decorator elements entirely and apply all styles directly to the content element, so we had to come up with a new solution.
Fortunately, IE9 supports Canvas and drawing a gradient is pretty simple:
var startColor = "#0000FF"; var startColorPosition = 0; var endColor = "#FFFF00"; var endColorPosition = 100; var width = 1; var height = 200; var canvas = document.createElement("canvas"); canvas.width = width; canvas.height = height; var ctx = canvas.getContext('2d'); var lingrad = ctx.createLinearGradient(0, 0, 0, height); lingrad.addColorStop(startColorPosition / 100, startColor); lingrad.addColorStop(endColorPosition / 100, endColor); ctx.fillStyle = lingrad; ctx.fillRect(0, 0, width, height);
In qx.desktop’s theming system the gradient is rendered only once and will then be applied to any widget using the same decorator. Since we don’t know in advance how tall each widget is going to be, we use a fixed size of 1 x 200 pixels. Finally, we convert the drawing into a data URL and apply it like a regular background image, stretching it to fill out the element:
var el = document.getElementById("test"); el.style["background-image"] = 'url(' + canvas.toDataURL() + ')'; el.style["background-size"] = "100% 100%";
And that’s it, border-radius and background gradient combined without a wrapper element.



