流
1.文档流(本文简称流)是引导元素排列和定位的布局机制,和现实世界中的水流有点类似。
2.流默认的流向是从左往右,自上而下(复杂的页面布局就需要通过破坏流来实现特殊布局)。
3.流本身具有自适应特性,但表格很特殊,不适用流的规则。
元素
块级元素
“块级元素”对应的英文是block-level element,常见的块级元素有<div>、<li>和<table>等。
需要注意是,“块级元素”和“display为block的元素”不是一个概念。
例如,<li>元素默认的display值是list-item,<table>元素默认的display值是table,但是它们均是“块级元素”,因为它们都符合块级元素的基本特征,也就是一个水平流上只能单独显示一个元素,多个块级元素则换行显示。
一、正是由于“块级元素”具有换行特性,因此理论上它都可以配合clear属性来清除浮动带来的影响。例如:
.clear:after {
content: '';
display: table; // 也可以是block,或者是list-item
clear: both;
}
二、实际开发时,我们要么使用block,要么使用table,并不会使用list-item。
- 1个字符的比较多,其他都是5个字符。
- 会出现不需要的项目符号。这其实并不是什么大问题,再加一行list-style: none声明就可以了。
- IE浏览器不支持伪元素的display值为list- item。这是不使用display:list-item清除浮动的主因,兼容性不好。对于IE浏览器(包括IE11),普通元素设置display:list-item有效,但是:before /:after伪元素就不行。
三、为什么list-item会出现元素符号?
所有的“块级元素”都有一个“主块级盒子”,list-item除此之外还有一个“附加盒子”。之所以list-item元素会出现项目符号是因为生成了一个附加的盒子,学名“标记盒子”(marker box),专门用来放圆点、数字这些项目符号。
四、元素的两个盒子
每个元素都两个盒子,外在盒子和内在盒子。外在盒子负责元素是可以一行显示,还是只能换行显示;内在盒子负责宽高、内容呈现等,内在盒子即容器盒子。于是,按照display的属性值不同,值为block的元素的盒子实际由外在的“块级盒子”和内在的“块级容器盒子”组成,值为inline-block的元素则由外在的“内联盒子”和内在的“块级容器盒子”组成,值为inline的元素则内外均是“内联盒子”。
小结:每个元素都有两个盒子——外在盒子、容器盒子。外在盒子控制是否换行,容器盒子控制宽高
block-block(block),
inline-block,
inline-inline(inline),
block-table(table),
inline-table,
list-items是个特殊的,除了块级盒子外还有个标记盒子。
废除的属性如:run-in此处不讨论。
内联元素
1.从定义看首先要明白这一点:“内联元素”的“内联”特指“外在盒子”,和“display为inline的元素”不是一个概念!inline-block和inline-table都是“内联元素”,因为它们的“外在盒子”都是内联盒子。自然display:inline的元素也是“内联元素”,那么,按钮元素是内联元素,因为其display默认值是inline-block;图片元素也是内联元素,因为其display默认值是inline等。
2.从表现看就行为表现来看,“内联元素”的典型特征就是可以和文字在一行显示。因此,文字是内联元素,图片是内联元素,按钮是内联元素,输入框、下拉框等原生表单控件也是内联元素。下面有一个疑问:浮动元素貌似也是可以和文字在一个水平上显示的,是不是浮动元素也是内联级别的呢?不是的。实际上,浮动元素和后面的文字并不在一行显示,浮动元素已经在文档流之外了。证据就是,当后面文字足够多的时候,文字并不是在浮动元素的下面,而是继续在后面。这就说明,浮动元素和后面文字不在一行,只是它们恰好站在了一起而已。真相是,浮动元素会生成“块盒子”,这就是后话了。
一、内联世界深入的基础—内联盒模型
<p>内联世界深入的基础-<em>内联盒模型</em>请关注</p>
(1)内容区域(content area)。内容区域指一种围绕文字看不见的盒子,其大小仅受字符本身特性控制,本质上是一个字符盒子(character box);但是有些元素,如图片这样的替换元素,其内容显然不是文字,不存在字符盒子之类的,因此,对于这些元素,内容区域可以看成元素自身。内容区域可以理解为平时我们选中的区域如:
(2)内联盒子(inline box)。“内联盒子”不会让内容成块显示,而是排成一行,这里的“内联盒子”实际指的就是元素的“外在盒子”,用来决定元素是内联还是块级。该盒子又可以细分为“内联盒子”和“匿名内联盒子”两类,如果外部含内联标签(<span>、<a>和<em>等),则属于“内联盒子”(实线框标注);如果是个光秃秃的文字,则属于“匿名内联盒子”。
(3)行框盒子(line box)。每一行就是一个“行框盒子”(实线框标注),每个“行框盒子”又是由一个一个“内联盒子”组成的。例如:
4)包含盒子(containing box)——包含块。图例中<p>标签就是一个“包含盒子”(实线框标注),此盒子由一行一行的“行框盒子”组成。例如:
二、幽灵空白节点
“幽灵空白节点”实际上也是一个盒子,不过是个假想盒,名叫“strut”,中文直译为“支柱”,是一个存在于每个“行框盒子”前面,同时具有该元素的字体和行高属性的0宽度的内联盒。
如上图,span的宽高都为0,父元素div的高度却是22,这就是因为幽灵空白节点的存在。
width/height的巧用
深藏不露的width:auto
宽度自适应的四种表现
- 充分利用可用空间。比方说,
<div>、<p>这些元素的宽度默认是100%于父级容器的。这种充分利用可用空间的行为还有个专有名字,叫作fill-available,大家了解即可。 - 收缩与包裹。典型代表就是浮动、绝对定位、inline-block元素或table元素,英文称为shrink-to-fit,直译为“收缩到合适”,有那么点儿意思,但不够形象,我一直把这种现象称为“包裹性”。CSS3中的fit-content指的就是这种宽度表现。
- 收缩到最小。这个最容易出现在table-layout为auto的表格中,如:
当每一列空间都不够的时候,文字能断就断,但中文是随便断的,英文单词不能断。于是,第一列被无情地每个字都断掉,形成一柱擎天。这种行为在规范中被描述为“preferred minimum width”或者“minimum content width”。后来还有了一个更加好听的名字min-content。
- 超出容器限制。除非有明确的width相关设置,否则上面3种情况尺寸都不会主动超过父级容器宽度的,但是存在一些特殊情况。例如,内容很长的连续的英文和数字,或者内联元素被设置了white-space:nowrap。
外部尺寸与流体特性
- 正常流宽度 表现为“外部尺寸”的块级元素一旦设置了宽度,流动性就丢失了。所谓流动性,并不是看上去的宽度100%显示这么简单,而是一种margin/border/padding和content内容区域自动分配水平空间的机制。充分利用流动性这条准则,能让你少写代码,少些计算,少些维护,即“无宽度准则”
- 格式化宽 格式化宽度仅出现在“绝对定位模型”中,也就是出现在position属性值为absolute或fixed的元素中。在默认情况下,绝对定位元素的宽度表现是“包裹性”,宽度由内部尺寸决定,但是,有一种情况其宽度是由外部尺寸决定的,是什么情况呢?
对于非替换元素,当left/top或top/bottom对立方位的属性值同时存在的时候,元素的宽度表现为“格式化宽度”,其宽度大小相对于最近的具有定位特性(position属性值不是static)的祖先元素计算。
和上面的普通流一样,“格式化宽度”具有完全的流体性,也就是margin、border、padding和content内容区域同样会自动分配水平(和垂直)空间。
内部尺寸与流体特性
所谓“内部尺寸”,简单来讲就是元素的尺寸由内部的元素决定,而非由外部的容器决定。如何快速判断一个元素使用的是否为“内部尺寸”呢?很简单,假如这个元素里面没有内容,宽度就是0,那就是应用的“内部尺寸”。
内部尺寸的三种表现形式
-
包裹性——自适应性(元素尺寸由内部元素决定,但永远小于“包含块”容器的尺寸【除非容器尺寸小于元素的“首选最小宽度”】) “包裹性”对实际开发有什么作用呢?请看这个需求:页面某个模块的文字内容是动态的,可能是几个字,也可能是一句话。然后,希望文字少的时候居中显示,文字超过一行的时候居左显示。该如何实现?
-
首选最小宽度——指的是元素最适合的最小宽度 (1)、东亚文字(如中文)最小宽度为每个汉字的宽度
(2)、西方文字最小宽度由特定的连续的英文字符单元决定。并不是所有的英文字符都会组成连续单元,一般会终止于空格(普通空格)、短横线、问号以及其他非英文字符等。例如,“display:inline- block”这几个字符以连接符“-”作为分隔符,形成了“display:inline”和“block”两个连续单元,由于连接符“-”分隔位置在字符后面,因此,最后的宽度就是“display:inline-”的宽度
(3)、类似图片这样的替换元素的最小宽度就是该元素内容本身的宽度
首选最小宽度”对我们实际开发有什么作用呢?可以让我们遇到类似现象的时候知道原因是什么,方便迅速对症下药,其他就没什么用了。其实也可以利用首选最小宽度的规则,快速简单的实现某些特定的效果,如:
- 最大宽度 “最大宽度”实际等同于“包裹性”元素设置white-space:nowrap声明后的宽度。如果内部没有元素成功设定宽度值,则“最大宽度”实际上是最大的连续内联盒子的宽度。
<div>
我是文本
<span>我在inline标签内</span>
<button>这是一个按钮</button>
<br/>
下一行开始
<p>这是一段描述</p>
</div>
width值作用的细节
width是作用在“内在盒子”上的,这个“内在盒子”又被分成了4个盒子,分别是content box、padding box、border box和margin box。content box 写作content-box,padding box 写作padding-box,border box写作border-box,唯独margin box并没有对应的CSS关键字名称。
通常情况下,width控制的是“内在盒子”的content-box。因此元素的实际宽度往往是content-box+padding-box+border-box(也可以通过box-sizing来改变)。
CSS流体布局下的宽度分离原则
所谓“宽度分离原则”,就是CSS中的width属性不与影响宽度的padding/border(有时候包括margin)属性共存,也就是不能出现以下的组合:
.box1 { width: 100px; border: 1px solid; } 或者.box2 { width: 100px; padding: 20px}
当宽度和边框,宽度和内间距同时出现时,box1的实际宽度其实是102,box2的实际宽度时140,当任意一个属性的值变化,都会导致多个变化。
而宽度分离原则的写法则是——分离(width独立占用一层标签,而padding、border、margin利用流动性在内部自适应呈现)
.father {
width: 180px;
}
.son {
margin: 0 20px;
padding: 20px;
border: 1px solid;
}
只需要定一个父元素的宽度,其他属性值有任何改动,都能轻松应对。
宽度分离的优势:
- 便于维护(不用多次计算元素宽度间距等值) 宽度分离的劣势
- 多一层标签
也有即不用计算也不需要多一层标签的做法,就是接下来要讨论的box-sizing
改变width/height作用细节的box-sizing
作为css3的box-sizing其兼容性非常友好
.box1 { box-sizing: content-box; } /* 默认值 */
.box2 { box-sizing: padding-box; } /* Firefox曾经支持 */
.box3 { box-sizing: border-box; } /* 全线支持 */
.box4 { box-sizing: margin-box; } /* 从未支持过 */
前面提到的组合可以完美的出现了,且不用担心设计稿细微的调整等而导致频繁的计算
.box { width: 100px; border: 1px solid; box-sizing: border-box; } 或者
.box { width: 100px; padding: 20px; box-sizing: border-box;}
然而我在我们实际写项目的时候,所有的元素的box-sizing的默认值大多是content-box,为了方便通常会全局格式化样式*{box-sizing: border-box;}
这样做无疑是增加了不必要的开销,对于普通内联元素(非图片等替换元素),box-sizing无论是什么值,对其渲染表现都没有影响,因此,*对这些元素而言就是没有必要的消耗;同时有些元素,如search类型的搜索框,其默认的box-sizing就是border-box(如果浏览器支持)。
box-sizing不支持margin-box,只有当元素没有水平margin时候,box-sizing才能真正无计算。当我们遇到以下这样的需求时,box-sizing就不太够用了
利用宽度分离原则,充分利用元素本身的特性来实现我们想要的效果,方便快捷,便于维护何乐而不为呢?
相对简单而单纯的height
CSS的默认流是水平方向的,宽度是稀缺的,高度是无限的。因此,宽度的分配规则就比较复杂,高度就显得比较随意
height和width一个比较明显的区别就是对百分比单位的支持。对于width属性,就算父元素width为auto,其百分比值也是支持的;但是,对于height属性,如果父元素height为auto,只要子元素在文档流中,其百分比值完全就被忽略了。
height:100%
-
为何height:100%无效 如果包含块的高度没有显式指定(即高度由内容决定),并且该元素不是绝对定位,则计算值为auto。一句话总结就是:因为解释成了auto。
-
如何让元素支持height:100%效果
(1)设定显式的高度值
(2)使用绝对定位
min-height/max-height
- min-width/min-height的初始值是auto,max-width/max- height的初始值是none
- min-width/max-width和min-height/max-height属性会覆盖width/height(即使是!important)
- min-width覆盖max-width
- 未知高度的元素展开收起动画(设置max-height)
本文为阅读张鑫旭老师的css世界一书而写