N
NewsBot
Opacity. Gradients. Drop shadows.
Long before CSS proposals for Transitions and Transforms, Internet Explorer 4 supported visual special effects through CSS. This capability was further extended by Internet Explorer 5.5. As an example, the following rule could be used to apply opacity to an object:
filterrogidXImageTransform.Microsoft.Alpha(opacity=50).csharpcode, .csharpcode pre{ font-size: small color: black font-family: consolas, "Courier New", courier, monospace background-color: #ffffff /*white-space: pre*/}.csharpcode pre { margin: 0em }.csharpcode .rem { color: #008000 }.csharpcode .kwrd { color: #0000ff }.csharpcode .str { color: #006080 }.csharpcode .op { color: #0000c0 }.csharpcode .preproc { color: #cc6633 }.csharpcode .asp { background-color: #ffff00 }.csharpcode .html { color: #800000 }.csharpcode .attr { color: #ff0000 }.csharpcode .alt { background-color: #f4f4f4 width: 100% margin: 0em}.csharpcode .lnum { color: #606060 }Partly as a consequence of its early design, the syntax for filter properties violates the CSS 2.1 grammar: it includes a ‘:’ character, a delimiter used by CSS to separate property names from their values and therefore forbidden outside of a quoted string. The value syntax also relies on a functional notation i.e. of the form function(expression) but accepts the ‘=’ sign in the expression.
“OK, but what is really wrong with that?â€
The consequence of these violations can be quite visible when a filter is syntactically invalid e.g. missing a terminating parenthesis. CSS syntax error recovery rules require parsers to ignore unknown, illegal or malformed declarations by locating the end of such declarations and resuming parsing the rest of the style sheet. An important caveat is that certain character pairs must be matched during the recovery : if one or more ‘(‘ are found, the declaration does not end until the matching set of closing ‘)’ have been parsed.
Given the following markup :
doctype html>.bordered { border: 2px solid black padding: 5px} .filtered { filterrogidXImageTransform.Microsoft.Alpha(opacity=50 border: 1px dotted black background-color:lime width:75%}p#test { font-weight:bold color:red} Visit the IE Blog This text should be red A standard-compliant parser will render the following:
Because filter is a non-standard Microsoft extension, the parser must look for the end of the unknown bold red declaration so as to ignore it. As it encounters an opening ‘(‘ along the way but never finds its matching ‘)’ in the rest of the rule set the dotted border, background, width and paragraph rules end up being ignored as well.
Since it understands filters and is not strict in its CSS parsing, IE7 is more resilient in this case:
But the dotted border rule that follows the filter declaration remains lost.
How should IE8 standards mode handle filter declarations?
With a new stylesheet parser compliant with CSS 2.1, one option for IE8 would be to require filters such as the one above to be rewritten like this:
-ms-filter:"progidXImageTransform.Microsoft.Alpha(opacity=50)".csharpcode, .csharpcode pre{ font-size: small color: black font-family: consolas, "Courier New", courier, monospace background-color: #ffffff /*white-space: pre*/}.csharpcode pre { margin: 0em }.csharpcode .rem { color: #008000 }.csharpcode .kwrd { color: #0000ff }.csharpcode .str { color: #006080 }.csharpcode .op { color: #0000c0 }.csharpcode .preproc { color: #cc6633 }.csharpcode .asp { background-color: #ffff00 }.csharpcode .html { color: #800000 }.csharpcode .attr { color: #ff0000 }.csharpcode .alt { background-color: #f4f4f4 width: 100% margin: 0em}.csharpcode .lnum { color: #606060 }The –ms vendor prefix explicitly marks the property as proprietary to Microsoft. By delimiting the entire value as a string, grammatical delimiter issues are avoided. Other browsers are thus able to safely ignore this declaration even if the filter value itself is syntactically invalid.
This is in fact what IE8 Beta 1 and Beta 2 required.
“But what would this strict syntax mean for my web site?â€
It means none of your existing filter declarations are applied by IE8 Betas’ standards mode. At best, these declarations have no effect at worst, they are syntactically invalid and silently disable one or more declarations in your style sheet.
It also means that in order to apply a filter in both IE7 and IE8 Betas, you have to write two rules :
-ms-filter:"progidXImageTransform.Microsoft.Alpha(opacity=50)"filterrogidXImageTransform.Microsoft.Alpha(opacity=50).csharpcode, .csharpcode pre{ font-size: small color: black font-family: consolas, "Courier New", courier, monospace background-color: #ffffff /*white-space: pre*/}.csharpcode pre { margin: 0em }.csharpcode .rem { color: #008000 }.csharpcode .kwrd { color: #0000ff }.csharpcode .str { color: #006080 }.csharpcode .op { color: #0000c0 }.csharpcode .preproc { color: #cc6633 }.csharpcode .asp { background-color: #ffff00 }.csharpcode .html { color: #800000 }.csharpcode .attr { color: #ff0000 }.csharpcode .alt { background-color: #f4f4f4 width: 100% margin: 0em}.csharpcode .lnum { color: #606060 }Moreover, the sequence of these declarations mattered to IE8 parser in compatibility view: -ms-filter was required to come first.
“So I would have to go through all of my stylesheets that use this property and update them ?â€
Indeed, and this was a very expensive proposition for some of our customers and partners. While they were both very understanding and supportive of our standard compliance goals, the backward compatibility impact was sufficient for some to consider forcing Compatibility View when IE8 shipped until their assets were up to date. Which meant millions of users would upgrade to IE8 and still access these high-traffic sites through the IE7 layout engine.
A Pragmatic Solution
.spaced li { margin-bottom: 1em}While the decision may appear binary – should IE8 be backward-compatible or standard compliant? – other factors needed to be considered :
If the filter is syntactically invalid, however, IE8 should fail per standard rules.
This is what IE8 does since RC1.
“Since it is the only feature I and many others ever use filters for, why not just implement opacity?â€
Yes, opacity is a very common use case for filters today. However :
[*]As a CSS3 feature, opacity was beyond our compliance release goal - CSS 2.1 – and as such a stretch goal.[*]A common assumption is that implementing opacity is mostly a matter of converting the alpha filter value to a number between 0 and 1. As specified, however, the opacity property has side-effects on an element’s stacking context.[*]Opacity is not the only filter feature in use on the web. Some of these features do not have CSS counterparts.[/list]Built to pass a very large number of CSS test cases, IE8’s new layout engine is also expected to ‘just work’ with HTML and CSS input that is somewhat compliant, a little compliant or not compliant at all. It is expected to pass standard tests and support proprietary features from earlier releases. Being able to write one cross-browser stylesheet tomorrow is great, as long as yesterday’s stylesheets still work. The goals of web standards and the expectations of web designers and end users are not either-or: standard compliance and backward compatibility are essential.
Sylvain Galineau
Program Manager
More...
Long before CSS proposals for Transitions and Transforms, Internet Explorer 4 supported visual special effects through CSS. This capability was further extended by Internet Explorer 5.5. As an example, the following rule could be used to apply opacity to an object:
filterrogidXImageTransform.Microsoft.Alpha(opacity=50).csharpcode, .csharpcode pre{ font-size: small color: black font-family: consolas, "Courier New", courier, monospace background-color: #ffffff /*white-space: pre*/}.csharpcode pre { margin: 0em }.csharpcode .rem { color: #008000 }.csharpcode .kwrd { color: #0000ff }.csharpcode .str { color: #006080 }.csharpcode .op { color: #0000c0 }.csharpcode .preproc { color: #cc6633 }.csharpcode .asp { background-color: #ffff00 }.csharpcode .html { color: #800000 }.csharpcode .attr { color: #ff0000 }.csharpcode .alt { background-color: #f4f4f4 width: 100% margin: 0em}.csharpcode .lnum { color: #606060 }Partly as a consequence of its early design, the syntax for filter properties violates the CSS 2.1 grammar: it includes a ‘:’ character, a delimiter used by CSS to separate property names from their values and therefore forbidden outside of a quoted string. The value syntax also relies on a functional notation i.e. of the form function(expression) but accepts the ‘=’ sign in the expression.
“OK, but what is really wrong with that?â€
The consequence of these violations can be quite visible when a filter is syntactically invalid e.g. missing a terminating parenthesis. CSS syntax error recovery rules require parsers to ignore unknown, illegal or malformed declarations by locating the end of such declarations and resuming parsing the rest of the style sheet. An important caveat is that certain character pairs must be matched during the recovery : if one or more ‘(‘ are found, the declaration does not end until the matching set of closing ‘)’ have been parsed.
Given the following markup :
doctype html>.bordered { border: 2px solid black padding: 5px} .filtered { filterrogidXImageTransform.Microsoft.Alpha(opacity=50 border: 1px dotted black background-color:lime width:75%}p#test { font-weight:bold color:red} Visit the IE Blog This text should be red A standard-compliant parser will render the following:
Because filter is a non-standard Microsoft extension, the parser must look for the end of the unknown bold red declaration so as to ignore it. As it encounters an opening ‘(‘ along the way but never finds its matching ‘)’ in the rest of the rule set the dotted border, background, width and paragraph rules end up being ignored as well.
Since it understands filters and is not strict in its CSS parsing, IE7 is more resilient in this case:
But the dotted border rule that follows the filter declaration remains lost.
How should IE8 standards mode handle filter declarations?
With a new stylesheet parser compliant with CSS 2.1, one option for IE8 would be to require filters such as the one above to be rewritten like this:
-ms-filter:"progidXImageTransform.Microsoft.Alpha(opacity=50)".csharpcode, .csharpcode pre{ font-size: small color: black font-family: consolas, "Courier New", courier, monospace background-color: #ffffff /*white-space: pre*/}.csharpcode pre { margin: 0em }.csharpcode .rem { color: #008000 }.csharpcode .kwrd { color: #0000ff }.csharpcode .str { color: #006080 }.csharpcode .op { color: #0000c0 }.csharpcode .preproc { color: #cc6633 }.csharpcode .asp { background-color: #ffff00 }.csharpcode .html { color: #800000 }.csharpcode .attr { color: #ff0000 }.csharpcode .alt { background-color: #f4f4f4 width: 100% margin: 0em}.csharpcode .lnum { color: #606060 }The –ms vendor prefix explicitly marks the property as proprietary to Microsoft. By delimiting the entire value as a string, grammatical delimiter issues are avoided. Other browsers are thus able to safely ignore this declaration even if the filter value itself is syntactically invalid.
This is in fact what IE8 Beta 1 and Beta 2 required.
“But what would this strict syntax mean for my web site?â€
It means none of your existing filter declarations are applied by IE8 Betas’ standards mode. At best, these declarations have no effect at worst, they are syntactically invalid and silently disable one or more declarations in your style sheet.
It also means that in order to apply a filter in both IE7 and IE8 Betas, you have to write two rules :
-ms-filter:"progidXImageTransform.Microsoft.Alpha(opacity=50)"filterrogidXImageTransform.Microsoft.Alpha(opacity=50).csharpcode, .csharpcode pre{ font-size: small color: black font-family: consolas, "Courier New", courier, monospace background-color: #ffffff /*white-space: pre*/}.csharpcode pre { margin: 0em }.csharpcode .rem { color: #008000 }.csharpcode .kwrd { color: #0000ff }.csharpcode .str { color: #006080 }.csharpcode .op { color: #0000c0 }.csharpcode .preproc { color: #cc6633 }.csharpcode .asp { background-color: #ffff00 }.csharpcode .html { color: #800000 }.csharpcode .attr { color: #ff0000 }.csharpcode .alt { background-color: #f4f4f4 width: 100% margin: 0em}.csharpcode .lnum { color: #606060 }Moreover, the sequence of these declarations mattered to IE8 parser in compatibility view: -ms-filter was required to come first.
“So I would have to go through all of my stylesheets that use this property and update them ?â€
Indeed, and this was a very expensive proposition for some of our customers and partners. While they were both very understanding and supportive of our standard compliance goals, the backward compatibility impact was sufficient for some to consider forcing Compatibility View when IE8 shipped until their assets were up to date. Which meant millions of users would upgrade to IE8 and still access these high-traffic sites through the IE7 layout engine.
A Pragmatic Solution
.spaced li { margin-bottom: 1em}While the decision may appear binary – should IE8 be backward-compatible or standard compliant? – other factors needed to be considered :
- The filter property is proprietary to Microsoft and unlikely to be standardized or supported by other browser vendors
- The filter property is widely used
- Both the CSS grammar rules and existing implementations are able to skip syntactically valid filter rules safely.
- In IE8 standards mode, our CSS parser must conform with CSS 2.1 error recovery.
If the filter is syntactically invalid, however, IE8 should fail per standard rules.
This is what IE8 does since RC1.
“Since it is the only feature I and many others ever use filters for, why not just implement opacity?â€
Yes, opacity is a very common use case for filters today. However :
[*]As a CSS3 feature, opacity was beyond our compliance release goal - CSS 2.1 – and as such a stretch goal.[*]A common assumption is that implementing opacity is mostly a matter of converting the alpha filter value to a number between 0 and 1. As specified, however, the opacity property has side-effects on an element’s stacking context.[*]Opacity is not the only filter feature in use on the web. Some of these features do not have CSS counterparts.[/list]Built to pass a very large number of CSS test cases, IE8’s new layout engine is also expected to ‘just work’ with HTML and CSS input that is somewhat compliant, a little compliant or not compliant at all. It is expected to pass standard tests and support proprietary features from earlier releases. Being able to write one cross-browser stylesheet tomorrow is great, as long as yesterday’s stylesheets still work. The goals of web standards and the expectations of web designers and end users are not either-or: standard compliance and backward compatibility are essential.
Sylvain Galineau
Program Manager
More...