侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

CSS样式表渐进增强的应用

前端  /  管理员 发布于 7年前   237


有多种方式可以将渐进增强融入到层叠样式表(Cascading Style Sheets, 简称CSS)的工作中,本文将讨论其中比较成功的一些,并考虑采用其它方式来逐步增强你的站点。
原文:Progressive Enhancement with CSS
作者: Aaron Gustafson

有多种方式可以将渐进增强融入到层叠样式表(Cascading Style Sheets, 简称CSS)的工作中,本文将讨论其中比较成功的一些,并考虑采用其它方式来逐步增强你的站点。样式表的组织
如何在文档中引入样式表,很多Web设计者和开发者并没有想太多,但这其实是一门艺术。使用正确的方法,可以立即获得渐进增强的很多好处。使用多个样式表
对样式进行稍许拆分可以带来很多好处。显而易见,超过1500行的样式表是有点难以维护的,将其拆分成多个样式表,可以改进工作流程(并节省你的精力)。还有一个好处很少提及:有助于在目标媒介类型(译注:指计算机、打印机、电视、手机等各种媒介类型)上获取更一致的呈现效果。
main.css文件包含了站点的所有样式规则,考虑将其拆分成包含版式、布局和颜色的独立样式表,相应地命名为:type.css, layout.css, color.css.

(图示:如何将单个样式表拆分成多个相关的样式表)
一旦完成了上面的分离,就可以使用一点神奇的小手段来给过时的浏览器(比如IE5/Mac)和很多对CSS布局缺乏有力支持的浏览器自动提供“低保真”的体验。怎么做呢?这完全取决你如何引入文件。假设通过link元素来引入main.css:
<link rel="stylesheet" type="text/css" href="main.css" />
首先,将上面一行引用拆分成三个相关的样式表:
<link rel="stylesheet" type="text/css" href="type.css" /> <link rel="stylesheet" type="text/css" href="layout.css" /> <link rel="stylesheet" type="text/css" href="color.css" />
在过去,很多开发者将media的值设为”screen”或”projection”, 以使得布局样式在Netscape 4.x上彻底失效(译注:Netscape 4.x不支持浮动和定位等复杂布局)。然而,有更好的解决方法。在详细讲解这个方法前,我们先来看看可选媒介类型(Alternate Media Types)。可选媒介类型
渐进增强主要关注内容,我们要将“增强”的体验带到所有支持内容显示的设备上。因此需要考虑浏览器之外的设备,比如打印和移动设备就很重要。
糟糕地是,移动设备市场依旧四分五裂而且不成熟(不要天真地认为所有手持浏览器都会渲染目标为“screen”的媒介类型样式)。结果,用渐进增强的方式来处理所有媒介的细节讨论,如果不写成一本书的话,也得用上好多篇幅。然而请别沮丧:在移动世界里,差异正开始统一起来,并且一些非常聪明的人正开始将资源放在一起以帮助我们开发。不过,为了节约时间和节省精力,我们将集中于打印设备上。
通常,我们需要使用另一个link元素来添加打印样式:
<link rel="stylesheet" type="text/css" media="print" href="print.css" />
按照惯例,上面这个样式表包含所有打印相关的规则,包括版式和颜色规则。特别是版式,样式表中的规则大部分很可能拷贝自main.css. 也就是说,这造成了很多重复代码。
可以看出从布局样式中拆分出版式和颜色样式的好处了:在打印样式表中,我们不再需要那些重复的规则了。除此之外,可以使用另一个组织上的小技巧来改进站点的适用性,以及针对有问题的浏览器隐藏某些布局样式。
回顾下我们的样式表,考虑以下代码:
<link rel="stylesheet" type="text/css" href="type.css" /> <link rel="stylesheet" type="text/css" href="layout.css" /> <link rel="stylesheet" type="text/css" href="color.css" />
我们没有声明媒介类型,因此 Netscape 4.x 会读取这三个文件中的所有样式。但是,Netscape浏览器能理解最基本的CSS, 我们可以利用这一点。通过将layout.css包含的所有样式移动到新的样式表——适当的取名为screen.css, 我们可以进一步组织样式。最后,将layout.css中的内容更新为引入screen.css, 这样,NS4.x和它的同族浏览器们就再也聪明不起来了(因为它们不理解 @import指令)。(译注:作者这里说的是将所有layout.css中的内容都移动到screen.css中,然后在layout.css中通过@import引入screen.css. 我觉得最好的做法应该是在layout.css中保留最基本的NS4.x也可以理解的布局样式,而将其它高级布局样式移动到screen.css中。)
@import 'screen.css';
还有一些改进的余地——应该声明样式表所针对的媒介,我们通过给@import声明添加媒介类型来做到这点:
@import 'screen.css' screen;
问题是IE7及以下浏览器不理解这种语法从而忽略上面的样式表,如果想给这些浏览器提供上面的样式(这是经常期望的),可以很简单地使用条件注释来做到,这将在下文阐述。如果你拥有鹰一般利锐的眼睛,可能已经注意到在样式表名称的两边使用了单引号(’)来替代双引号(”),这个小技巧可以让 IE5/Mac忽略样式表。IE5/Mac的CSS布局能力非常弱(特别是对浮动和定位的支持),对它们隐藏布局规则是完全可接受的。毕竟,它们依旧能获取颜色和版式信息,这在某些情况下已经够用了。
采用相同的技术,可以导入print.css文件(和你猜想的一样,包含打印布局的特定规则)。
@import 'screen.css' screen; @import 'print.css' print;
现在我们不仅拥有了组织得很漂亮的样式表,我们还拥有了一套逐步增强站点设计的有效方法。

(图示:多个样式表间的相互关系以及将它们应用到文档的方法)现在讨论值一千万美元的问题:如何处理IE6?
对很多伙计来说,Internet Explorer 6 是一个新的 Netscape 4 ——所有人都想让它滚蛋。
我们略过对IE6问题的喋喋不休。IE6的问题已经有了很好的文档总结,并且,老实说,解决起来也并不是那么困难。而且,IE7的采纳相当快速(特别是在消费市场),同时IE8也已经在公测了。这意味着某一天,我们可以真正地对老态龙钟的IE6说拜拜。
不管是有意还是无意,微软在推出IE5时,为渐进增强提供了一个好工具:条件注释。这些巧妙的逻辑片段(在所有其它浏览器中都降级为HTML注释(译注:其它浏览器把IE的条件注释理解为纯粹的HTML注释,不起任何作用))不仅允许某些标记代码片段只作用于IE,还允许这些代码片段只作用于IE的特定版本。
作为有Web标准意识的开发者,我们始终应该首先在大部分现有的兼容标准的浏览器上测试我们的设计,然后再为那些稍作细微修改就能回到正轨的浏览器提供补丁。每个人的工作流程都不同,但我发现最好用一套标准的文件来开始每个项目。我的基本套件包括以下文件: type.css layout.css screen.css print.css color.css
然后,根据项目的需求,添加针对特定浏览器的CSS文件来包含那些“细微修改”。在现在的大部分项目中,这些文件是ie7.css和ie6.css. 如果项目要求支持IE6之前的版本,我也会为其创建相应的文件(比如ie5.5.css等等)。将这些文件放在恰当的位置后,我开始将样式规则添加到合适的样式表中。
我的CSS测试都是从Mozilla Firefox中开始,因为我的大部分CSS都是用Firefox的CSS编辑侧栏来编写的。一旦在Firefox中完成了页面设计,我立刻开启其它浏览器来测试查看。大部分表现很完美,因为他们遵守了Web标准。接着打开IE7来测试。大部分情况下也没多少问题,偶尔需要触发hasLayout或者修正另一些布局上的小错误。我没有将这些修正补丁写入到基本套件的样式表文件中,而是添加到ie7.css中,并且在文档的HEAD中通过条件注释来引入:
<!-- [if lte IE 7]> <link rel="stylesheet" type="text/css" href="ie7.css" /> <[endif]-->
上面的条件注释使得IE7及其以下版本(译注:lte是less than or equal的缩写)能识别引入的样式。因此,当用IE7浏览页面时,将获取这些补丁。但是如果用的是新版本的IE——可能已经修复这些问题,比如IE8抛弃了hasLayout从而不再有这些问题——将忽略这些样式。另一方面,使用IE6可以获取到这些样式。这是很好的,因为在IE7中的渲染错误往往也存在于IE6中。上文中已经提及,IE7及其以下版本无法理解带媒介类型的@import,通过这种方式引入screen.css对IE7及其以下版本是无效的。因此,还需要在ie7.css文件的顶部添加不带媒介类型的@import语句来引入screen.css.
一旦为IE7添加完补丁,我会打开IE6, 看看是否需要随手打些补丁。如果确实需要,我会给文档添加另一个条件注释,引入ie6.css:
<!-- [if lte IE 7]> <link rel="stylesheet" type="text/css" href="ie7.css" /> <[endif]--> <!-- [if lte IE 6]> <link rel="stylesheet" type="text/css" href="ie6.css" /> <[endif]-->
接着,简单地将IE6需要的补丁添加到对应的样式表中,这些样式表将被IE7忽略,但是会依旧往下影响到IE5.5等版本。
通过这种方式使用条件注释,可以很轻松的管理项目中的目标浏览器,并使得CSS补丁文件保持独立自由。其它考虑
CSS渐进增强并不局限于如何将样式表与文档关联起来,还可以应用在如何编写CSS上。
例如,考虑生成的内容(译注:比如用:after伪类生成的内容)。并非所有浏览器都支持,但这是一个很好的方法:可以用来添加一些额外的设计或文本。对于页面的可用性来说,这不是必须的,但这能提供一些视觉或其它方面上的增强。
拿简单的联系表单来举个例子:

(图示:此例中使用的HTML表单(代码将在下面给出))
当编写上面的HTML代码时,很可能会自然地将冒号(:)写在label元素里。为什么要这样做?真的给label元素添加了内容吗?并没有。这样做的目的是给用户提供额外的视觉线索,对label元素来说,这是多余的,应当去掉:
<form id="contact-form" action="#" method="post"> <fieldset> <legend>Contact Us</legend> <p>Send us a message. All fields are required.</p> <ol> <li> <label for="contact-name">Name</label> <input type="text" id="contact-name" name="name" /> </li> <li> <label for="contact-email">Email</label> <input type="text" id="contact-email" name="email" /> </li> <li> <label for="contact-message">Message</label> <textarea id="contact-message" name="message" rows="4" » cols="30"></textarea> </li> </ol> <button type="submit">Send It</button> </fieldset> </form>
通过生成内容来将冒号添加回文档,这是一种更完美合适的方式:
label:after { content: ":"; }
用这种方式来编写表单,给了我们灵活性:当需要从整个站点移除装饰字符时,只要简单的编辑CSS文件,而不需要去寻找每一个表单(虽然我们曾经知道在哪)。这个技巧也能够很好降级,因为没有冒号时,表单并不会被渲染得无法使用——这是渐进增强的一个绝佳例子。
也许你已经发现,使用高级CSS选择符(译注:selector, 也有译为选择器的,但我觉得选择符更能体现本意,比如operator翻译成运算符,而不是运算器),可以将特定的样式附加到更多高级浏览器上,这有助于逐步增强站点。一个很好的例子是属性选择符,在IE6及其同一时代以及更早的浏览器中不能被理解(因此也就被忽略了)。Egor Kloos很漂亮地运用了这个概念,在CSS禅意花园(CSS Zen Garden)上提交了名为”双双”(Gemination)的作品:

(图示:Egor Kloos的CSS禅意花园作品(“双双”)在标准浏览器和IE6中的呈现对比)
他是怎样做到的?下面是略加修改的示例代码:
body { margin: 0; text-align: center; background: #600 none; } body[id=css-zen-garden] { margin: 100px 0 0; padding: 0; text-align: center; background: transparent url(squidback.gif); }
差异很明显,并且非常漂亮地说明了渐进增强如何应用在CSS中。
类似地,Andy Clarke的站点上也有些关于IE6的小玩意。通过使用IE的滤镜以及加入一些条件注释,Andy成功地去除了站点上的所有颜色,并提供了一些可替换的图片,这构成了一个真实的“低保真”体验。

(图示:Andy Clark的站点在标准浏览器和IE6上的对比)
上面的图片灰色技术是这样的:在条件注释添加的针对IE6(及其以下)的样式表中,添加以下声明:
img { filter: gray; }
尽管上面这两个例子可能包含了过多日常工作中的运用不到的技巧,但它们非常棒地用事实说明了一个概念:如何在实践中应用CSS渐进增强。总结
正如我们讨论过的,有多种方式可以将CSS渐进增强应用到站点上。最简单也可能是最好的一种方式是,组织好样式表并认真考虑如何将样式表链入文档。一旦理解了条件注释,处理IE的特定问题也将是轻而易举的事。如果对如何选用选择符以及使用它们的场景了然于胸,还能在CSS中完成更多小粒度的调整。


  • 上一条:
    CSS实例:vertical-align属性让网页层居中
    下一条:
    基于CSS的网站导航菜单
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客