当前位置: 首页 > news >正文

防御 CSS 黑客——介绍“安全的 CSS hacks”

我们如何在 CSS 中定位 Internet Explorer? 你使用 CSS hacks、条件样式表或其他东西吗?

关于这个已经有很多讨论了,我并不是要开始一个新的讨论。 每个人都有权发表自己的意见,但问题是这不仅仅是一个哲学问题。 我写这篇文章是因为我注意到在 CSS hack 这个主题上存在很多误解。

人们一直提倡三种不同的方法:条件样式表、CSS hack 或条件类名。 所有这些技术都有其优点和缺点。 让我们来看看。


条件样式表

条件注释使得指定只应在 Internet Explorer 或甚至在该浏览器的特定版本中加载的样式表变得非常容易。 非 IE 浏览器将条件注释视为任何其他 HTML 注释。 这是一个例子:

<!--[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]-->

此代码段将导致 lte-ie-8.css 在 IE8、IE7、IE6 甚至 IE5 中加载。 (旧的 IE 版本不支持条件注释。)在 IE7 和旧版本中,lte-ie-7.css 也会被加载。 在 IE6 中,将加载所有三个附加样式表。

如果你想使用这种技术在特定版本的 Internet Explorer 中为元素设置不同的样式,它看起来像这样:

/* 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; }

优点

  • 条件注释片段是有效的 HTML。
  • 由于不需要使用 CSS hack,如果愿意,我们甚至可以编写有效的 CSS。

缺点

  • 由于多个额外的 HTTP 请求,性能会降低,具体取决于浏览器。
  • 条件注释会阻止 IE 中的下载,除非另一个(可能是空的)条件注释较早地包含在源代码中。
  • 总文件大小增加了,因为必须为每个 HTML 单个文档重复条件注释,并且您必须在每个 CSS 文件中重复选择器。 更多打字工作!
  • 可维护性受到负面影响。 我们现在必须维护四个独立的样式表,而不是一个。 每当我们对主 CSS 文件进行更改时,我们需要记住在必要时更改 IE 特定的 CSS 文件。

条件类名

那些不愿意使用 CSS hack 的人总是可以将条件类名应用于 <html><body> 元素。 这种方法允许我们以向 HTML 添加 hack 条件注释为代价编写干净且无 hack 的 CSS。

<!--[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]-->

这允许我们将特定于浏览器的 CSS 保存在同一个文件中:

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

优点

  • 条件类片段是有效的 HTML。 (在 HTML5 之前,我们必须将类添加到 <body> 元素中。)
  • 由于不需要使用 CSS hack,如果愿意,我们甚至可以编写有效的 CSS。
  • 没有发出额外的 HTTP 请求来获取 IE 特定的样式。
  • 在这种特殊情况下,条件注释不会阻止下载。

缺点

  • 此技术会增加我们使用它的每个 HTML 文档的文件大小。
  • 使用特定于 IE 的类名会自动增加选择器的特异性,这可能不是我们想要的。
  • 由于我们需要选择器中的类名,因此我们必须为 IE 特定样式使用单独的 CSS 规则。
  • 字符编码声明(例如 <meta charset="utf-8">)应该放在 HTML 文档的前 1024 个字节内。 使用这种技术,我们可能会越过此限制,特别是如果我们向 <html> 元素添加许多其他属性(因为我们必须在每个条件注释中重复它们)。
  • 在开始的 <html> 标签周围使用条件注释会使 IE 进入兼容性视图,除非我们在服务器端配置中设置 X-UA-Compatible 标头。
  • Simon Pieters 报告说,在 <meta http-equiv="X-UA-Compatible"> 之前使用条件注释会导致 IE 忽略 <meta>。 同样,我们需要在服务器端配置中设置 X-UA-Compatible 标头。

CSS hacks

Paul Irish 为各种浏览器维护了一个完整的 CSS hack 列表。 实际上,我们很少需要专门针对 IE 之外的任何目标。 以下是三个最流行的 CSS hack 以及它们应该针对哪些浏览器的概述:

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

注意 \9 CSS hack 的使用。 Web 开发人员注意到它可以用于轻松地针对 IE8 和更早版本,所以他们就这样做了。 但是后来出现了 IE9,事实证明,最终的 IE9 版本仍然受到这次黑客攻击的影响。 所有那些原本只适用于 IE8 和更早版本的 CSS 声明,现在也被 IE9 解释了。 不用说,东西坏了,因为 IE9 不需要大多数 IE8 特定的 CSS 修复。

这是不安全 CSS hack 的完美示例。

安全的 CSS 技巧

那么什么构成了“安全”的 CSS hack? 是什么让我甚至认为有这样的事情?

让我们面对现实吧——CSS 黑客仍然是黑客。 无法准确预测未来的浏览器版本将如何解析这些规则。 但我们可以做出有根据的猜测——有些 hack 比其他 hack 更简单。 安全的 CSS hack 是一种 CSS hack:

  • 适用于给定网络浏览器的特定版本;
  • 不太可能被所有其他浏览器解析,包括未来的版本。

_property: value hack 为例。 CSS 2.1 规范说明如下:

-_ 开头的关键字和属性名称保留用于特定于供应商的扩展。

属性名称是一个标识符。

在 CSS 中,标识符(包括元素名称、类和选择器中的 ID)只能包含字符 [a-zA-Z0-9] 和 ISO 10646 字符 U+00A0 及更高版本,加上连字符 (-) 和下划线 ( _); 它们不能以一个数字、两个连字符或一个连字符后跟一个数字开头。

那么谁能说永远不会有以下划线字符开头的属性名称呢? 引用 CSS3 规范:

尽管 [下划线] 是一个有效的起始字符,但 CSS 工作组认为它永远不会定义任何以该字符开头的标识符。

_property: value*property: value hacks(如上面的代码块所示)都是安全 CSS hacks 的例子。 它们被发现,被识别为错误,并在浏览器更新中进行了修补。 从那时起,微软和其他浏览器供应商很可能在他们的布局测试中添加了对这些 CSS hack 的检查,以确保新的浏览器版本不会出现如此严重的回归。

如果我们在某个浏览器的最新版本中发现了 CSS hack,那么在发布该浏览器的更新版本并修复解析器错误之前,它不会是安全的 hack。 例如,有些人(包括我自己)一直在寻找特定于 IE9 的 CSS hack。 最近发现了一个,但我们至少要等到 IE10 的最终版本才能使用它,因为 IE10 可能会或可能不会附带相同的 CSS 解析器错误。 我们不能冒险重复 \9 hack 的历史。

优点

  • 我们不必向每个 HTML 页面添加条件注释。
  • 没有发出额外的 HTTP 请求来获取 IE 特定的样式。
  • 你的 CSS 选择器的特殊性被保留了下来。
  • 无需重复 CSS 规则——我们只需在声明块中添加额外的声明(使用技巧)即可。

缺点

  • 他们被称为 CSS hacks 是有原因的——只使用安全的 CSS hacks。
  • 没有针对 IE8 的安全 CSS hack(还没有?)。
  • 与条件注释相反,大多数 CSS hack 不验证。 但话又说回来,CSS3 属性和供应商前缀属性也不验证。

将条件类名与安全的 CSS 技巧相结合

安全的 CSS hack 比条件样式表或类名更可取,但是如果我们必须编写 IE9 特定的样式怎么办? 根据定义,至少在 IE10 发布之前,不会有针对 IE9 的安全 CSS hack。 另外,IE8呢? 没有针对 IE8 而不是 IE9 的安全 CSS hack(据我所知)。 该怎么办?

在 HTML 中,我们可以使用条件类名技术的最小版本,如下所示:

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

然后我们可以使用 .lte-ie8 作为 CSS 选择器中的样式挂钩,以针对 IE8 和旧版本。 结合安全的 CSS hacks,我们最终可以在不影响 IE9 的情况下针对 IE8 和更早的版本:

.foo {
	color: black;
}

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

这种技术结合了安全 CSS hack 和条件类名的所有优点,同时最大限度地减少了缺点。

相关文章:

  • 通信原理与MATLAB(九):DPSK的调制解调
  • Docker安装配置运行Redis
  • 2022 年上海市大学生程序设计竞赛 M. My University Is Better Than Yours
  • 数据结构(陈越、何钦铭)学习笔记
  • pytorch集锦(2)-处理数据DataLoader和Dataset(2)
  • Ant Design入门
  • 网络请求回调的实现方式
  • STM32 使用IQmath实现SVPWM 正弦波无刷电机控制
  • Openstack的安装部署教程
  • 密码学_AES加密算法
  • 个人博客系统(前后端分离)
  • Linux常用基本指令详解
  • Linux c编程之静态库与动态库
  • 【消息中间件】RocketMQ如何实现Producer的负载均衡
  • 阳了在家没事干?教大家用python在家做一个万能看视频软件,绝对正经啦~
  • 2019年如何成为全栈工程师?
  • dva中组件的懒加载
  • Hibernate【inverse和cascade属性】知识要点
  • HTTP 简介
  • JavaScript创建对象的四种方式
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • webgl (原生)基础入门指南【一】
  • webpack入门学习手记(二)
  • 用Visual Studio开发以太坊智能合约
  • ​​​【收录 Hello 算法】9.4 小结
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • #NOIP 2014# day.2 T2 寻找道路
  • $.ajax()
  • (04)odoo视图操作
  • (bean配置类的注解开发)学习Spring的第十三天
  • (C语言)球球大作战
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (汇总)os模块以及shutil模块对文件的操作
  • (篇九)MySQL常用内置函数
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (三)Kafka 监控之 Streams 监控(Streams Monitoring)和其他
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (一) springboot详细介绍
  • (转)ORM
  • .NET 5种线程安全集合
  • .NET C# 操作Neo4j图数据库
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .NET 读取 JSON格式的数据
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .netcore如何运行环境安装到Linux服务器
  • .net流程开发平台的一些难点(1)
  • .NET运行机制
  • .Net中的集合
  • .net中我喜欢的两种验证码
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • @基于大模型的旅游路线推荐方案
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku
  • [acwing周赛复盘] 第 69 场周赛20220917