前言:
CSS是前端样式的基础,目前比较流行的Bootstrap、layui、sass、less等这些框架,都有CSS的影子。CSS是内功,需要静下心来修炼,以后的Bootstrap、layui、sass、less等这些是招式。内功不稳,很容易被打出内伤。所以建议你把CSS的内功修炼好,以后就可以见招拆招啦。
——献给新新萌的你
正文:
1.流
写CSS布局时,很少人会关注CSS流。其实CSS中的布局是由流完成的:流是CSS布局的规则,它是引导页面定位和布局的沟渠,默认的流向是自左向右,从上到下,但是可以通过CSS属性设置来局部改变,在流的世界里有块级元素和内联元素。流,你可理解为水流,块级元素和内联元素就是水流上漂浮的物体。
道德经上说:上善若水,水利万物而不争,处众人之所恶,故几于道。你说流厉不厉害!
2. CSS语法
CSS语法:
你可以这样理解:
搜刮一下自己的初中生物知识,把CSS的世界当成一个生物圈,那么想象一下:
是不是很有意思,很有仿生学的感觉。就是这样子,遇到陌生的东西,把它多多带到你熟悉的地带,那里才是你的舒适区,你才能发挥你的水平!
3.盒子
CSS把页面元素当成一个个的矩形盒子(即使你看到的是一个有圆角的元素,它在你看不到的区域也是一个矩形盒子)。
把CSS盒子想象成你的梳妆盒:
里面可能还有盒子,盒子还套盒子,然后就是具体的梳妆物。(男生的我不太清楚小女生的梳妆盒,但是不耽误把它们联系在一起)。
那么CSS盒子也是一样,它里面也是有好多个盒子。CSS盒子是一个概念,它是一个元素(以下称元素盒子)以CSS解析后其中各个盒子的集合称呼。
一个元素盒子有外在盒子,内在盒子(容器盒子)、附加盒子等。(咦!我为什么要说“等”?因为目前我只知道这几个,而且CSS规则制定组织W3C也会根据未来的需求为元素盒子再考虑添加新的盒子,这都是说不定的事)。
这么说你可能还不明白,那举个例子:
(1) display:inline-block ;
的元素盒子的分布:外在盒子是inline,内在盒子是block。
- 外在盒子负责与其他元素盒子交涉,就像是一个国家的外交官一样。
- 内在盒子负责管理它内部内容“子民”,就像是国家的内政官员。
这也是为什么inline-block元素既可以不换行又能设置宽高的原因。
(2) display:inline;
和 display:block;
元素(这是我的理解,不一定对)
display:inline;
元素盒子的分布:外在盒子和内在盒子都是inline。display:block;
元素盒子的分布:外在盒子和内在盒子都是block。
(3)li元素的前缀(比如· 和 1. 这两个前缀)就是附加盒子的产物。
这也是你为什么操控不了其前缀的原因:因为我们平时写的CSS属性大部分是作用给内 在盒子和外在盒子上的。
说一下我的想法:我猜测width
、height
、padding
、border
这些属性是作用在内在盒子中的,而margin
是作用在外在盒子中的。
4.块级元素
CSS中块级元素负责结构(架构),内联元素负责内容。
像一个房子的整体框架、每个屋子的框架,这就是块级元素该干的活。
而屋子里书架上书的罗列、茶几上茶具的摆放,这就是内联元素要干的活。
也就是说块级元素可以嵌套块级元素和内联元素,而内联元素最好只放置内容(比如文字),当然它也可以嵌套内联元素。
有一点要注意,内联元素不要嵌套块级元素,如果你这样写了,可能会正常显示内容,但是你设置的CSS属性就可能去海南度假没空搭理你啦。
说了这么多,那到底什么是块级元素?理论上div
、p
、li
这些元素CSS默认的是块级元素。而透过现象看本质,它的背后大BOSS是display这个属性,通过设置 display:block;
可以将一切元素声明为块级元素。
块级元素的内在盒子和外在盒子都是block(块级)的。
块级元素的表现是:可以设置width
、height
、margin
、padding
,而且不管width是多大,其相邻的兄弟元素都不能在它这一行站着,连看都不可以看(CSS流的规则)。
有一点大学时占座位的感觉,寝室一个人去到教室,选一个适合上课睡觉的后排好位置,这一排放上书,别人就不会去做那个位置了,这就是块级元素的占位子的套路。
5.内联元素
理论上span
、i
、label
这些标签这些元素CSS默认的是内联元素。同理,可以通过设置
display:inline;
将一切元素声明为内联元素。
内联元素也叫行内元素,其内在盒子和外在盒子都是inline(行内)的。
内联元素的表现是:
不可以设置width
、height
、margin
、padding-top
、 padding-bottom
,可以设置padding-left
和padding-right
(但可以通过设置 line-height
来撑起其高度)。其相邻的兄弟内联元素可以和它肩并肩同行显示。
这里说的不可以不是真的不可以,你可以设置这些属性,但是它们不起作用。拿padding-top
来说。你给内联元素设置这个属性,他的上部的距离并没有变化,但是你通过开发者工具(F12)打开查看这个元素的结构时,它是有padding-top
区域的,但是它不占位子,它的padding-top
被它上面的大哥按在地上打爆狗头啦。
还是那个占位子的同学,书一一放好了,准备占位子,可悲的是,来的人不管你的书,直接把书当成了坐垫儿,什么位置?什么书?没看到啊!这时候是不是应该来一首阿炳的二胡独奏《二泉映月》,不觉悲从中来。
6.inline-block元素
这个元素按照严格意义来说也是内联元素,因为按照它的外在表现,第一眼看上去就给它打了一个内联元素的标签。但为了好区分,还是把它单独列出来吧。
给元素设置display:inline-block;
属性即可。
inline-block元素它在CSS的世界里的处事就要比块级元素和行内元素圆滑一些。它的处事原则就是:自己多大体积就占多大的位置,绝不越界。
具体表现就是:可以设置width
、height
、margin
、padding
,其非块级兄弟元素可以和它肩并肩同行显示。
7.元素尺寸
这里说的元素尺寸不仅仅是width
、height
,width
、height
只是其中的一部分。你可以把它暂且看成元素的二维空间。
元素尺寸分为外部尺寸和内部尺寸。
- 外部尺寸:由父容器元素控制的内容区域空间。
- 内部尺寸:由当前元素或其子元素控制的内容空间区域。
看到这里你一定会脑袋上冒出了圈圈:黑人问号。不用怕,我会慢慢擦掉那些问号,然后把他变白。
来个例子:
.mother{
width:1000px;
height:1000px;
}
.daughter{
width:100px;
height:100px;
}
.daughter-daughter{
width:10px;
height:10px;
}
<div class="mother">
<div class="daughter">
<div class="daughter-daughter"></div>
</div>
</div>
瞧!这一家人!以daughter的角度看mother,mother的空间(目前是1000*1000的区域)就是daughter的外部尺寸。
这是mother给她的成长环境,daughter乖的话就会在这个区域内自由活动(margin
)和成长(width
、heihgt
)。
遵照mother的叮嘱,daughter也会给daughter-daughter一个成长环境(目前是100*100的区域),让daughter-daughter也在她的呵护下快乐的成长和活动,而这一区域就是daughter的内部尺寸。
这样窥探这三代div家族的生活,你是不是清楚外部尺寸和内部尺寸的定义了。你会疑问有什么用呢?拍一拍你的…呀!仙人掌!当~~~然~~~有~~~用。
外部尺寸的别名又叫可用空间,你可以通过一些属性的设置让daughter充分利用可用空间,这样能达到自适应的效果,无论浏览器窗口多大她都可以随着一起变大和变小。这是mother给她的保护。块级元素的width天然拥有此特性不用设置(其实其内部是将块级元素设置了一个width:auto;
的属性。这是流的一个特性吧,因为流的默认流向是先自左向右,然后在自上而下,所以流会对横向多关照一些,正常流中块级元素默认只对宽度有此特性)。对于定位元素position:absolute;
需要设置top:0;bottom:0;left:0;right:0;
才会充分利用可用空间(position:absolute;
是破坏文档流,你可以先不考虑,它在另一篇定位有讲解)。
内部尺寸有包裹性,什么是包裹性?包裹性又叫收缩到合适。
- 双11要到了,到时你可以体会一下,快递给你包裹的大小是由你内部物品的大小决定的,不太可能你买了一部手机,她给你用吉他的包裹装的。
- 再一个例子就是现在钱包鼓鼓的,双11过后钱包瘪瘪的。
细细品一下,这就是包裹性。在CSS中的表现就是
-
没有设置height的块级元素会随内容自动撑开高度。
-
还有内联元素,它把这一特性发挥到了极致。
-
还有就是定位元素(
position:absolute
)和浮动元素(float:left
)都有这一特性。
包裹性能让元素自适应内容伸缩。这是daughter给daughter-daughter的关爱:你喜欢怎样就怎样,我完全包容你。
8.元素的width/height
为什么说元素尺寸不只是width/height。看一下下面的例子你就知道啦:
div{
width:100px;
padding-left:20px;
}
你猜一下,这时的div的实际宽度是多少?
120px!对的,我没有打错,它的实际占用的物理宽度时(100+20)px,而它的可用空间是100px。
再看一下
div{
box-sizing:border-box;
width:100px;
padding-left:20px;
}
这次呢?哈哈!
这次不一样了!它的实际占用的物理宽度是100px,而它的可用空间是(100 - 20)px。
所以说width/height是元素的实际尺寸只是一种情况,不能以偏概全。
这个box-sizing
施展了什么魔法让width/height这么听话呢?
box-sizing
是CSS3的属性,它控制width/height对元素的作用区域。
目前有两种值:content-box
(默认值)、border-box
。
这里需要延伸一下:平时我们可以给元素设置margin
、border
、padding
和content内容部分
。
CSS3把这里每个区域划分出来(专业术语叫做盒模型),分别叫做border-box
、padding-box
和content-box
(为什么没有margin-box?我猜测是margin是在外在盒子之上,它对盒子内部的影响不大,所以不需要。如果你喜欢也可以在你的知识图谱中虚构一个margin-box,这都无伤大雅)。
收!回来看看这个box-sizing
的这两个值。
- content-box:让width/height作用在盒模型的content-box,也就是内容区域
。
- border-box:让width/height作用在盒模型的border-box,也就是边框区域。
width/height说了这么多,下面是重磅炸弹!请选择安全地点,戴好安全帽!
元素width设置具体值时,会阻断其容器盒子的流特性(布局自适应),你要尽量应用这一特性,虽然现在CSS3的一些新东西已经可以做到这一点,但是要是遇到对CSS3支持不友好的浏览器呢。
把它当成一种信仰,不需要你时时瞻仰它,当你遇到困难时想到它,可能它会给你一种思路。
有一个案例:
小A写了一个div的样式,想让.card卡片元素在200px的外框下水平展示,为了其能平铺满wrap元素,给.card元素width:100px;
<div class="wrap">
<div class="card c1">卡片1</div>
<div class="card c2">卡片2</div>
</div>
.wrap{
overflow:hidden;
width:200px; /*主要看这里*/
outline:6px solid #000;
}
.card{
float:left;
height:100px;
width:100px; /*主要看这里*/
line-height:100px;
text-align:center;
}
.c1{
background:tan;
}
.c2{
background:pink;
}
这时BOSS屁颠屁颠跑来找小A,说卡片再加一个边框比较好看,这时小A有急于提交的其他项目,于是把这个需求给了新同事小H,小H信心满满的说这儿事儿包我身上了。然后小H的card代码是这样的
.card{
width:100px;
border:1px solid rgba(255,255,0,0.5);
/**其他代码不变,偷个懒省略**/
}
Ctrl+S,浏览器F5。
妈耶!怎么了,card怎么跑偏了!在改
.card{
width:98px;
border:1px solid rgba(255,255,0,0.5);
/**其他代码还不变,再偷个懒省略**/
}
打完收工!交给BOSS看一下,BOSS看完之后觉得边框不明显,再大一点。于是代码变成了这样
.card{
width:84px;
border:8px solid rgba(255,255,0,0.5);
}
大功告成!小H瞬间觉得小学的加减乘除没白学,终于有用武之地了,于是有些飘飘然了。
过段时间,小A的项目忙完了,善变的BOSS又来找小A,说边框太大了,再小点。小A拿到代码一看,会心一笑,对小H说:还是年轻啊,你不觉得这84px怪怪的么。小H挠挠头,尴尬笑着。
小A对小H说:看我重构一下代码结构
<div class=”wrap”>
<div class=”card-wrap”>
<div class=”card”></div>
</div>
<div class=”card-wrap”>
<div class=”card”></div>
</div>
</div>
.wrap{
overflow:hidden;
width:200px; /*主要看这里*/
outline:6px solid #000;
}
.card-wrap{
float:left;
width:100px; /*主要看这里*/
line-height:100px;
text-align:center;
}
.card{
border:4px solid rgba(255,255,0,0.5); /*主要看这里*/
height:100px;
}
哇!怎么实现的,这么神奇!小H好奇的问。
宽度分离!
把宽度的设置放到父元素,而其他属性的设置就在这个元素上设置即可,此时这个元素的宽度是充分利用可用空间的。以后再改这个元素的样式,就不用动用你的小学数学知识图谱了。小A谆谆的道。
这在武学上是不是就叫做乾坤大挪移:
他强由他强,清风拂山岗,他横任他横,明月照山岗。
哈哈哈,小A,小H笑道。
于是小H找到BOSS说:你看一下,我调,你看哪个合适你就喊停。
至此之后,小H再也不用担心BOSS善变了!
9.内联盒模型
内联盒模型适用在外在盒子为inline的元素上,比如display
值为inline
和inline-block
的元素。
内联盒模型包括:内容区域、内联盒子、匿名内联盒子、行框盒子、包含盒子(包含块)。
- 内容区域:可以简单理解为文字部分(一般平时你用鼠标拖动选中文字那个蓝色的背景条就是内容区域)。
- 内联盒子:用内联元素包裹的文字会创造出一个内联盒子。
- 匿名内联盒子:没有内联元素包裹的文字,一般是在块级元素下直接输入文字,这样会创造出一个匿名内联盒子。
- 行框盒子:当你的文字多时会自动折行,这就是行框盒子的功劳。
- 包含盒子:块级元素会在所有内联元素的上面创造一个包含盒子,也叫包含块。
看一下例子:
<p>
I am XiaoYang!<em>What is your name?</em>Nice to meet you!
</p>
10.幽灵空白节点
看到这里你已经很棒了!恭喜你,你已经拿到前端观光旅游的门票了!祝你在前端的世界玩的嗨森。
这里我要讲一个鬼故事:从前,好久好久以前…算了,手有些抖,还是讲一个正常的故事吧。
在HTML5之前,HTML这个村落的日子清淡,日出而作日落而息,土地平旷,屋舍俨然,有良田美池桑竹之属。后来HTML5来到了这个村落,带来了外面的信息,它们才知道已经改朝换代了,于是它们积极应对变化,自我改变,于是村落变成了小洋楼,家家户户都富足了起来。可也出现了奇怪的事情:有时不知谁家前院就多了一道沟壑。它们把它称为幽灵空白节点。听起来挺可怕的,于是村民们聚在一起开了个针对《幽灵空白节点的分析讨论会》,会上总结了幽灵空白节点的出现时机,下面是它们总结内容:
幽灵空白节点的出现时机:
(1)HTML5声明
(2)内联盒模型中
(3)产生于每个行框盒子的开头
(4)宽度为0,受line-height和字体各属性的影响
(5)英文名叫“strut”,中文翻译为“支柱”
好了,关于幽灵空白节点的具体报道我会持续跟进。
(注:为什么不在这一节中写,因为旭大神就是在下面某个章节具体介绍的,我得紧跟着大神的步伐呀)