{"id":896,"date":"2010-03-09T01:00:05","date_gmt":"2010-03-09T05:00:05","guid":{"rendered":"http:\/\/www.useragentman.com\/blog\/?p=896"},"modified":"2019-01-31T13:16:14","modified_gmt":"2019-01-31T17:16:14","slug":"cross-browser-css-transforms-even-in-ie","status":"publish","type":"post","link":"https:\/\/www.useragentman.com\/blog\/2010\/03\/09\/cross-browser-css-transforms-even-in-ie\/","title":{"rendered":"Cross Browser CSS Transforms &#8211; even in IE"},"content":{"rendered":"<div class=\"importantNotes\">\n<h3>Updates:<\/h3>\n<ul>\n<li><strong>(March 7, 2013)<\/strong> The examples on this page were missing due to a migration issue when upgrading my blogging software.  Thanks to James Wages for pointing this out.<\/li>\n<li><strong>(August 11, 2012)<\/strong> The <code>skew()<\/code> transform no longer works in Firefox, due to <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/CSS\/transform#skew\">not being in the CSS3 specification anymore<\/a>.  Developers must use the <code>skewX()<\/code> and <code>skewY()<\/code> functions instead.  The examples in cssSandaper, as well as this documentation, have been updated to reflect this change in the spec.  Thanks to <a href=\"http:\/\/telares.cifasis-conicet.gov.ar\/libro\/\">Pablo<\/a>, who gave a bug report on the cube example below that led me to find out about this.<\/li>\n<li><strong>(June 29th, 2011):<\/strong> cssSandpaper has been <a href=\"https:\/\/www.useragentman.com\/blog\/2011\/06\/29\/full-css3-text-shadows-even-in-ie\/\">updated to support CSS3 text-shadows in IE<\/a>.<\/li>\n<li><strong>(August 28th, 2010)<\/strong> cssSandpaper now <a href=\"https:\/\/www.useragentman.com\/blog\/2010\/08\/28\/coding-colors-easily-using-css3-hsl-notation\/\">supports HSL\/HSLA colors<\/a>.<\/li>\n<li><strong>(May 6th, 2010):<\/strong> cssSandpaper has been <a href=\"https:\/\/www.useragentman.com\/blog\/2010\/05\/06\/csssandpaper-now-supports-transform-translate-and-rgba-gradients\/\">updated to support RGBA gradients<\/a>.<\/li>\n<li><strong>(April 6, 2010):<\/strong> Please see the <a href=\"\/blog\/2010\/04\/05\/cross-browser-animated-css-transforms-even-in-ie\/\">follow up article on Cross Browser CSS3 Animation<\/a> which explores scripting CSS3 properties.<\/li>\n<\/ul>\n<\/div>\n<div class=\"mceTemp\">\n<dl id=\"attachment_822\" class=\"wp-caption alignright\" style=\"width: 267px;\">\n<dt class=\"wp-caption-dt\"><a href=\"https:\/\/www.useragentman.com\/tests\/cssSandpaper\/cube3.html\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-822 \" title=\"CSS3 Cube Layout Example\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeExampleScreenshot.png\" alt=\"\" width=\"257\" height=\"208\" \/><\/a><\/dt>\n<dd class=\"wp-caption-dd\">\n<div>An example of a page using the CSS Transform property and cssSandpaper.  Visible in most major browsers, including Internet Explorer.  Layout based on work done by Paul Hayes in his article <a href=\"&lt;\/dd\"><\/a><\/div>\n<\/dd>\n<\/dl>\n<\/div>\n<p><a href=\"&lt;\/dd\">The <\/a><a href=\"http:\/\/www.w3.org\/TR\/css3-2d-transforms\/\">CSS <code>transform<\/code> property<\/a> allows developers to rotate, scale, and skew blocks of HTML via CSS.  Although you can do the same thing with images in Photoshop or The GIMP, using CSS transforms allows developers to do the same thing with any HTML markup and allows users to select the text within the transformed object.<\/p>\n<p>When I first saw sites using <code>transform<\/code>, I looked at the underlying code and tried to produce pages using <code>transform<\/code> in all browsers.  Although Firefox, Opera and Webkit based browser support it via <a href=\"http:\/\/reference.sitepoint.com\/css\/vendorspecific\">vendor-specific prefixes<\/a> (using <code>-moz-transform<\/code>, <code>-o-transform<\/code> and <code>-webkit-transform<\/code> respectively) Internet Explorer doesn&#8217;t support it at all.  I didn&#8217;t like that, so I took out my JavaScript whip, beat Explorer into submission and made it do my bidding (but not without getting a few mental bruises of my own).<\/p>\n<p>Before I start talking about the details of my solution, let&#8217;s take a look at a few examples of it in action.  The following code has been tested with Firefox 3.5, Safari 4,  Chrome 4, Internet Explorer 6 and higher.<\/p>\n<ol>\n<li><a href=\"\/tests\/cssSandpaper\/rotateTest.html\">Rotations Example<\/a><\/li>\n<li><a href=\"\/tests\/cssSandpaper\/skewTest.html\">Skew Example<\/a><\/li>\n<li><a href=\"\/tests\/cssSandpaper\/cube3.html\">Cube Example, using rotates and skews<\/a><\/li>\n<li><a href=\"\/tests\/cssSandpaper\/example.html\">Another example that looks like a CSS3 version of a Geocities page.<\/a><\/li>\n<\/ol>\n<p>(The examples  also work on my copy of Opera 10.5, although I have seen it fail on other installations &#8211; I will update this post when I find  out why).<\/p>\n<h2>cssSandpaper to the Rescue<\/h2>\n<p>I saw the design potential of using CSS transforms and was frustrated at Explorer&#8217;s lack of support.  I originally tried a non-JavaScript solution which involved creating CSS rules that combine <code>transform<\/code> with an IE technology that does something similar: the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms533014%28VS.85%29.aspx\"><code>DXImageTransform.Microsoft.Matrix<\/code> CSS <code>filter<\/code><\/a>.<\/p>\n<p>I then, to steal a phrase from Russel Peters, started to Hurt Real Bad:<\/p>\n<ul>\n<li>the syntax of <code>transform<\/code> is very obvious:<br \/>\n<blockquote class=\"code\">\n<pre>#myObject {\r\n   transform: rotate(40deg) scale(2.0);\r\n}<\/pre>\n<\/blockquote>\n<p>but the IE filter code is quite intimidating:<\/p>\n<blockquote class=\"code\">\n<pre>#myObject {\r\n   filter: progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand',\r\n        M11=1.5320888862379554, M12=-1.2855752193730787,\r\n        M21=1.2855752193730796, M22=1.5320888862379558);\r\n}<\/pre>\n<\/blockquote>\n<p>The scary numbers that the <code>DXImageTransform.Microsoft.Matrix<\/code> filter uses requires knowledge of matrix and vector mathematics.  Even though there is a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Transformation_matrix\">great Wikipedia article on the subject<\/a>, even the mathematically gifted wouldn&#8217;t want to do the calculations to do a simple rotate in CSS (I would like to note here that even though I have a university degree in Mathematics, I hate doing arithmetic inside my head.  If you don&#8217;t believe me, watch  me figure out a tip at a restaurant sometime.  I&#8217;m not kidding).<\/li>\n<li>although it is possible to have a list of transformations using <code>transform<\/code>, the <code>DXImageTransform.Microsoft.Matrix<\/code> filter only allows one transform matrix. In order to implement multiple transforms using one filter,  a designer would have to <a href=\"http:\/\/en.wikipedia.org\/wiki\/Matrix_multiplication\">convert all the transforms into matrices and multiply them together<\/a>.  Again, as ugly as I am when I first wake up in the morning.<\/li>\n<li>when rotating, skewing, or doing any other transformations on objects using the <code>transform<\/code> property, the center of the object remains fixed.  However, the <code>Matrix<\/code> filter doesn&#8217;t keep the centre of the transformed object fixed, as seen by the illustration below:<br \/>\n<table class=\"screenshots\">\n<thead>\n<tr>\n<th>Rotate using CSS transform<\/th>\n<th>Rotate using IE Filter<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateFirefox.png\"><\/a><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateFirefox.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-872\" title=\"Screenshot of object rotated using CSS transform property.\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateFirefox.png\" alt=\"\" width=\"241\" height=\"240\" srcset=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateFirefox.png 241w, https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateFirefox-150x150.png 150w\" sizes=\"auto, (max-width: 241px) 100vw, 241px\" \/><\/a><\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateIE.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-873\" title=\"example of object rotated with IE filter.\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateIE.png\" alt=\"\" width=\"241\" height=\"240\" srcset=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateIE.png 241w, https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/rotateIE-150x150.png 150w\" sizes=\"auto, (max-width: 241px) 100vw, 241px\" \/><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/li>\n<\/ul>\n<p><a class=\"exampleLink\" href=\"\/tests\/cssSandpaper\/failedRotateExample.html\">See the above example in action (compare IE with the other browsers to see the difference for yourself)<\/a><\/p>\n<p>I was about to give up on my endeavor until I read Weston Ruter&#8217;s clever <a href=\"http:\/\/weston.ruter.net\/projects\/css-gradients-via-canvas\/\">CSS Gradients in Canvas<\/a> article, which implements gradients in older versions Firefox and Opera.  What I really liked was how he used the CSS from a web page to place the canvas gradients in the page (as opposed to using CSS classes to indicate where the gradients should go).   I then thought it would be a great idea to do the same with CSS transforms &#8211; why not have  JavaScript find out which objects are transformed by reading the style sheets containing the transform rules, and if the browser is Internet Explorer, apply the <code>Matrix<\/code> filter, while translating the image so that the center is maintained.  How hard could it be &#8230;&#8230;.. right?<\/p>\n<p>After a few obsessive months of coding, coffee drinking and Asprin popping (as well angrily asking myself on several occasions why the &amp;@$! I would wanted to do this in the first place), I created <code>cssSandpaper.js<\/code>, a library that implements <code>transform<\/code> (and some other CSS3 properties) as consistently as possible in all browsers.  It uses many ideas from Ruter&#8217;s gradient script, as well as <code>sylvester.js<\/code>, <a href=\"www.jcoglan.com\/\">James Coglan&#8217;s<\/a> brilliant <a href=\"http:\/\/sylvester.jcoglan.com\/\">matrix and vector math library<\/a>.<\/p>\n<p>The code is currently in a beta stage, but I think that it&#8217;s in good enough shape that developers can start to play around with these really cool effects today and have it work in almost any browser.<\/p>\n<h2>Browser Differences<\/h2>\n<p>After I finished cssSandpaper and played around with transforms, I found some slight differences in the way browsers handled them:<\/p>\n<ul>\n<li>If you transform an object with scrollbars, it is possible to scroll the object in most browsers in most cases.  However, in the cube page I mocked up, I noticed the following behaviour:\n<ul>\n<li>the left facing side of the cube isn&#8217;t easily accessible in IE.<\/li>\n<li>the scrollbars don&#8217;t appear at all in Opera.<\/li>\n<li>the scrollbars are not quite clear in Chrome for Windows, although one can still scroll the sides if you can guess where they are.<\/li>\n<li>Firefox 3.5 for Mac puts the scrollbars in strange places (this has been fixed 3.6).<\/li>\n<\/ul>\n<\/li>\n<li>In Internet Explorer, the text is selectable but sometimes it takes a few tries to figure out how to do it (try selecting text with IE in my cube mockup and you&#8217;ll see what I mean).<\/li>\n<li>When selecting text within Firefox, the text tends to jump around ever so slightly for some odd reason (this is quite a subtle effect that it is probably not noticeable in most instances).<\/li>\n<li>It <strong>looks<\/strong> like Internet Explorer takes the block of HTML, converts it to an image and then does the transform (I&#8217;m not sure .. I&#8217;m guessing).  As a result, the text in certain situations will look a little blurry, especially if scaling is involved.<\/li>\n<\/ul>\n<p>As to be expected, the rendering of the transformed text in the other browsers slightly differs:<\/p>\n<table class=\"screenshots\">\n<thead>\n<tr>\n<th><\/th>\n<th>Explorer 6.x+<\/th>\n<th>Firefox 3.5+<\/th>\n<th>Safari 4.0+<\/th>\n<th>Chrome 3.0+<\/th>\n<th>Opera 10.0+<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th>Windows<\/th>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeExplorerWindows.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" title=\"cubeExplorerWindows\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeExplorerWindows.png\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeFirefoxWindows.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeFirefoxWindows.png\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeSafariWindows.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeSafariWindows.png\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeChromeWindows.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" title=\"cubeExplorerWindows\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeChromeWindows.png\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeOperaWindows.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeOperaWindows.png\" alt=\"\" \/><\/a><\/td>\n<\/tr>\n<tr>\n<th>Mac OS X<\/th>\n<td style=\"text-align: center;\">Not Applicable<\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeFirefoxMac.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeFirefoxMac.png\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeSafariMac.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeSafariMac.png\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeChromeMac.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeChromeMac.png\" alt=\"\" \/><\/a><\/td>\n<td>Doesn&#8217;t support transforms yet (as of version 10.50)<\/td>\n<\/tr>\n<tr>\n<th>Linux<\/th>\n<td style=\"text-align: center;\">Not Applicable<\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeFirefoxUbuntu.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeFirefoxUbuntu.png\" alt=\"\" \/><\/a><\/td>\n<td style=\"text-align: center;\">Not Applicable<\/td>\n<td><a href=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeChromeUbuntu.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-840\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2010\/03\/cubeChromeUbuntu.png\" alt=\"\" \/><\/a><\/td>\n<td>Doesn&#8217;t support transforms yet (as of version 10.50)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Using cssSandpaper<\/h2>\n<p>After <a href=\"\/downloads\/cssSandpaper.1.0-beta1.zip\">downloading the archive<\/a> you must put the following tags into the head of your document <strong>after all of your style sheet declarations<\/strong> (this is to ensure the JavaScripts will run after the style sheets are loaded):<\/p>\n<blockquote class=\"code\">\n<pre>&lt;script type=\"text\/javascript\" src=\"path\/to\/js\/cssQuery-p.js\"&gt;&lt;\/script&gt;\r\n&lt;script type=\"text\/javascript\" src=\"path\/to\/js\/jcoglan.com\/sylvester.js\"&gt;&lt;\/script&gt;\r\n&lt;script type=\"text\/javascript\" src=\"path\/to\/js\/cssSandpaper.js\"&gt;&lt;\/script&gt;<\/pre>\n<\/blockquote>\n<p>You can then use the transform property in your web pages.  Note that since the specification for the transform property is finalized by the W3C, I decided to use the  <a href=\"http:\/\/reference.sitepoint.com\/css\/vendorspecific\">vendor-specific prefix<\/a> <code>-sand-<\/code> before each CSS3 property it supports.<\/p>\n<p>The following is a description of how to use <code>transform<\/code>, as well as two other CSS3 properties that cssSandpaper supports, <code>box-shadow<\/code> and <code>gradient<\/code>.<\/p>\n<p><a class=\"exampleLink\" href=\"https:\/\/www.useragentman.com\/blog\/csssandpaper-a-css3-javascript-library\/\">Go to the cssSandpaper documentation to download the latest version.<\/a><\/p>\n<h2>-sand-transform<\/h2>\n<p><!-- Begin steps --><\/p>\n<div class=\"steps\">\n<h3 class=\"first\">Description<\/h3>\n<p>Transforms allow developers to rotate, scale, and skew blocks of HTML via CSS.<\/p>\n<h3>Syntax<\/h3>\n<blockquote class=\"code\">\n<pre>#container {\r\n   -sand-transform:  <em>&lt;function-list&gt;<\/em>;\r\n}<\/pre>\n<\/blockquote>\n<p>where <em>&lt;function-list&gt;<\/em> can be a space separated list of the following functions:<\/p>\n<table class=\"screenshot\">\n<thead>\n<tr>\n<th>Function<\/th>\n<th>Purpose<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>rotate(angle)<\/code><\/td>\n<td>Rotates HTML elements.  <code>angle<\/code> can be in degrees (e.g. rotate(30deg)) or radians <code>rotate(1.3rad)<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>scale(sx[, sy])<\/code><\/td>\n<td>Scales HTML elements.  <code>sx<\/code> and <code>sy<\/code> are numbers, where <code>1<\/code> represents the original size, <code>2<\/code> represents twice the size, etc.  Note that if <code>sy<\/code> isn&#8217;t specified, it is assumed to be equal to <code>sx<\/code>.  Similar functions are <code>scaleX(sx)<\/code> and <code>scaleY(sy)<\/code>.<\/td>\n<\/tr>\n<tr>\n<td><code>skewX(ax)<\/code>, and <code>skewY(ay)<\/code><\/td>\n<td>These functions skew the object around the x and y axes by the specified angles in degrees or radians.<strong>Note: the <code>skew(ax, ay)<\/code> function, which used to work in browsers that support CSS3 Transforms natively is no longer part of the W3C CSS3 spec and is no longer supported by Firefox.<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>matrix(a, c, b, d, tx, ty)<\/code><\/td>\n<td>Applies a 2D transformation matrix comprised of the specified six values.  If you aren&#8217;t familiar with linear algebra and matrix arithmetic, this function will be hard to understand.  For further information, you may want to read <a href=\"http:\/\/en.wikipedia.org\/wiki\/Transformation_matrix\">Wikipedia&#8217;s Transformation Matrix<\/a> article, although if you are mathematically challenged, you may run away from your computer screaming.<\/p>\n<p>If you are familiar with matrix multiplication, note that c and b are reversed.  This follows the way Firefox has implemented this method (i <strong>believe<\/strong> WebKit based browsers reverse these numbers).<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Note:<\/strong> non-Explorer browsers support the <code>translate<\/code> function as well.  I have not been able to find a way to make this work IE at this time, due to a technical  issue with the IE&#8217;s <code>Matrix<\/code> filter property (for those who want details, I use <code>sizingMethod='auto expand'<\/code> when using the <code>Matrix<\/code> filter which doesn&#8217;t support translations, and using sizingMethod=&#8217;crop&#8217; is not suitable to emulate the <code>transform<\/code> property).  For this reason, the <code>tx<\/code> and <code>ty<\/code> values of the <code>matrix()<\/code> function are not supported as well.<\/p>\n<h3>Examples<\/h3>\n<ul>\n<li><a href=\"\/tests\/cssSandpaper\/rotateTest.html\">Rotations<\/a><\/li>\n<li><a href=\"\/tests\/cssSandpaper\/skewTest.html\">Skews<\/a><\/li>\n<\/ul>\n<\/div>\n<h2>-sand-box-shadow<\/h2>\n<div class=\"steps\">\n<h3 class=\"first\">Description<\/h3>\n<p><code>box-shadow<\/code> allows us to take a block level element and put a shadow underneath.  There can optionally set a blur factor to give a warmer effect to the shadow.<\/p>\n<h3>Syntax<\/h3>\n<blockquote class=\"code\">\n<pre>#container {\r\n   -sand-box-shadow: <em>&lt;horizontal-offset&gt;<\/em> <em>&lt;vertical-offset&gt;<\/em> <em>&lt;blur-radius&gt;<\/em> <em>\r\n<\/em>;\r\n}<\/pre>\n<\/blockquote>\n<p>Note that in IE, the <code>blur-radius<\/code> is not supported, due to a lack of support in IE&#8217;s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms533014%28VS.85%29.aspx\"><code>DropShadow<\/code> filter<\/a>.<\/p>\n<h3>Examples<\/h3>\n<ul>\n<li><a href=\"\/tests\/cssSandpaper\/boxShadowTest.html\">Box-Shadow Example<\/a><\/li>\n<\/ul>\n<\/div>\n<h2>-sand-gradient<\/h2>\n<div class=\"steps\">\n<h3 class=\"first\">Description<\/h3>\n<p>Gradients are gradual blends of color, and can be <code>linear<\/code> or <code>radial<\/code>:<\/p>\n<h3>Syntax<\/h3>\n<blockquote class=\"code\">\n<pre>#container {\r\n   background-image: -sand-gradient(<em>&lt;type&gt;, &lt;start-point&gt;, &lt;end-point&gt;, &lt;color-stop1&gt;, &lt;color-stop2&gt;, ..., &lt;color-stopN&gt;<\/em>)\r\n}<\/pre>\n<\/blockquote>\n<p>The type can be <code>linear<\/code> and <code>gradient<\/code>, although Internet Explorer doesn&#8217;t support radial gradients at this time, due to limitations in IE&#8217;s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms532997%28VS.85%29.aspx\"><code>gradient<\/code> filter<\/a>.  Internet Explorer also only supports simple linear gradients (i.e. only  horizontal and vertical and only two colours).<\/p>\n<p>A more detailed explanation can be found in the <a href=\"http:\/\/dev.w3.org\/csswg\/css3-images\/#linear-gradients\">section regarding gradients<\/a> of the <a href=\"http:\/\/dev.w3.org\/csswg\/css3-images\/\">W3C&#8217;s working draft of CSS Image Values Module Level 3<\/a><\/p>\n<h3>Examples<\/h3>\n<ul>\n<li><a href=\"\/tests\/cssSandpaper\/gradientTest.html\">Gradients Example Page<\/a><\/li>\n<\/ul>\n<\/div>\n<h2>Other Known Issues<\/h2>\n<ul>\n<li>Currently, when a users changes the font-size in IE, the layout gets a little messed up.  This will be fixed in a future release.<\/li>\n<li>Scripting in IE cannot be done via the usual <code>obj.style.transform<\/code>.  There is, however, an alternative way of scripting the cssSandpaper supported properties which will be outlined in a future blog post (I don&#8217;t mean to keep anyone in suspense &#8230; it&#8217;s just that I feel like I&#8217;ve spent too much time on this post and I want to get at least this part out the door :-) ).<\/li>\n<li>Opera 10.5 sort of works.  It works on my copy, but not on another copy I&#8217;ve seen.  I don&#8217;t know why yet, but I will find out soon and post and update when I do.<\/li>\n<li>Weston Ruter&#8217;s gradient script has more features.  I will incorporate them in a future release.<\/li>\n<\/ul>\n<h2>Future Work<\/h2>\n<p>cssSandpaper will eventually be about more than just transforms &#8211; I would like to be able to support other advanced CSS topics (maybe even animations, if it is possible). It probably has a few bugs in it &#8211; I would really appreciate anyone letting  me know if you find any (my e-mail address is at the top left part of the page).<\/p>\n<p>If anyone would like to get contribute code or do testing, I would love the help too.  :-)<\/p>\n<h2>Acknowledgments<\/h2>\n<p>I would like to thank Weston Ruter for his <a href=\"http:\/\/weston.ruter.net\/projects\/css-gradients-via-canvas\/\">CSS Gradients in Canvas<\/a> script, since I stole many of his ideas with his permission (I will be implementing more of the advanced features of his script in a future release of CSS3Sandpaper).  I would also like to thank  <a href=\"www.jcoglan.com\/\">James Coglan<\/a> for building  <a href=\"http:\/\/sylvester.jcoglan.com\/\">Sylvester<\/a> so I didn&#8217;t have to.<\/p>\n<h2>Downloads<\/h2>\n<p><a class=\"exampleLink\" href=\"https:\/\/www.useragentman.com\/blog\/csssandpaper-a-css3-javascript-library\/\">Go to the cssSandpaper documentation to download the latest version.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The CSS transform  property allows developers to rotate, scale, and skew blocks of HTML via CSS.  There are variants that work natively on all major browsers &#8230; except for IE.  I created a new library, cssSandpaper, that implements CSS3 transforms (as well as gradients and box-shadows) in IE.  It also allows developers to use one transform declaration, instead of three vendor-specific ones for Opera, Firefox and WebKit browsers.  <\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[126,9,38,125,120,7,119,41],"tags":[45,40,42,43,39,44,222],"class_list":["post-896","post","type-post","status-publish","format-standard","hentry","category-box-shadow","category-css","category-css3","category-gradients","category-ie-visual-filters","category-javascript","category-polyfills","category-transform","tag-cross-browser","tag-css-sandpaper","tag-css-transform","tag-css3-transform","tag-csssandpaper","tag-ie-filters","tag-transform"],"_links":{"self":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/896","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/comments?post=896"}],"version-history":[{"count":43,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/896\/revisions"}],"predecessor-version":[{"id":7669,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/896\/revisions\/7669"}],"wp:attachment":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/media?parent=896"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/categories?post=896"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/tags?post=896"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}