1. HTML的困境
我是著名的CSS, 很多人都知道我的名字, 但是却对我的原理和细节不求甚解。
这也可以理解,相比于简单的HTML,我要复杂得多, 尤其是想要使用我做出美奂美伦的页面,需要了解太多的细节,那真不是一件普通人能干的事儿。 于是大家看见我以后最多打个招呼,然后马上低头绕行。
说起HTML,这其实是个非常单纯的家伙, 他只关注内容的语义, 比如说他用<h1>表明这是一个大标题,用<p> 表明这是一个段落,用<img> 表明这儿有一个图片, 用<a> 表示此处有链接。
链接真是个有趣的发明, 它可以从一个网页跳到另外一个网页,从一个网站跳到另外一个网站,于是整个世界的网站都链接了起来,形成了一张大网 。
在我诞生之前, 世界上的网站虽然很多,但是他们都有一个共同的特点: 丑。
原因很简单, 一个HTML文档有很多标签, 当这些标签组合起来的时候,到底该怎么显示呢? 用什么样的字体? 什么颜色? 怎么对齐?
HTML不想管也管不了,于是早期的网站大部分长这个样子:
真是难以想象,上个世纪的人们竟然用这么简陋的网站来购物 !
无数的人向HTML投诉: 你就不能把自己打扮得漂亮一点吗?
HTML理直气壮地回答:不不,我的主人只让我负责网页的内容和结构,至于这些结构要显示成什么样子,浏览器可以负责啊。
而浏览器也会推卸责任:“这我可管不了,你不告诉我你用什么字体,什么颜色,我怎么可能给你展示出来?”
理由很充分,对吧,浏览器确实不应该做这件事情。
HTML没有办法,只好向组织上申请,给自己加上一堆新的标签, 专门用来描述展示相关的东西:
于是网页变得比以前漂亮了一些,大家似乎满意了。
只是HTML发现自己的身躯越来越臃肿,这些负责显示的标签把原本的内容都给淹没了, 更要命的是修改的难度越来越高,你可以想象一下,当一个html文件中有上百个<font>标签时, 老板让你把字体改小一号, 那肯定要抓狂的。
组织上看到了问题的症结所在, 决定为HTML瘦身, 他定下了一个目标: “内容和样式必须要分离!”
这个重担就交给了我。
2 选择器
刚开始的时候,我一点思路都没有,到底怎么把内容和样式分离呢? 我为此苦苦思考了好几天,既然我想给内容施加样式, 作为***步, 必须要解决定位的问题,换句话说我需要能找到HTML中的元素才可以。
我问HTML:“ 你一个页面这么多标签, 我怎么才能获得你完整的结构呢?”
“结构? 那很简单啊, 我在浏览器中就是一个DOM 树啊, 你尽管访问啊 ”
好 ! 有这个玩意儿就好办事了,但是我怎么定位到一个元素,去设定这个元素的字体,颜色等显示属性呢?
XML向我支招: “这太容易了, 你可以仿照我的XPath啊,例如那个DOM树,你想选中title 元素,就用 /html/head/title ,或者简单一点//title ; 你想选中***个div 下面的h3, 可以这么做 /html/head/div[1]/h3 ,是不是很方便? ”
(码农翻身老刘注:实际上XPath的出现要比CSS晚)
“方便是方便, 可是你这为什么要一个斜杠呢? 直接写成html head title 不行吗? ”
"这。。。" XML无语了。
我决定不用斜杠,我要讨好程序员,就用div ul li 这样写起来很简洁的方式, 我也不想叫XPath, 那是XML的宝贝。
我打算把它叫做选择器(Selector)。比如说我想把所有的h3都变成红色, 黑体, 可以这么写:
h3 {color:blue ; font-weight:bold;}
当然我设计的选择器能力可不仅仅这么简单,使用它你完全可以选择一个特定的节点(如果有id属性或class属性的话),不管这个节点“隐藏”得有多深。
还可以选择一个节点的兄弟节点, 某组元素的第x个孩子,任何带有属性名的标签名等等。
一句话, 使用Selector, 你可以尽情在DOM树中遨游, 找到你想要的地方, 然后设置样式。
内容和样式就分离了。
3 盒子
定位的问题解决了, 初步的样式也解决了。 但是最让人排版的问题依然存在, 想想你曾经看过的报纸和杂志,人家那图文并茂,赏心悦目的排版, 我们得好好学习下了。
我对杂志的排版做了仔细的研究, 分栏,间距,对齐, 图文混排, 本质上他们是由一个个“块”组成的。
我对HTML说: 咱们能不能也把内容搞成一个一个的块啊, 然后把这些块进行组合不就成了?
HTML回答: “块(block) 我有啊, 你还不知道吗, 所有的HTML元素要么是块级(block)元素,要么是行内(inline)元素。”
“什么意思?”
“块级元素(比如标题和段落) 会一个接一个的堆叠起来沿着页面向下排列,每个元素占一行; 行内元素(比如链接和图片)则会在一行内相互并列,只有在空间不足以并列的时候才会折到下一行。你可以想象一下, 一个文档其实就是这些元素在页面上堆叠流动而已, 俗称文档流。”
既然如此, 我就可以把这些元素当成一个个的“盒子”了,为了能够排版,我给每个盒子都都设定三个属性:
边框(border): 可以设定宽窄,样式,颜色
内边距(padding): 内容到边框的间距
外边距(margin): 边框到相邻元素的间距
通过调整内外边距和边框,你就可以对页面做一点基本的美化排版了。
4 浮动和定位
盒子还只是在在文档流中按次序流动而已, 想要做到漂亮的排版, 还得让他们灵活地定位才行。
比如说有人想把一个盒子放到浏览器的最右边,不会随着页面滚动而滚动;
或者大盒子中套了一个小盒子,小盒子要相对于大盒子来定位;
或者两个盒子想罗列起来;
或者像报纸杂志那样分栏显示,左边是菜单,中间是内容,再加上一个右边栏; 等等诸如此类的要求。
所以,一个盒子必须得能在常规的文档流中重新定位,于是我给盒子添加了两个重要的属性:float和position 。
float可以让一个盒子脱离标准的文档流,一直往上飘,直到遇到父元素的边界。
当有多个盒子都在飘的时候,就可以按照次序形成分栏的效果了。
比如下面这3个<div> 本来是从上往下依次往下流动的, 如果给div2, div3加上float:left属性,他们就横着排列起来了:
对于position 来说, 那就更加灵活了。 如果不设置,那就是默认定位,在文档流中的位置不做改变。
可以设置为相对于盒子在原来文档流中的位置做定位(原来的位置没有被别的div占据):
还可以设置成相对于某个父元素做绝对定位(下图中祖先元素就是橙色的框,div2原来的位置被div3占据了) 。
唉,给大家说这么多琐碎的东西, 我自己都有点烦了, 总结下就是:我提供了各种各样的方式让你的盒子可以灵活的排列起来。
当然我必须得承认, 这些布局对程序员们确实不那么友好,你没有办法通过拖拽的方式对这些盒子进行排版。
为了减少工作量,大量CSS框架在源源不断地推出,例如Bootstrap, Semantic UI, Pure.css , EZ-CSS。。。。。。 这是后话了。
5 CSS
浮动和定位可以说是我搞出的最复杂的东西, 其他的像背景了,字体了,文本了就简单得多,就不再啰嗦了。
当我告诉HTML我的定义工作基本搞定时, 他提出了一个问题: “你这些选择器,盒子模型,浮动和定位, 背景,字体之类定义,最终要放在哪儿啊? 你不会还是想放在我这里吧?”
我想了想,必须得有***的灵活度,程序员可以直接写到元素的标签中(叫行内样式), 也可以写到html的<style>标签里(这叫嵌入样式), 当然我是建议大家写到单独的CSS样式中,然后通过链接的方式和html内容结合起来。
行内样式长这个样子:
很明显,这和最早的在html中写<font>标签差不多。
嵌入样式就好一点:
如果把这些样式完全从html中分离,放到独立的文件中,就可以使用链接样式:
- <link href="mystyle.css" rel="stylesheet" type="text/css" />
正像你猜到的那样, 嵌入样式会覆盖链接样式, 行内的样式会覆盖嵌入样式。 就像一层盖着一层那样, 就是由于这个原因,W3C把我命名为层叠样式表(CSS)。
【本文为51CTO专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】