你可能不熟悉的CSS

虽然对Web应用已经有3年的开发经历,但是我还是CSS处于一知半解的状态。主要是因为对xhtml恐惧,除了刚工作那阵子逼不得已,在后来的项目中我都选择编写数据、通信或框架的代码,最接近UI的仅限到编写WebControl,UI的开发我会交给信任的并且擅长Web-End的partner去做。从2010开始我定位转向互联网开发的工作,看现在每一个网站都在注重UI体验,相关的RIA技术也是火爆异常,博客园的首页经常会有Ajax/JQuery/Silverlight的内容,没办法,我只有补课了,于是最近近乎疯狂的学习相关技术。

如果你和我一样,对CSS一知半解,那么本文相信对你会非常有用。看看下面的列表,其中的css rule你是否都明白是什么意思:

* {font-size:12px;}
div {font-size:12px;}
div > p {font-size:12px;}
div + p {font-size:12px;}
div:first-child {font-size:12px;}
.light {font-size:12px;}
div.light {font-size:12px;}
#light {font-size:12px;}
div#light {font-size:12px;}
div[id] {font-size:12px;}
div[id="foo"]{font-size:12px;}
div[id~="foo"]{font-size:12px;}
div[id^="foo"]{font-size:12px;}
div[id$="foo"]{font-size:12px;}
div[id*="foo"]{font-size:12px;}
div[id|="foo"]{font-size:12px;}
a:link {font-size:12px;}
a:visited {font-size:12px;}
div:hover {font-size:12px;}
div:focus {font-size:12px;}
textarea:active {font-size:12px;}
p:first-letter {font-size:12px;}
p:first-line {font-size:12px;}
p:before {font-size:12px;}
p:after {font-size:12px;}
h1,h2 {font-size:12px;}
.class1, .class2 {font-size:12px;}
div.light a:link {font-size:12px;}

如果上面所列的css selectors中有你不熟悉的,没关系,在读完本文后你会有一个清楚的了解。本文将包括以下内容:

  • 各式各样的CSS Selector
  • CSS Box Model
  • 定位(positioning)
  • CSS的版本和浏览器兼容
  • 其他 

声明:本文所讨论的CSS版本为CSS2.1

CSS Selectors

每一个CSS rule都是由selector {declaration}两部分组成的,如p {font-size:12px},为了更精确选择需要应用CSS样式的元素,CSS为我们提供了各式各样的selector。为什么称为selector(选择器),我在google上查了“why named css selector” ,没有找到答案,但我猜想这应该是和浏览器的实现行为有关,浏览器在从服务器获得html字符流后,要根据CSS“画”出html中包含的DOM element,这个“画”的过程应该是按照DOM element在html字符流中出现的顺序进行的,selector用于匹配满足条件的DOM element,当然这只是猜测,如果有哪位朋友知道麻烦请告诉我。CSS2.1中常用的有以下几种类型的selector:

  • type selector(DOM元素类型选择器)
  • decendant selector (子元素节点选择器)
  • class selector (class 选择器)
  • id selector (id选择器)
  • attribute selector (属性选择器)
  • pseudo-class and pseudo-element selector (伪class和伪元素选择器)

完整选择器的定义请参考W3C文档:

W3C关于CSS2选择器的说明:http://www.w3.org/TR/CSS2/selector.html

最有趣的是, CSS的selector可以组合起来定义,我们看看下面的css rule:

div.post div.entry h1, div.post div.entry h2, div.post div.entry h3, div.post div.entry a:hover{
	margin-bottom:12px;
	margin-top:24px;
}

上述css rule用了grouping selector的定义,匹配如下元素:

1)  匹配所有<div class=”post”>元素中的<div class=”entry”>中的<h1>、<h2>、<h3>元素。

2) a:hover是伪class选择器,匹配所有<div class=”post”>元素中的<div class=”entry”>中的<a>,定义了当鼠标移至<a>元素时的样式。

 

在实际的应用中,有时候会遇到css rule冲突的问题。像博客园的页面包含了博客园的css、模板的css、每个用户自定义的css,难免会造成css selector或css rule的重复定义,看看下面的例子:

body div p { font-size: 14px; }
div p { font-size: 12px; }

上面的例子中同样是选择p元素,那么到底font-size最后是12px还是14px呢?CSS通过计算特征权重来决定最后采用哪个css rule

CSS2中关于特征计算的说明:http://www.w3.org/TR/CSS2/cascade.html#specificity

如果来自于博客园页面的CSS与用户自己设定的偏好CSS冲突了,那又怎么办呢?

IE用户可以完全忽略掉网站页面提供的CSS,而采用自己偏好的CSS定义,具体设置路径:控制面板->Internet选项->常规选项卡->辅助功能

CSS的全称是Cascade Stylesheet,Cascade的意思是级联、层叠,对于来自浏览器、用户和页面的CSS,浏览器将按照这些CSS的优先级顺序,采用高优先级的CSS rule,若同优先级则计算特征。CSS优先级从高到低排序如下:

  1. user important declaration
  2. author important declaration
  3. author normal declaration
  4. user important declaration
  5. user agent declaration (浏览器的css设置)

相信一般的用户是不会去设置自己偏好的CSS设置的,浏览器我们也是管不着的。和CSS编写有关的是2)和3)。我的博客用的是老赵的模板,在模板的css里,div.post h1的设置是gray,sidebar也是gray,但是我个人喜欢绿色和金色,但是不可能修改模板的css,幸好博客园提供了自定义css设置,于是我在自定义css设置中重新定义了h1和sidebar的css rule,覆盖掉了模板css的设置。对于类似这样的css rule,CSS2提供了!important关键字,如:

div.post h1 {color: lime !important;}

所以,标记为important的css rule覆盖掉了模板css中normal的css rule。Anyway,还是要感谢老赵提供的模板,我非常喜欢,老赵很王道。

CSS Box Model

Box Model是CSS的核心,虽然不同浏览器实现技术不同,但是它们都要按照相应的Box Model把html中的dom element给画出来。我们先来看看一段简单的html和它的Box Model:

<p style="height:140px;width:400px">Hi, u r reading a post written by k.k
<img alt="aa" height="120" src="a7946.jpg" width="120" />.</p>

2010-01-17 4-23-08

外层的方框表示的是<p>生成的Box Model,内层的方框表示<img>生成的Box Model,对浏览器来说显示页面就是画框,把这些嵌套的Box Model画出来(最外层的Box Model是html元素或body元素)。关于Box Model,最重要的是弄清楚padding、border和margin三个概念,W3C的文档说得很清楚:

W3C关于Box Model的说明:http://www.w3.org/TR/CSS2/box.html

这里讨论两个有关Box Model的两个概念:Block-level element和Inline-level element

Block-level elements generate an element box that fills its parent element's content area and can not have other elements at its sides(left and right). It generates "break" before and after the element box.

Inline-level elements generate an element box within a line of text and do not break up the flow of that line.

Block-level element和Inline-level element的区别在于——是否会在前后元素之间产生换行。最典型的Block-Level element就是<p>和<div>,他们的出现让前后元素之间产生换行;最典型的Inline-Level element是<a>,他的出现不会让前后产生换行。通过display:block或display:inline,我们可以直接指定DOM element的Box Model的生成方式:

<div>this is <div style="display:block">block-level</div>element</div><p></p>
<div>this is <div style="display:inline">inline-level </div>element</div>

生成页面效果如下:

2010-01-17 4-48-32

display还有一个取值——display:none,可以用来不显示某个element,视觉效果与visibility:hidden相同。但对于两者在浏览器实现上是有区别的:浏览器不会对标记display:none的element的html进行处理,它的高、宽等值失效;visibility:hidden只是视觉上看不见,而浏览器仍保留element所占据的空间,它的高、宽等值仍然有效。简单的说,后者是哈利波特披了隐身斗篷。

现在流行的div弹出对话框,因为计算positioning offset,需要用到div的高和宽等信息,所以css设置要用visibility:hidden。

定位 Positioning

CSS的定位分为三种:浮动定位、相对定位和绝对定位。

浮动定位(float)

用过Word等文字排版工具的用户应该很容易理解浮动定位,类似Word中的图文混排,不过CSS的浮动定位(float)非常简单,只有left和right。

我的博客页面的右上角的About设置就用了float:

<img id="myicon" src="http://images.cnblogs.com/cnblogs_com/chwkai/227090/r_a7946.jpg" alt="k.k icon"/><p class="kkintro">
对一个问题或领域,从不了解到了解,从了解到熟悉,从熟悉到精通,这记录了K.K思考和解决问题的成长过程。</p>
<p class="kkintro">On an issue or area, never learned to understand, from the learned to be familiar with, from the familiar 
to the master, this blog records the K.K's growth by thinking and solving problems.</p>
<p></p>

页面效果如下:

2010-01-17 11-46-51

上面看到是文字和图片混排的效果,如果你不希望混排,可以用设置clear属性,可能取值为left/right/both/none。我们看看上面的html中<p>设置了clear:both后的效果:

2010-01-17 11-51-35

相对定位(position:relative)

相对定位指的是html element的box model包含在父节点的box model内,以父节点的左上角(top-left-corner)为坐标0点的定位。看下面的html代码你就理解了:

<div style="width:200px;height:200px;margin: 30px;border: thin solid black;background-color: #FFFF99;display: block;">
	<div style="width:100px;height:100px;background-color: #CC3300;border: thin solid black;position: relative;top: 50%;left: 50%;"></div>
</div>

内层嵌套的div采用了相对定位,距离父div的左上角(x,y)的距离为(+100px, +100px),页面效果如下:

2010-01-17 13-05-20

绝对定位(position:fixed & position:absolute)

position:absolute指的是相对于已定位的父element的定位,position:fixed是相对于浏览器视窗的定位。当element不存在已定位的父elemenet时,position:absolute将相对浏览器视窗定位,等价于position:fixed。

已定位的父element:the containing block is set to the nearest ancestor (of any kind) that has a position value other than static

我们看看一个绝对定位的例子,google suggestion下拉框:

2010-01-17 14-05-46

css设置:

.gac_m {
-moz-background-clip:border;
-moz-background-inline-policy:continuous;
-moz-background-origin:padding;
background:#FFFFFF none repeat scroll 0 0;
border:1px solid #000000;
cursor:default;
font-size:14px;
margin:0;
position:absolute;
z-index:99;
}

.gac_m中的position:absolute的containing block是浏览器视窗,等价于position:fixed,都是相对于浏览器视窗的定位。现在个网站标配的div对话框基本上是用position:fixed来进行定位的。

CSS的版本和浏览器兼容 Version & User Agent Compatibility

CSS2.1和CSS3.0的浏览器兼容情况一览:http://www.quirksmode.org/css/contents.html

CSS2.1浏览器兼容情况(详细):http://www.webdevout.net/browser-support-css

其他 Tricks

实现div透明遮罩(overlay)

div透明遮罩也基本成了div对话框的标配了,有全浏览器窗口的遮罩,如博客园的求职简历填写;也有边框的遮罩,如豆瓣的“想读”。我个人比较喜欢豆瓣的风格,虽然弹出一个对话框,然后这个浏览器窗口变灰或白这样看起来很酷,但始终给人一种突兀的感觉,当然全屏的遮罩还有一个作用就是模仿模态窗口的效果,这倒是很实用的。

要实现透明遮罩要用到opacity设置,下面给出了在不同浏览器实现透明效果的css

div#overlay {
	/*opacity setting for ie*/
	filter:alpha(opacity=50);
	/*opacity setting for early version of firefox*/
	-moz-opacity:0.5;
	/*opacity setting for early version of safari*/
	-khtml-opacity: 0.5;
	/*opacity setting in css3*/
	opacity: 0.5;
}

CSS Transparency settings for All browsers: http://css-tricks.com/css-transparency-settings-for-all-broswers/

在实现透明遮罩的时候,由于多个div之间存在层叠关系,我们可以通过设置z-index来实现element的层叠次序,z-index值大的在上面。

一个完整的实现overlay遮罩的例子:https://files.cnblogs.com/chwkai/popup.html.xml (去掉.xml后缀可浏览)

解读HTML的<link>元素

我相信做过Web页面都知道<link>可以用来链接外部的css和javascript文件,但不仅局限于此link可用来链接任何的外部资源。

W3C关于HTML的<link>元素的说明:http://www.w3school.com.cn/tags/tag_link.asp

以css为例,一个完整的<link>形如:

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

你可也可以链接一个RSS,当使用Rss feed reader订阅此页面时,reader会自动分析页面中是否包含<link title=”RSS”>的<link>节点,如果有则会以此为该页面的RSS feed,如douban http://www.douban.com/subject/1000534/ 页面:

<link rel="alternate" href="/feed/subject/1000534/reviews" type="application/rss+xml" title="RSS" />

 

这里要说明一下<link rel=”stylesheet” …>和<link rel=”alternate stylesheet” …>两种<link>节点,同样都是链接了外部的css,但浏览器会默认采用<link ref=”stylesheet” …>指向的css,<link rel=”alternate stylesheet” …>将作为备选的css。我们可以通过JS编程的方式实现alternate stylesheet的切换,从而实现诸如字体变换,背景变化等,好像这些功能也是流行网站的标配。

Stylesheet switcher (pure js): http://www.dynamicdrive.com/dynamicindex9/stylesheetswitcher.htm

Switch to alterate stylesheet using jQuery: http://webdevcodex.com/how-to-switch-to-an-alternate-stylesheet-using-jquery/

工具 Tools

工欲善其事必先利其器,进行Web页面开发的时候,有一个好的编辑器是非常重要的,最著名的当然是Adobe Dreamweaver了,但是我更喜欢另外的一个工具——微软的Expression Web Designer 3,更简洁的界面,更好的Asp.Net支持,html和css智能提示也不错,superpreview的功能更方便于查看页面的多浏览器兼容情况。

Expression Web Desginer 3 download (simplified-chinese):

http://download.microsoft.com/download/3/5/8/358EF194-E47F-46BC-815F-D610732E977C/Web_Trial_zh-Hans.exe

第二个推荐的工具时firefox+firebug,firebug提供了inspect element的功能,可以选择页面上的任一dom element查看html和css,非常方便。

firebug:  http://getfirebug.com/

参考资料 References

CSS – The Definitive Guide, 3rd Edition  http://www.douban.com/subject/2152110/

CSS Cookbook, 3rd Edition http://www.douban.com/subject/4016866/

W3School CSS Online Tutorial http://www.w3school.com.cn/css/index.asp

建议每一个Web开发人员都有机会通读《CSS: The definitive guide》,对CSS有一个完整的掌握。

posted @ 2010-01-17 15:27  海南K.K  阅读(3993)  评论(15编辑  收藏  举报