CSS权威指南(第四版)第一章(中文翻译)

持续修正版请参见这里:githubcss

CSS和文档

Cascading Style Sheets (CSS) 是一个可以改造文档和文档集合呈现的强大工具,它已经扩展到web的几乎每一个角落以及许多看起来是非web的环境。例如,基于Gecko1的浏览器经过CSS影响Chrome浏览器的呈现,以及一些即时通信客户端(如Adium)使用CSS来格式化聊天窗口。JavaScript框架(如jQuery)所使用的语法中能够找到CSS的面孔。它无处不在!html

Web样式历史简介

CSS于1994年首次被提出,正当Web开始真正流行的时候。事实上,最终成为CSS(被命名为Cascading HTML Style Sheets)的第一个草案发表于Mozilla(其后成为Netscape Navigator)初版被公布的仅仅几天前。git

当时,浏览器赋予用户各类样式化能力——例如,在Mosaic2的显示偏好中,容许用户基于每一个元素定义全部风格的字体系列、尺寸和颜色。而文档开发者却没法作到这些,他们所能作的只是把一段内容标记为段落、做为某级标题、做为预约义格式的文本或者其它不多量的元素类型中的一个。若是用户配置本身的浏览器,把全部一级标题设置成“微小”和粉色,而把六级标题设置为“巨大”和红色,那浏览器就会如用户所设置的显示。github

CSS就是在这种背景下引入的。它的目标很简单:提供一种简单的、声明式的样式语言供文档开发者灵活地使用,更重要的是,为开发者和用户提供一样的样式化能力。经过“层叠(cascade)”的手段,这些样式能够组合并按优先级排序,让开发者和阅读者都有对样式的控制权——尽管阅读者老是有最终的控制权。web

工做迅速推动,到1996年年末,CSS1完成了。新成立的CSS工做组继续向前推动CSS2,浏览器们则在尽力以相互兼容的方式实现CSS1。尽管每一个单独的CSS片断都是至关简单的,但它们的组合却产生了使人意外的复杂行为。早期的实现还存在一些不幸的失误,好比今天已经臭名昭著的框模型实现的差别。这些问题使CSS面临被彻底破坏的威胁,但幸运的是一些聪明的提案被实现了,浏览器们也开始协调起来了。几年内,得益于持续增长的互通性和高关注度的开发者(如基于CSS从新设计的《连线(Wired)》杂志和CSS禅意花园(Zen Garden)),CSS开始真正流行起来。chrome

在这一切发生以前,CSS工做组已经在1998年初完成了至关重的CSS2规范。CSS2一完成,CSS3(以及一个CSS2的清晰化版本:CSS2.1)的工做就当即开始了。与时俱进的CSS3被构造为一系列(理论上的)独立模块,而不是单个的总体规范。这种作法体现了当时活跃的XHML规范的影响,它(XHML)也由于相似的缘由被拆分红模块。浏览器

把CSS3模块化的理由是,每一个模块能够按照本身的步调发展,特别关键(或流行)的模块能够随着W3C的路线先行推动,而没必要被其它模块拖延。事实也正是这样。到2012年初,3个CSS3模块(与CSS1和CSS 2.1一块儿)实现了完整推荐3状态——CSS Color Level 三、CSS Namespaces和Selectors Level 3。与此同时,七个模块正处于候选推荐4状态,其它几十个模块处在工做草案的不一样阶段。按照之前的作法,颜色、选择器和命名空间三个模块将不得不等待规范中的全部其它模块都被完成或取消,才能做为完整规范的一部分被提案。得益于模块化,它们不须要等待规范的其它部分了。缓存

模块化好处的另外一面是,很难说一个单一的“CSS3规范”。事实上没有也不会有这样一个东西。即使其它每一个CSS3模块都完成了——假如,在2014年末——可能那时已经有一个Selectors Level 4正在推动中甚至已经要完成了,咱们应该把它叫作CSS4吗?若是这样的话,其它尚在使用中的CSS3特性算什么呢?服务器

因此,虽然咱们不能指着一个大部头说:“这就是CSS3”,但咱们能够对每一个模块名称及它们所指代的功能特性进行讨论。模块灵活性上的好处远远大于它们引入的语义上尴尬的坏处。app

元素

元素是文档结构的基础。在HTML中,最多见的元素很容易识别,例如ptablespanadiv。每一个元素都在文档展现展现中扮演各自的角色。

替换元素和非替换元素

虽然CSS依赖于元素,但并不是全部的元素都同样。例如,图片和段落就不是同类型的元素,spandiv也不是。在CSS中,元素一般有两种形式:替换的和非替换的。

替换元素

替换元素是指那些内容会被其它东西所替换的元素,这些东西并不直接体如今文档内容里。在HTML中最为人所熟悉的例子大概就是img元素了,它会被存储在文档外部的一个图片文件所替代。事实上,img元素没有实在的内容,正以下面的简单示例中所展现的:

<img src="howdy.gif" >

这个代码片断只包含元素名称和属性。 除非你把它指向外部内容(这里是由src属性指定的图片),这个元素不会显示任何内容。 若是把它指向有效的图片文件,则图片将被放置在文档中。反之,它将不显示任何内容或者浏览器将在这里放置一个“损坏图像”的占位符。

相似地,input元素也会被替换为单选按钮、复选框或文本输入框 —— 这取决与input元素的type属性。

非替换元素

大部分HTML元素是非替换元素。这意味着元素的内容会被用户代理(一般是浏览器)显示在一个由元素本身生成的“盒子”里。例如,<span>hi there</span>是一个非替换元素,文字“hi there”会由用户代理显示。对于段落、标题、表格单元格、列表以及HTML中的其余大部分元素都是如此。

元素显示角色

除了替换和费替换元素,CSS2.1还使用另外两种基本类型来区分元素:块级(block-level)行内级(inline-level)。曾经花费时间在HTML标签和它们在web浏览器中显示上的开发者,会对这两个类型更加熟悉。元素在图1中展现。

图1:HTML文档中的块级和行内元素

图1:HTML文档中的块级和行内元素

块级元素

块级元素生成一个(默认状况下)填充其父元素的内容区域的元素框,而且在其两侧不能有其余元素。 换句话说,它在元素框以前和以后生成“断行”。 HTML中最多见的块元素是pdiv。 替换元素能够是块级元素,但一般它们不是。

列表项是一种特别的块级元素。 除了与其余块级元素一致的行为以外,它们还生成一个标记(一般是用于无序列表的项目符号和用于有序列表的数字)并“附加到”元素框。 除了这个标记,列表项与其余块级元素的行为彻底相同。

行内元素

行内元素在文本行内生成一个元素框,而且不会破坏该行的流。HTML中行内元素的最好例子是a元素,其它还有strongem。这些元素不会在自身以前或以后生成“断行”,因此它们能够出如今其它元素的内容之中,而且不会破坏其显示。

须要注意,虽然名称“块级”和“行内”与HTML中的块和行内元素有不少共同之处,但还有个重要区别:在HTML中,块级元素不能做为行内元素的后代;但在CSS中,对显示角色之间的嵌套没有限制。

要了解其工做原理,咱们来考虑一个CSS属性display

取值:

none | inline | block | inline-block | list-item | run-in | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table- column-group | table-column | table-cell | table-caption | inherit

初始值:

inline

适用元素:

全部元素

继承:

计算值:

因浮动,定位和根元素而异(参见CSS2.1,第9.7节); 其它状况按规范取值

你可能已经注意到了这里有许多取值,只有其中三个是我提到过的:blockinlinelist-item

如今咱们把注意力放在blockinline上,看下面的代码:

<body>
    <p>This is a paragraph with <em>an inline element</em> within > it.</p> 
</body>

这里有两个块级元素(bodyp)和一个行内元素(em)。根据HTML规范,em能够做为p的后代,但反过来则不行。一般HTML的层级结构容许行内元素做为块级元素的后代,而不是相反。

另外一方面,CSS则没有这样的限制。你能够保持现有的标签结构,而后像这样修改这两个元素的显示角色:

p {display: inline;}
em {display: block;}

这使得元素在一个行内框里面生成了一个块级框,这在CSS中是彻底合法的,不会破坏任何规范。可是,若是你想在HTML中使用相反的嵌套结构,那就有会问题了,像这样:

<em><p>This is a paragraph improperly enclosed by an inline element.</p></em>

无论你如何使用CSS来修改它们的显示角色,这在HTML中都是不合法的。

修改元素的显示角色在HTML文档中颇有用,它对XML文档也相当重要。XML文档通常没有默认的显示角色,而彻底依赖文档开发者去定义它们。例如,若是你想要展现下面的XML片断:

<book>
    <maintitle>Cascading Style Sheets: The Definitive Guide</maintitle>  
    <subtitle>Third Edition</subtitle>  
    <author>Eric A. Meyer</author>  
    <publisher>O'Reilly and Associates</publisher>  
    <pubdate>November 2006</pubdate>  
    <isbn type="print">978-0-596-52733-4</isbn>  
</book>  
<book>  
    <maintitle>CSS Pocket Reference</maintitle>   
    <subtitle>Third Edition</subtitle>  
    <author>Eric A. Meyer</author>  
    <publisher>O'Reilly and Associates</publisher>  
    <pubdate>October 2007</pubdate>  
    <isbn type="print">978-0-596-51505-8</isbn>  
</book>

由于display属性的默认值是inline,因此这块内容会默认被显示为行内文本,就像图2所示的那样。这样的排版不太有用。

图2:一个XML文档的默认显示

图2:一个XML文档的默认显示

你能够用display来定义文档的基本板式:

book, maintitle, subtitle, author, isbn {display: block;} 
publisher, pubdate {display: inline;}

这样把7种元素中的5个设置成块级元素,2个设置成行内元素。块级元素会被像HTML中的div那样处理,两个行内元素会被相似span那样处理。

由于这种设置显示角色的基本能力,CSS在各类场景下都很是有用。你能够从上面的规则开始,添加一些更具视觉效果的样式,而后获得像图3这样的显示效果。

图3:添加了样式的XML文档

图3:添加了样式的XML文档

在详细学习如何编写CSS以前,咱们先要看一下如何关联CSS和文档,毕竟,若是不把它们结合在一块儿,CSS是没法对文档起做用的。咱们从最熟悉的HTML设置开始。

结合CSS和HTML

我提到过HTML文档存在一个固有结构,这一点值得重复一下。事实上这是旧网页问题的一部分:咱们太多人忘记了文档是应该有一个内在结构的,这与一个视觉上的结构是彻底不一样的。咱们急于在Web上建立看起来最酷的网页,咱们改造转换、修饰装点,全然忽视了页面应该包含具备一些结构意义的信息。

这种结构是HTML和CSS之间关系所固有的组成部分,没有它,关系就不会存在。为了更好地理解这种结构,咱们把下面这个示例的HTML文档拆解来看:

<html>
  <head>
    <title>Eric's World of Waffles</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <link rel="stylesheet" type="text/css" href="sheet1.css" media="all"> 
    <style type="text/css">
      /* These are my styles! Yay! */
      @import url(sheet2.css);
    </style>
  </head>
  <body>
    <h1>Waffles!</h1>
    <p style="color: gray;">The most wonderful of all breakfast 
    foods is the waffle—a ridged and cratered slab of home-cooked, 
    fluffy goodness that makes every child's heart soar with joy. 
    And they're so easy to make! Just a simple waffle-maker and some 
    batter, and you're ready for a morning of aromatic ecstasy!
    </p>
  </body>
</html>

代码的处理结果及应用的样式的如图四所示。

图片4:一个简单文档

图片4:一个简单文档

如今咱们来看文档关联CSS的几种方式。

link标签

首先是link标签的使用:

<link rel="stylesheet" type="text/css" href="sheet1.css" media="all">

link标签是一个有些被忽视的标签,但它是在HTML规范中存在了许多年的合法标签,一直在等着被善加利用。它最初的目的是容许HTML开发者把包含连接标签的文档与其余文档关联起来。CSS使用Link标签把样式表连接到文档中,如图5,一个名为sheet1.css的样式表被链接到文档。

图片5:展现外部样式表如何被应用到文档

图片5:展现外部样式表如何被应用到文档

这些样式表不是HTML文档的一部分但仍被应用于文档中,它们被称为外部样式表,由于它们存在于HTML文档的外部(看图)。

连接必须放置在head元素内,外部样式才能成功加载,与title不一样,它不能被放置在任何其它元素里。像图5所示的那样,web浏览器会定位并加载样式表,而后把样式表中的任何样式都应用在HTML文档渲染中。图5中还展现了使用@import声明加载的外部样式sheet2.css@import必须在包含它的样式表的开头5,除此以外没有其它限制。

那么外部样式表是什么样的格式呢?和咱们在前面章节中和在示例HTML文档中看到的那些样式同样,外部样式也是简单的规则列表,可是这些规则存储在本身的文件里面。要记住,HTML和其它任何标记语言都不能放进样式表中——它只能包含样式规则。一个外部样式表的内容是这样的:

h1 {color: red;}
h2 {color: maroon; background: white;} 
h3 {color: white; background: black; font: medium Helvetica;}

这就是它的所有内容——没有HTML标记或者注释,只有干净简单的样式声明。它们被存储在纯文本文件中,一般用.css做为后缀,例如sheet1.css

外部样式中不能包含任何文档标记,只能包含CSS规则和CSS注释,咱们将在后面的章节解释它们。外部样式表中的标记可能会致使其中的所有或部分样式被忽略。

文件扩展名不是必需的,但若是文件名不是以.css结尾,即便你在link元素中设置了正确的文件类型text/css,一些旧浏览器依然没法把文件识别为样式表。实际上,若是文件名不是以.css结尾,一些web服务器不会把文件当作text/css来处理,但一般这个问题能够经过修改服务器配置文件来解决。

属性

对于link标签的其它部分,属性和值都很直白。rel表示“关系”(relation),这里关系就是stylesheet(样式表)。type属性始终设置为text/css,这个值描述了被link标签加载的数据的类型。这样,web浏览器就能够知道这个样式表是一个CSS样式表,这决定着浏览器如何处理它引入的数据。毕竟,未来可能会用到其它样式语言,因此声明你所使用的是哪一种语言是有必要的。

接下来是href属性,这个属性的值是样式表的URL。这个URL能够是绝对或相对地址,这取决于你的须要。固然在咱们的示例中URL是相对的,显然它也能够是http://meyerweb.com/sheet1.css.这种形式。

最后是media属性,这个属性的值是一个或多个媒体描述符。媒体描述符是关于媒体类型和这些媒体的特性的规则,每一个规则之间用逗号分隔。例如,你在屏幕和投影媒体上均可以使用一个这样的连接样式表:

<link rel="stylesheet" type="text/css" href="visual-sheet.css" media="screen, projection">

媒体描述符能够设置得很是复杂,咱们将会在本章中稍后的部分作详细解释。如今咱们只使用基本的媒体类型。

注意,一个文档能够关联多个样式表。这时,只有那些包含rel属性值为stylesheet 的样式表会被用于文档的初始显示。所以,若是你想分别连接两个名为basic.csssplash.css的样式表,看起来会像这样:

<link rel="stylesheet" type="text/css" href="basic.css"> 
<link rel="stylesheet" type="text/css" href="splash.css">

这种写法会使浏览器加载两个样式表,并合并每一个样式表的规则,而后把它们所有应用于文档。例如

<link rel="stylesheet" type="text/css" href="basic.css"> 
<link rel="stylesheet" type="text/css" href="splash.css">
<p class="a1">This paragraph will be gray only if styles from the stylesheet 'basic.css' are applied.</p>
<p class="b1">This paragraph will be gray only if styles from the stylesheet 'splash.css' are applied.</p>

有一个能够可是并无在示例代码中出现的属性title。这个属性并不经常使用,但它可能会在将来变得重要,若是使用不当会带来意想不到的效果。为何呢?咱们将在下一节中探讨。

备用样式表

能够定义备用样式表。它们是经过把rel属性的值设为alternate stylesheet来实现的,并且它们只有被用户选择的时候才会用于文档显示。

若是浏览器可以使用备用的样式表,它会用link元素的title属性值来生成一个可选择的样式列表。你能够像下面这样写:

<link rel="stylesheet" type="text/css" href="sheet1.css" title="Default">
<link rel="alternate stylesheet" type="text/css" href="bigtext.css" title="Big Text">
<link rel="alternate stylesheet" type="text/css" href="zany.css" title="Crazy colors!">

而后用户就能够选择他们想用的样式,浏览器将会从第一个(这里被标记为“默认”(Default))切换到用户选择的任意一个。图6展现了这种选择机制的一个可能的(其实是CSS再次兴起的早期所使用的)完成方式。

图6:一个支持选择备用样式的浏览器

图6:一个支持选择备用样式的浏览器

在2012年初,大部分基于Gecko引擎的浏览器已经支持了备用样式表,如Firefox和Opera。在Internet Explorer系列的浏览器中可使用JavaScript实现支持,可是没有被浏览器原生支持。Webkit系列浏览器不支持选择备用样式表。(相比之下,图6所示的这么老旧的浏览器都提供了支持,真是使人惊讶。)

经过给title属性赋相同的值,备用样式表能够分组组合。所以,你可让用户在不管屏幕媒体仍是打印媒体中都能选择不一样的展现方式。例如:

<link rel="stylesheet" type="text/css" href="sheet1.css" title="Default" media="screen">
<link rel="stylesheet" type="text/css" href="print-sheet1.css" title="Default" media="print">
<link rel="alternate stylesheet" type="text/css" href="bigtext.css" title="Big Text" media="screen">
<link rel="alternate stylesheet" type="text/css" href="print-bigtext.css" title="Big Text" media="print">

若是用户在支持备用样式表选择机制的用户代理中选择了“Big Text”,那么bigtext.css将在屏幕媒体中为文档设置样式,而print-bigtext.css将会被用在打印媒体上。sheet1.cssprint-sheet1.css不会被用在任何一个媒体中。

为何会这样?由于一旦你为一个rel属性值为styleshetlink标签设置了title,你就指派了这个样式表为优先样式表。这表示它会比备用样式表优先被使用,会被用在文档第一次显示的时候。可是,当你选择了一个备用样式表的时候,优先样式表就不会再被使用了。

此外,若是你把多个样式表都指派为优先使用,那么除了一个以外全部其它的样式表都会被忽略。考虑下:

<link rel="stylesheet" type="text/css" href="sheet1.css" title="Default Layout">
<link rel="stylesheet" type="text/css" href="sheet2.css" title="Default Text Sizes">
<link rel="stylesheet" type="text/css" href="sheet3.css" title="Default Colors">

因为都被设置了title属性,三个link元素都被指定为优先样式表,但只有一个会被真正被做为优先样式表,而另外两个会彻底被忽略。哪两个呢?没有办法肯定。由于HTML并无提供一种方式,来决定哪一个样式应该被忽略,哪一个样式应该被使用。

若是你根本不给样式表设置title,它将变成一个持久的样式表,并一直用在文档显示中。一般这正是开发者想要的。

style元素

一种包含样式表的方法是使用style元素,它像这样显示在文档中:

<style type="text/css">...</style>

style须要设置type属性,与link标签同样,使用CSS文档的时候type值应该设置为text/css

就像上面的示例所表示的,style元素老是以<style type="text/css">开始。后面紧接着是一个或多个样式,最后一一个关闭标签</style>做结束。style也能够指定一个media属性,它的做用与前面介绍的在连接样式表中的功能是同样的。

这种在style开始和结束标签之间的样式被称为文档样式表或者内嵌样式表(由于这种样式表是嵌入在文档里的)。内嵌样式表包含许多应用于文档的样式,也可使用@import指令连接至多个外部样式。

@import指令

如今咱们开始讨论style标签内部。首先是与link很是相似的@import指令:

@import url(sheet2.css);

link同样,@import能够指示浏览器加载一个外部样式而后把它应用到HTML文档渲染中。它们之间主要的区别只是在于语法和命令的位置。正如咱们看到的这样,@import是被包含在style中的。命令必须放在其余CSS规则以前,不然它不会生效。看这个例子:

<style type="text/css">
@import url(styles.css); /* @import comes first */ 
h1 {color: gray;}
</style>

link相同的是,一个文档中能够有多个@import声明。但与link不一样的是,@import指令中的每一个样式表都会被加载和使用,@import不能设置备选样式表。所以,若是使用下面的代码:

@import url(sheet2.css); 
@import url(blueworld.css); 
@import url(zany.css);

所有三个外部样式都会被加载,它们的样式规则也都会被用于文档显示中。

相似link,你能够在样式表的URL后添加媒体描述符,来限制样式表被用于一个或多个媒体:

@import url(sheet2.css) all;
@import url(blueworld.css) screen; 
@import url(zany.css) projection, print;

正如在link元素的章节中介绍的,媒体描述符可能会很是复杂,咱们将在后面的章节详细介绍。

若是你想要在一个外部样式表中使用另外一个外部样式表,@import很是有用。由于外部样式表不能包含任何文档标记,link元素就没法使用,但@import却能够。因此,一个外部样式表多是这样的:

@import url(http://example.org/library/layout.css); 
@import url(basic-text.css);
@import url(printer.css) print;
body {color: red;}
h1 {color: blue;}

这些不是真正使用的样式,可是你能够经过它们看到@import的用法。上例中同时使用了绝对和相对URL,像link同样,两种都URL格式均可以使用。

还要注意,正如咱们在示例文档中所作的,@import指令出如今样式表的开头。CSS要求@import指令出如今样式表的其它规则以前。出如今其它规则(例如:body {color: red;})以后的@import会被标准的用户代理所忽略。

在Windows系统上的旧版的Internet Explorer浏览器中,即便@import指令放在其余规则以后,也不会被忽略。但其余浏览器会忽略位置不正确的@import指令,这很容易致使放置不正确的@import引发其余浏览器的显示错误。

HTTP连接

把CSS关联到文档还有一种很是晦涩的方式:你能够经过HTTP标头把它们连接在一块儿。

在Apache环境下,能够在.htaccess文件中添加CSS的文件引用来完成关联,例如:

Header add Link "</ui/testing.css>;rel=stylesheet;type=text/css"

支持该特性的浏览器会将引用的样式表与任何该.htaccess文件配置下的文档相关联,浏览器会把它当作一个连接样式表。另外一个可能更有效的选择是,把相同的规则添加到服务器的httpd.conf文件中:

<Directory /path/to/ /public/html/directory>
Header add Link "</ui/testing.css>;rel=stylesheet;type=text/css" 
</Directory>

对支持该特性的浏览器来讲,这两种方式效果是同样的,惟一的区别是只是你在哪里声明连接而已。

你确定注意到了前面所使用的“支持该特性的浏览器”。至2012年初,被普遍使用的浏览器中支持HTTP连接样式表的有Firefox系列和Opera。这使得大部分状况下这项技术被限制在使用这些浏览器的开发环境中。在这些环境中,你能够在测试服务器上使用HTTP连接来标记测试环境网页,从而与发布的公共版网页区分开来。这项技术仍是一种有趣的用来对WebKit和Internet Explorer系列浏览器隐藏样式的方法——假如你基于某些缘由须要这么作的话。

等价的技术存在于通用脚本语言中,如PHP和IIS,这两种语言都容许开发者发出HTTP头。使用这些语言能够向服务器的文档中写入link元素。这种技术有浏览器的更好的支持:每一个浏览器都支持link元素。

行内样式

若是你只想简单地为一个单独元素设置一些样式,不须要使用内嵌或者外部样式表,使用HTML的style属性来设置行内样式便可:

<p style="color: gray;">The most wonderful of all breakfast foods is the waffle—a ridged and cratered slab of home-cooked, fluffy goodness... 
</p>

除了位置在body以外的标签(headtitle等),style属性能够设置在任何HTML标签上。

style属性的语法很普通,跟style元素里面的规则声明很像,只不过花括号被换为双引号。<p style="color: maroon; background: yellow;">会把当前段落的文本设置为栗色,把背景设置为黄色,文档的其它部分不会受到这些样式声明的影响。

请注意,行内style属性只能放置样式规则声明块,而不是整个样式表。所以,style属性里既不能放置@import,也不能放进任何完整的样式规则,style属性的值只能被设置为样式规则花括号里面的那部分。

style属性一般不建议使用,实际上它也不大可能出如今HTML以外的XML语言中。当把样式放置在style属性中时,许多CSS的主要优点——例如将整个文档或服务器的全部文档的样式集中组织的能力——便没法有效发挥了。从许多方面来讲,使用行内样式并不比使用font标签好多少,尽管处理视觉效果的时候它确实(比font标签)更灵活。

媒体查询

经过媒体查询,开发者能够定义不一样媒体环境中浏览器可使用的样式表。过去,这是经过使用media属性来为link元素或style元素设置媒体类型,以及经过@import@media声明的媒体描述符来处理的。如今媒体查询使这个概念更进一步,容许开发者经过使用所谓的媒体描述符,基于给定媒体类型的特性来选择样式表。

使用

媒体查询可使用在如下位置:

  • link元素的media属性。
  • style元素的media属性。
  • @import声明的媒体描述符部分。
  • media声明的媒体描述符部分。

媒体查询能够是简单的媒体类型,也能够是媒体类型和特性的复杂组合。

媒体类型

媒体类型最基础的形式是媒体类型,首次出现于CSS2中。它们是表示不一样类型媒体的简单标签。它们是:

  • all

    用于全部演示媒体。

  • aural

    用于语音合成器、屏幕阅读器和文档的其它音频渲染媒体。

  • braille

    用于布莱叶盲文渲染文档。

  • embossed

    用于布莱叶盲文设备的打印。

  • handheld

    用于我的设备助理(PDA)或可以使用web的手机等手持设备。

  • print

    用于可视用户打印文档以及显示文档的打印预览。

  • projection

    用于投影媒体,例如演讲时用于展现幻灯片的数字投影仪。

  • screen

    用于在桌面电脑显示器等屏幕媒体中显示文档。在此类系统上运行的全部Web浏览器都是屏幕媒体用户代理。

  • tty

    用于固定间距显示环境(如电传打印机)中传送文档时使用。

  • tv

    用于电视机中显示文档。

这些媒体类型的大多数都不能被当前的web浏览器所支持。最被普遍支持的三个类型是allscreenprint。在撰写本文时6,一些浏览器还支持projection类型,容许把文档显示成幻灯片,一些移动设备浏览器支持handheld类型。

可以使用逗号分隔的列表指定多个媒体样式。下面的四个例子使用了相同的方式,把样式表(或样式规则代码块)应用于屏幕和投影媒体。

<link type="text/css" href="frobozz.css" media="screen, projection"> 
<style type="text/css" media="screen, projection">...</style>
@import url(frobozz.css) screen, projection;
@media screen, projection {...}

有趣的是当向这些媒体类型添加特性描述符(例如描述媒体分辨率和色深的值)时。

媒体描述符

link元素或者@import声明设置过媒体类型的开发者,将会对媒体查询(描述符)的位置很是熟悉。下面是在彩色打印机上渲染文档时应用外部样式表的两种基本等效的方法:

<link href="print-color.css" type="text/css" media="print and (color)" rel="stylesheet">
@import url(print-color.css) print and (color);

任何使用媒体类型的地方,均可以使用媒体查询(描述符)。这意味着对上面的例子,可使用逗号分隔能够列出多个查询:

<link href="print-color.css" type="text/css"
media="print and (color), projection and (color)" rel="stylesheet">
@import url(print-color.css) print and (color), projection and (color);

任何状况下,只要任何一个(逗号分隔的)媒体查询的判断结果为“真”,就会使用关联的样式表。所以,在前面的@import中,print-color.css将会被应用于彩色打印机或彩色投影环境的渲染。若是在黑白打印机上打印,两个查询的结果都是“假”,则print-color.css不会被应用于文档,对于任何屏幕媒体、灰阶(非彩色)投影环境、听觉媒体环境等都是如此。

每一个媒体描述符由一个媒体类型和一或多个媒体特性组成,每一个媒体特性描述符都被包括在括号中。若是没有指定媒体类型,它将被默认设置为all,所以下面两个示例是彻底等价的:

@media all and (min-resolution: 96dpi) {...}
@media (min-resolution: 960dpi) {...}

通常来讲,媒体特性描述符的格式相似于CSS中的属性-值对,但有一些区别。最明显的区别是能够指定一些没有值的特性,例如,使用(color)来匹配任何基于颜色的媒体,而使用(color: 16)来匹配16位色深的颜色媒体。实际上,不含值的描述符是一个对特性是否存在的一个真/假值判断:(color)表示判断“是不是颜色媒体?”。

多个特性描述符可使用逻辑关键字and连接,媒体查询里面有两个逻辑关键字:

  • and
    使用这种方式连接两个或多个媒体特性时,只有当每一个媒体特性都为真,总的查询结果才为真。例如,(color) and (orientation: landscape) and (min-device-width: 800px)表示三个条件必须都被知足:当媒体环境具备颜色、横向显示,并且设备的显示宽度至少为800像素时,样式表才会被使用。

  • not
    对整个查询求反,若是全部的条件都为真,样式表则不会被使用。例如,not (color) and (orientation: landscape) and (min- device-width: 800px)表示若是三个条件被知足,则表达式会被否认。所以,当媒体环境具备颜色、横向显示,而且设备显示宽度至少为800像素时,样式表不会被使用;反之在其它任何状况下,样式表都会被使用。 请注意,not关键字只能用在媒体查询的开头。(color) and not (min-device-width: 800px)这样的用法是不合法的,在这种状况下,查询会被忽略。一样须要注意的是,太旧的浏览器会由于没法理解媒体查询而老是跳过媒体描述符以not开头的样式表。

媒体查询中没有“或”关键字,但分隔查询列表的逗号能够起到“或”的做用——screen, print表示“若是媒体是屏幕或打印机,则应用样式”。设置screen and (max-color: 2) or (monochrome)将会被忽略,应该写成screen and (max-color: 2), screen and (monochrome)来代替。

另外还有一个关键字only,专门用于向后兼容。是的,你没看错。

  • only
    用于对没法理解媒体查询的旧浏览器隐藏样式表。例如,为了在全部媒体但仅在可以理解媒体查询的浏览器上应用样式表,写作@import url(new.css) only all。对于可以理解媒体查询的浏览器,only关键字会被忽略,样式表会被使用;对不能理解媒体查询的浏览器,only关键字会建立一个显式的媒体类型only all,而这是非法的,所以样式表不会应用于这样的浏览器中。要注意,only关键字只能用在媒体查询的开头。

媒体特性描述符

咱们已经在示例中见过了一些媒体特性描述符,如今咱们来看描述符和它们取值的完整列表。

请注意,下面的取值都不能为负数,并且特性描述符老是在括号内。

  • 描述符:width, min-width, max-width

    • 值:<长度>
      指用户代理的显示区域的宽度。在屏幕媒体的web浏览器中,指视口加上滚动条的宽度。在分页媒体中,指页框的宽度。所以,(min-width: 850px)表示当视口宽度大于850像素时有效。
  • 描述符:device-width, min-device-width, max-device-width7

    • 值:<长度>
      指输入设备完整渲染区域的宽度。对屏幕媒体就是屏幕的宽度。对分页媒体就是页面的宽度。所以,(max-device-width: 1200px)表示当设备输出区域宽度小于1200像素时有效。
  • 描述符:height, min-height, max-height

    • 值:<长度>
      指用户代理的显示区域的高度。在屏幕媒体的web浏览器中,指视口加上滚动条的高度。在分页媒体中,指页框的高度。所以,(height: 567px)表示当视口高度刚好为567像素的时候有效。
  • 描述符:device-height, min-device-height, max-device-height

    • 值:<长度>
      指输入设备完整渲染区域的高度。对屏幕媒体就是屏幕的高度。对分页媒体就是页面的高度。所以,(max-device-height: 400px)表示当设备输出区域高度小于400像素时有效。
  • 描述符:aspect-ratio, min-aspect-ratio, max-aspect-ratio

    • 值:<比率>
      指媒体特性width和媒体特性height的比值(请看下一节中关于ratio的定义)。所以,(min- aspect-ratio: 2/1)表示当视口的宽高比至少为2:1时有效。
  • 描述符:device-aspect-ratio, min-device-aspect-ratio, max-device-aspect- ratio

    • 值:<比率>
      指媒体特性device-width和媒体特性device-height的比值(请看下一节中关于ratio的定义)。所以,(device-aspect-ratio: 16/9)表示当输出设备的宽高比正好是16:9时有效。
  • 描述符:color, min-color, max-color

    • 值:<整数>
      指输出设备显示彩色的能力,可选的数字值表示每一个颜色份量的位数。所以,(color)表示对全部色深的设备有效,而(min-color: 4)表示每一个颜色份量至少是4位色深。不支持颜色的设备将会返回0值。
  • 描述符:color-index, min-color-index, max-color-index

    • 值:<整数>
      指输出设备颜色表中可用的颜色总数。不使用颜色表的设备将会返回0值。所以,(min- color-index: 256)表示当设备拥有至少256个颜色时有效。
  • 描述符:monochrome, min-monochrome, max-monochrome

    • 值:<整数>
      指单色显示器,可选的数字值表示输出设备帧缓存中每一个像素的位数。不是单色显示的设备将会返回0值。所以,(monochrome)表示当单色输出设备时有效,而(min-monochrome: 2)表示当单色输出设备帧缓存中的每一个像素至少为2位时有效。
  • 描述符:resolution, min-resolution, max-resolution

    • 值:<分辨率>
      指以像素密度(以每英寸点数(dpi)或每厘米点数(dpcm))测量的输出设备的分辨率;详细信息请参阅下一节中的<resolution>定义。当输出设备不是正方形像素时,会使用最小密度的轴向,例如,若是一个设备在一个轴(水平或垂直)上的密度是100dpcm而在另外一个轴上的密度是120dpcm,那么100会做为返回值。另外,在非正方形像素状况下,仅指定resolution特性的任何值都不能成功匹配8(尽管min-resolutionmax-resolution能够)。
  • 描述符:orientation

    • 值:portrait | landscape
      指输出设备的完整输出区域中,当媒体特性height值大于等于媒体特性width值时取值为portrait,不然取值为landscape
  • 描述符:scan

    • 值:progressive | interlace
      媒体类型为tv的输出设备的扫描方式9
  • 描述符:grid

    • 值:0 | 1
      指是不是基于栅格的输入设备(例如tty终端)。栅格设备会取值为1,不然取0值。

新的值类型

媒体查询引入了两种以前(2012年初)未在其它场景下使用过的新值类型。这两种类型与特定的媒体特性结合使用,下一节将详细说明。

  • <比率>
    比率值由两个被斜线(/)分开的正整数值,和可选的空格组成。第一个(正整数)值表示宽度,第二个表示高度。所以,要表示宽高比是16:9,能够写成16/9或者16 / 9。到撰写本文时,比率值不支持设置为单个实数或者使用冒号代替斜线。

  • <分辨率>
    分辨率值是正整数,后跟单位标识符dpi(每英寸点数)或dpcm(每厘米点数)。在CSS术语中,“点”能够是任何显示单位,其中常见的是像素。 整数值和标识符之间不容许有空格。 所以,一个每英寸正好具备150个像素(点)的显示器与值150dpi匹配。

样式表内容

那么,样式表的内容究竟是什么样呢?像这样:

h1 {color: maroon;}
body {background: yellow;}

各类各样的嵌入样式表都是有这样的内容组成,不管内容长短,简单仍是复杂。不多有文档的style元素不包含任何规则——尽管有的文档可能只包含一个简单的@import声明列表而没有像上面那样的真正的规则。

在开始本书的其它内容以前,咱们首先须要确认样式表中能包含哪些东西,以及不能包含哪些东西。

标记

样式表中没有标记。这彷佛是显而易见的,但可能会让你惊讶的是,有一个HTML注释标记是例外,由于历史缘由它容许存在于style元素中:

<style type="text/css"><!-- 
h1 {color: maroon;}
body {background: yellow;} 
--></style>

就这样。

规则结构

咱们把结构分解,详细地说明规则的概念。

每条规则由两个基本部分构成:选择器声明块。声明块由一个或多个声明组成,每一个声明是一个属性-值对。每一个样式表都是由一系列规则组成的。图7展现了规则:

图7:规则的结构

图7:规则的结构

规则左侧的选择器,定义了文档中的哪些部分这条规则影响。图7中选择了h1元素,若是选择器是p,那全部的p(段落)元素将会被选择。

规则右侧是由一或多个声明组成的声明块。每一个声明都由一个CSS属性和这个属性的取值组成。在图7中,声明块包含两个声明。第一个会使受影响的那部分文档的color属性值为red,第二个会使受影响的那部分文档的background属性值为yellow。所以,文档中全部的h1元素(由选择器决定)都会被设置为红色文字和黄色背景。

厂商前缀

有时你会看到CSS中存在像-o-border-image这样在前面带着短线和标签的声明。这被称做厂商前缀(vendor prefixes)10,浏览器厂商在提供试验性或专有(或二者)功能时,用它来标记属性、值或其余CSS内容。到2012年中已经有了不少厂商前缀,表1中列出了最多见的几种。

表1: 一些常见的厂商前缀

前缀 厂商
-epub- 国际数字出版论坛epub格式
-moz- 基于Mozilla的浏览器(如:Firefox)
-ms- Microsoft Internet Explorer
-o- 基于Opera的浏览器
-webkit- 基于WebKit的浏览器(如:Safari和Chrome)

如表1所示,厂商前缀的一般格式是短线-标签-短线,尽管有些(厂商的)前缀错误地省略了第一个短线。

厂商前缀的使用以及其后的滥用是一个漫长而又曲折的过程,讲述它超出了本书的范围。咱们只需知道,它们一开始是做为厂商测试新功能的一种方式,从而有助于加速(不一样浏览器之间)的互通性,而不至于被其它不能兼容的旧浏览器禁锢脚步。这避免了一系列问题,使得CSS幸免于在初期就被扼杀的厄运。然而不幸的是,随后前缀属性被web开发者无所顾忌地配置,最终致使了一系列新的问题。到撰写本文时,厂商前缀的将来受到了普遍的质疑,它们极可能在几年内被弃用。

请记住,不管什么时候都要谨慎地处理前缀CSS,使用以前在每种浏览器上测试它们各自的前缀。

空格处理

虽然有些例外,但基本上CSS对规则间的空格不敏感,对规则内的空格则更加不敏感。

通常来讲,CSS处理空格的方式相似HTML:任何空格字符的序列都被当作单个空格解析。所以,一个假想的rainbow规则能够格式化为下面的格式:

rainbow:infrared red orange yellow green blue indigo violet ultraviolet; 
rainbow:
    infrared red orange yellow green blue indigo violet ultraviolet;  
rainbow:
    infrared 
    red
    orange 
    yellow 
    green
    blue 
    indigo 
    violet 
    ultraviolet 
    ;

以及其余你能想到的分隔模式。惟一的限制是分割字符须要是空白:空格、tab符、换行符,单个仍是组合使用,随你喜欢。

相似地,你可使用空白把一系列样式规则按照任何你偏好的风格格式化,这是无限多种可能中的五种格式:

html{color:black;}
body {background: white;} 
p{
    color: gray;} 
h2 {
    color : silver ; 
    }
ol 
    {
        color 
            :
        silver 
            ;
}

在第一条规则中,空白被最大化地略去了。这种状况一般发生在CSS“压缩”的时候,这时会把不影响语义的空格所有删除。前两条以后的规则逐渐加入更多空白,到最后一条规则,几乎每一个能够被分隔的地方都被分开了。

以上的每种方式都是合法的,所以你应该选择一种最有意义的格式,即在你看来最易读的格式,而后坚持一向地使用它。

有些地方是确切地须要空白的,最多见的例子是在属性值中分隔关键字列表,例如上面的假想rainbow例子中。这些地方必须用空白来分隔。

媒体块

若是须要将特定媒体下的规则嵌入样式表中(而不是使用media属性或@import声明把媒体特性用于整个样式表),可使用@media块。像这样:

h1 {color: maroon;} 
@media projection {
    body {background: yellow;} 
}

在这个例子中,h1元素会在全部媒中都显示为栗色,但body元素仅会在投影媒体上被设置为黄色背景。

能够在一个样式表中加入许多@media块,每一个拥有本身的媒体描述符(在后面的章节中详细介绍)。若是你愿意,甚至能够把全部规则封装进一个@media模块:

@media all {
    h1 {color: maroon;}
    body {background: yellow;} 
}

可是因为这种写法与去掉第一行和最后一行以后的写法没有什么区别,所以这么作没有什么意义。

本节中的缩进仅仅是为了显示得更清晰,你不须要遵照@media块中的缩进规则,但这样作是推荐的,由于它可使你的CSS更易于阅读。

CSS注释

CSS是容许添加注释的。与C/C++中用/**/包裹的注释相似:

/* This is a CSS1 comment */

象C++中同样,注释能够连续多行:

/* This is a CSS1 comment, and 
it can be several lines long without 
any problem whatsoever. */

要记住,CSS注释不容许嵌套,像这样是不正确的:

/* This is a comment, in which we find 
another comment, which is WRONG
/* Another comment */
and back to the first comment */

固然,没人想要嵌套注释,因此这个限制没什么要紧的。

一个可能会建立了“嵌套”注释的场景是,当想要把样式表中一大块包含了注释的代码临时注释掉时。由于CSS不容许嵌套注释,“外层”注释会在“内层”注释结束的时候就结束了。

不妙的是,CSS中没有行注释符,如//#(这个字符是ID选择器的保留字)。/* */是惟一的CSS注释方式。所以,若是你想要把注释放置在规则的同一行,就要当心放置的方式,例如,这是正确的方式:

h1 {color: gray;} /* This CSS comment is several lines */ 
h2 {color: silver;} /* long, but since it is alongside */ 
p {color: white;} /* actual styles, each line needs to */ 
pre {color: gray;} /* be wrapped in comment markers. */

这个例子里,若是单行注释没有关闭,会致使大部分样式表变成注释的一部分,也就不能生效了:

h1 {color: gray;} /* This CSS comment is several lines 
h2 {color: silver;} long, but since it is not wrapped 
p {color: white;} in comment markers, the last three 
pre {color: gray;} styles are part of the comment. */

在这个例子中,只有第一行规则(h1 {color: gray;})会被应用于文档。其它的则被浏览器的渲染引擎当作注释的一部分而忽略掉了。

CSS注释会被CSS解析器当作不存在同样,也不会当作空白处理,这意味着你能够把注释放进规则中间,甚至放在声明里!11

总结

CSS能够彻底改变用户代理显示元素的方式。这种改变可使用display属性在基本的显示级别上执行,而且经过把样式表关联到文档的不一样方式来执行,用户不会知道这是经过外部仍是内嵌样式表,甚至行内样式表完成的。外部样式表的重要性在于容许开发者把一个站点的全部展现信息放在一个地方,而后把全部文档指向这个地方。这不只使站点更新和维护变得容易,还由于在文档中移除了全部展现信息而节省了带宽。

为了充分利用CSS的能力,开发者须要弄清楚如何将一组样式与文档中的元素相关联。为了彻底理解CSS是如何作到这一点的,开发者须要透彻地领会CSS选择文档片断的方式,这就是下一个主题:“选择器,特度和层叠”。

1. 译注:Firefox等浏览器所使用的引擎。

2. 译注:Web发展早期第一个普及的浏览器。

3. 译注:Recommendation 是W3C的推荐标准,标准已经历了理论上和实际上的评审和测试,由W3C做签署,能够普遍应用。这是W3C提案的最终成熟的阶段。)

4. 译注:Candidate Recommendation是W3C的候选推荐标准,候选推荐标准与工做草案相比更加稳定,提案的重大的特性大部分已经锁定。

5. 译注:@import规则必须放在其余除了@charset规则之外的CSS规则的前面

6. 译注:本文写于2012年。

7. 译注:device-widthdevice-heightdevice-aspect-ratio三个特性已经被移出Web标准。_

8. 译注:由于设备的水平方向和垂直方向的像素密度不一样,因此使用任何值都不能匹配。

9. 译注:逐行扫描和隔行扫描。

10. 译注:vendor prefixes有时被翻译为“浏览器引擎前缀”或“第三方前缀”,译法未见统一,这里采用直译“厂商前缀”,以突出“vendor”的“厂商”之意。

11. 译注:例如h1 { co/* comments */lor: red; }

相关文章
相关标签/搜索