惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
雷峰网
雷峰网
Recent Announcements
Recent Announcements
月光博客
月光博客
G
Google Developers Blog
腾讯CDC
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
T
Tenable Blog
云风的 BLOG
云风的 BLOG
W
WeLiveSecurity
博客园 - 【当耐特】
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 聂微东
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
P
Privacy International News Feed
MyScale Blog
MyScale Blog
K
Kaspersky official blog
T
The Blog of Author Tim Ferriss
Attack and Defense Labs
Attack and Defense Labs
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
aimingoo的专栏
aimingoo的专栏
I
Intezer
Vercel News
Vercel News
小众软件
小众软件
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
Latest news
Latest news
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tor Project blog
S
Security Affairs
P
Proofpoint News Feed
博客园 - 三生石上(FineUI控件)
博客园 - Franky
C
Cyber Attacks, Cyber Crime and Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
美团技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
Security @ Cisco Blogs
L
LINUX DO - 热门话题
Know Your Adversary
Know Your Adversary
Project Zero
Project Zero
D
Docker
L
Lohrmann on Cybersecurity
F
Full Disclosure

Mathias Bynens

A horrifying globalThis polyfill in universal JavaScript JavaScript engine fundamentals: optimizing prototypes JavaScript engine fundamentals: Shapes and Inline Caches Asynchronous stack traces: why await beats Promise#then() ECMAScript regular expressions are getting better! Unicode property escapes in JavaScript regular expressions ES2015 const is not about immutability Valid JavaScript variable names in ES2015 Unicode-aware regular expressions in ES2015 Dear Google, please fix plain text emails in Gmail PBKDF2+HMAC hash collisions explained JavaScript has a Unicode problem Processing Content Security Policy violation reports Hiding JSON-formatted data in the DOM with CSP enabled Loading JSON-formatted data with Ajax and xhr.responseType='json' Reserved keywords in JavaScript How to support full Unicode in MySQL databases How to speedrun Dropbox’s Dropquest 2012 Unquoted font family names in CSS Unquoted property names / object keys in JavaScript Valid JavaScript variable names in ES5 CSS character escape sequences JavaScript’s internal character encoding: UCS-2 or UTF-16? The smallest possible valid (X)HTML documents JavaScript character escape sequences JavaScript foo.prototype.bar notation Ambiguous ampersands HTML element + attribute notation How I detect and use localStorage: a simple JavaScript pattern Unquoted attribute values in HTML and CSS/JS selectors The end-tag open (ETAGO) delimiter Using the oninput event handler with onkeyup/onkeydown as its fallback Everything you always wanted to know about touch icons AirPlay video support in iOS Safari — a bookmarklet Completing Dropbox’s Dropquest 2011 in 60 seconds Using CSS without HTML How to create simple Mac apps from shell scripts Using setTimeout to speed up window.onload Bulletproof JavaScript benchmarks Thoughts on Safari Reader’s generated HTML How to enable Safari Reader on your site? The XML serialization of HTML5, aka ‘XHTML5’ The id attribute got more classy in HTML5 The three levels of HTML5 usage The HTML5 document.head DOM tree accessor Bulletproof HTML5 <details> fallback using jQuery Displaying hidden elements like <head> using CSS Inline <script> and <style> vs. external .js and .css — what’s the size threshold? Using Showdown/PageDown with and without jQuery
In defense of CSS hacks — introducing “safe CSS hacks”
Mathias · 2011-02-21 · via Mathias Bynens

How do you target Internet Explorer in your CSS? Do you use CSS hacks, conditional stylesheets or something else?

It’s the perfect trollbait. There have been plenty of discussions about this, and I don’t mean to start a new one. Everyone’s entitled to their own opinion, but the thing is that it’s not purely a philosophical matter. I am writing this article because I noticed there’s a lot of misunderstanding on the subject of CSS hacks.

People have been advocating three different approaches: conditional stylesheets, CSS hacks, or conditional classnames. All these techniques have their pros and cons. Let’s take a look.

Conditional stylesheets

Conditional comments make it very easy to specify stylesheets that should only be loaded in Internet Explorer, or even in specific versions of that browser. Non-IE browsers treat conditional comments as any other HTML comment. Here’s an example:

<!--[if lte IE 8]><link rel="stylesheet" href="lte-ie-8.css"><![endif]-->
<!--[if lte IE 7]><link rel="stylesheet" href="lte-ie-7.css"><![endif]-->
<!--[if lte IE 6]><link rel="stylesheet" href="lte-ie-6.css"><![endif]-->

This snippet will cause lte-ie-8.css to be loaded in IE8, IE7, IE6 and even in IE5. (Older IE versions don’t support conditional comments.) In IE7 and older versions, lte-ie-7.css will be loaded as well. In IE6 all three additional stylesheets will be loaded.

If you want to use this technique to style an element differently in specific versions of Internet Explorer, it’d look something like this:

/* Main stylesheet */
.foo { color: black; }

/* lte-ie-8.css, for IE8 and older */
.foo { color: green; }

/* lte-ie-7.css, for IE7 and older */
.foo { color: blue; }

/* lte-ie-6.css, for IE6 and older */
.foo { color: red; }

Pros

  • The conditional comments snippet is valid HTML.
  • Since there’s no need to use CSS hacks, you can even write valid CSS if you want to.

Cons

  • Performance decreases due to the multiple additional HTTP requests, depending on the browser.
  • Conditional comments block downloads in IE unless another (possibly empty) conditional comment is included earlier in the source.
  • The total file size increases, since the conditional comments have to be repeated for every HTML single document, and you’ll have to repeat the selector in every CSS file. More typing work!
  • Maintainability is negatively affected. You now have to maintain four separate stylesheets instead of just one. Whenever you make changes to your main CSS file, you need to remember to change the IE-specific CSS files if necessary.

Conditional classnames

Those not willing to use CSS hacks can always apply conditional classnames to the <html> or <body> element. This approach allows you to write clean and hack-free CSS at the cost of adding hacks conditional comments to your HTML.

<!--[if lt IE 7]><html class="ie6"><![endif]-->
<!--[if IE 7]>   <html class="ie7"><![endif]-->
<!--[if IE 8]>   <html class="ie8"><![endif]-->
<!--[if gt IE 8]><!--><html><!--<![endif]-->

This allows you to keep your browser-specific CSS in the same file:

.foo { color: black; }
.ie8 .foo { color: green; } /* IE8 */
.ie7 .foo { color: blue; } /* IE7 */
.ie6 .foo { color: red; } /* IE6 and IE5 (but who cares, right?) */

Pros

  • The conditional classes snippet is valid HTML. (Prior to HTML5, you would have to add the classes to the <body> element instead.)
  • Since there’s no need to use CSS hacks, you can even write valid CSS if you want to.
  • No additional HTTP requests are being issued to get the IE-specific styles.
  • In this particular case, the conditional comments don’t block downloads.

Cons

  • This technique increases the file size of every HTML document you use it for.
  • The use of the IE-specific classnames automatically increases the specificity of your selectors, which may not be what you want.
  • Since you’ll need the classnames in the selectors, you’ll have to use separate CSS rules for IE-specific styles.
  • The character encoding declaration (e.g. <meta charset="utf-8">) should be placed within the first 1024 bytes of the HTML document. Using this technique, you may cross this limit, especially if you’re adding lots of other attributes to the <html> element (since you’ll have to repeat them inside every conditional comment).
  • Using conditional comments around the opening <html> tag throws IE into compatibility view unless you set the X-UA-Compatible header in a server-side config.
  • Simon Pieters reports that using conditional comments before <meta http-equiv="X-UA-Compatible"> causes IE to ignore the <meta>. So again, you’ll need to set the X-UA-Compatible header in a server-side config.

CSS hacks

Paul Irish maintains a comprehensive list of CSS hacks for various browsers. In reality, you’ll rarely need to specifically target anything but IE. Here’s an overview of the three most popular CSS hacks and which browsers they’re supposed to target:

.foo {
	color: black;
	color: green\9; /* IE8 and older, but there’s more… */
	*color: blue; /* IE7 and older */
	_color: red; /* IE6 and older */
}

Note the use of the \9 CSS hack. Web developers noticed it could be used to easily target IE8 and older versions, so that’s what they did. But then there was IE9, and as it turned out, the final IE9 release was still affected by this hack (despite my bug report on the matter). All those CSS declarations that were meant to be for IE8 and earlier versions only, now got interpreted by IE9 as well. Needless to say, stuff broke, since IE9 doesn’t need most of the IE8-specific CSS fixes.

This is the perfect example of an unsafe CSS hack.

Safe CSS hacks

So what constitutes a “safe” CSS hack? What makes me even think there is such a thing?

Let’s face it — CSS hacks are still hacks. There’s no way to accurately predict how future browser versions will parse these rules. But we can make an educated guess — some hacks are less hacky than others. A safe CSS hack is a CSS hack that:

  • works in specific versions of a given web browser;
  • is unlikely to be parsed by all other browsers, including future versions.

Take the _property: value hack, for example. The CSS 2.1 spec says the following:

Keywords and property names beginning with - or _ are reserved for vendor-specific extensions.

A property name is an identifier.

In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, or a hyphen followed by a digit.

So who’s to say there will never be a property name starting with an underscore character? To quote the CSS3 spec:

Although [the underscore] is a valid start character, the CSS Working Group believes it will never define any identifiers that start with that character.

Both the _property: value and *property: value hacks (as seen in the above code block) are examples of safe CSS hacks. They were discovered, identified as bugs, and patched in a browser update. Since then, it’s very likely that Microsoft and other browser vendors added checks for these CSS hacks to their layout tests, to make sure no new browser version is shipped with a regression this significant.

If you discover a CSS hack in the latest version of a certain browser, it won’t be a safe hack until an updated version of that browser is released where the parser bug is fixed. For example, some people (myself included) have been looking for an IE9-specific CSS hack. Recently, one was found, but we’ll have to wait at least until the final IE10 release to use it, because IE10 may or may not be shipped with the same CSS parser bug. We can’t risk repeating the history of the \9 hack.

Pros

  • You don’t have to add conditional comments to every single HTML page.
  • No additional HTTP requests are being issued to get the IE-specific styles.
  • The specificity of your CSS selectors is preserved.
  • There’s no need to repeat CSS rules — you can just add extra declarations (with the hacks) to the declaration block.

Cons

  • They’re called CSS hacks for a reason — only use safe CSS hacks.
  • There’s no safe CSS hack for IE8 (yet?).
  • Contrary to conditional comments, most CSS hacks don’t validate. But then again, CSS3 properties and vendor-prefixed properties don’t validate either.

Combining conditional classnames with safe CSS hacks

Safe CSS hacks are preferable to conditional stylesheets or classnames, but what if you have to write IE9-specific styles? By definition, there won’t be a safe CSS hack for IE9 at least until IE10 is released. Also, what about IE8? There is no safe CSS hack (that I know of) that targets IE8 but not IE9. What to do?

In the HTML, we can use a minimal version of the conditional classnames technique, like so:

<!--[if lt IE 9]><html class="lte-ie8"><![endif]-->
<!--[if gt IE 8]><!--><html><!--<![endif]-->

We can then use .lte-ie8 as a styling hook in CSS selectors to target IE8 and older versions. Combined with safe CSS hacks, we can finally target IE8 and older versions without also affecting IE9:

.foo {
	color: black;
}

.lte-ie8 .foo {
	color: green; /* IE8 and older */
	*color: blue; /* IE7 and older */
	_color: red; /* IE6 and older */
}

This technique combines all the advantages of safe CSS hacks and conditional classnames, while minimizing the drawbacks.