流、元素、基本尺寸
- 块级元素: 基本特征是一个水平流上只能单独显示一 个元素,多个块级元素则换行显示。
// 清除浮动 .clear::after { content: ''; display: block; // 也可以是 table,或者是 list-item clear: both; }
- 盒子: 每个元素都两个盒子, 外在盒子1和内在盒子。外在盒子负责元素是可以一行显示,还是只能换行显示;内在盒子负责 宽高、内容呈现什么的。
- “鑫三无准则”,即“无宽度,无图片,无浮动”。为何要“无宽度”? 原因很简单,表现为“外部尺寸”的块级元素一旦设置了宽度,流动性就丢失了。
所谓流动性,并不是看上去的宽度 100%显示这么简单,而是一种 margin/border/padding 和 content 内容区域自动分配水平空间的机制。 - 首选最小宽度: 父类宽度为0,在 CSS 世界中,图片和文字的权重要远大于布局,因此,CSS 的设计者显 然是不会让子类图文在 width:auto 时宽度变成 0 的,此时所表现的宽度就是“首选最小宽度”
// 包裹性 // 文字少的时候居中显示,文字超过一行的时候居左显示 .box { text-align: center; } .content { display: inline-block; text-align: left; }
- 所谓“宽度分离原则”,就是 CSS 中的 width 属性不与影响宽度的 padding/border(有时候包括 margin)属性共存; 分离,width 独立占用一层标签,而padding、border、margin 利用流动性在内部自适应呈现。
- 在 CSS 世界中,唯一离不开 box-sizing:border-box 的 就是原生普通文本框 input 和文本域textarea 的100%自适应父容器宽度。拿文本域textarea举例,textarea为替换元素,替换元素的特性之一就是尺寸由 内部元素决定,且无论其 display 属性值是 inline 还是 block。这个特性很有意思,对于非替换元素,如果其 display 属性值为 block,则会具有流动性,宽度由外部尺寸决定,但 是替换元素的宽度却不受 display 水平影响,因此,我们通过CSS 修改textarea的 display 水平是无法让尺寸100%自适应父容器的
textarea { width: 100%; -ms-box-sizing: border-box; /* for IE8 */ box-sizing: border-box; }
- 如何让元素支持 height:100%效果: (1)设定显式的高度值;(2)使用绝对定位
使用绝对定位:此时的 height:100%就会有计算值,即使祖先元素的 height 计算为 auto 也是如此。 需要注意的是,绝对定位元素的百分比计算和非绝对定位元素的百分比计算是有区别的,区别 在于绝对定位的宽高百分比计算是相对于 padding box 的,也就是说会把 padding 大小值计算 在内,但是,非绝对定位元素则是相对于 content box 计算的。
- 内联元素:“内联元素”的“内联”特指“外在盒子”,和“display 为 inline 的元素”不是一个概念!inline-block 和 inline-table 都是“内联元素”,因为它们的 “外在盒子”都是内联盒子。“内联元素”的典型特征就是可以和文字在一行显示。
- 幽灵空白节点: 内联元素的所有解析和渲染表现就如同每个行框盒子的前面有一个“空白节点”一样。(每一行就是一个“行框盒子”(实线框标注),每个“行框盒子”又是由一个一个“内联盒子” 组成的。)
盒尺寸四大家族
- 替换元素: 修改某个属性值呈现的内容就可以被替换的元素就称为“替换元素”。因此,img、object、video、iframe或者表单元素textarea和input都是典型 的替换元素。
(1)内容的外观不受页面上的 CSS 的影响。(2)有自己的尺寸。在很多 CSS 属性上有自己的一套表现规则。比较具有代表性的就是 vertical-align 属性
-
所有的替换元素都是内联水平元素,也就是替换元素和替换元素、替换元素和文字都是可 以在一行显示的;
- 替换元素的尺寸计算规则: (1)固有尺寸指的是替换内容原本的尺寸; (2)HTML 尺寸只能通过HTML 原生属性改变;(3)CSS 尺寸特指可以通过 CSS 的 width 和 height 或者 max-width/min-width 和 max-height/min-height 设置的尺寸,对应盒尺寸中的 content box。
1)如果没有 CSS 尺寸和 HTML 尺寸,则使用固有尺寸作为最终的宽高; 2)如果没有 CSS 尺寸,则使用 HTML 尺寸作为最终的宽高。 3)如果有 CSS 尺寸,则最终尺寸由 CSS 属性决定。 4)如果“固有尺寸”含有固有的宽高比例,同时仅设置了宽度或仅设置了高度,则元素依 然按照固有的宽高比例显示。 5)如果上面的条件都不符合,则最终宽度表现为300像素,高度为150像素,宽高比2:1(唯独图片例外)。 6)内联替换元素和块级替换元素使用上面同一套尺寸计算规则。
- 替换元素和非替换元素的距离有多远: 1)观点 1:替换元素和非替换元素之间只隔了一个 src 属性! 2)观点 2:替换元素和非替换元素之间只隔了一个 CSS content 属性!
- content 内容生成技术:
// HTML: // 正在加载中<dot>...</dot> // CSS: dot { display: inline-block; height: 1em; line-height: 1; text-align: left; vertical-align: -.25em; overflow: hidden; } dot::before { display: block; content: '...\A..\A.'; white-space: pre-wrap; animation: dot 3s infinite step-start both; } @keyframes dot { 33% { transform: translateY(-2em); } 66% { transform: translateY(-1em); } }
- 深入理解 content 计数器: 对应CSS计数器的两个属性(counter-reset和counter-increment)和一个方法(counter()/counters())
- 一个错误的认识:内联元素 的 padding 只会影响水平方向,不会影响垂直方向。这种认知是不准确的,内联元素的 padding 在垂直方向同样会影响布局,影响视觉表现。 只是因为内联元素没有可视宽度和可视高度的说法(clientHeight 和 clientWidth 永远是 0),垂直方向的行为表现完全受 line-height 和 vertical-align 的影响,视觉上并没有 改变和上一行下一行内容的间距,因此,给我们的感觉就会是垂直 padding 没有起作用。如果我们给内联元素加个背景色或者边框,自然就可以看到其尺寸空间确实受 padding 影响了
- CSS 中还有很多其他场景或属性会出现这种不影响其他元素布局而是出现层叠效果的现象。比如,relative 元素的定位、盒阴影 box-shadow 以及 outline 等。这些层叠现象虽 然看似类似,但实际上是有区别的。其分为两类:一类是纯视觉层叠,不影响外部尺寸;另一类则会影响外部尺寸。box-shadow 以及 outline 属于前者,而这里的 inline 元素的padding 层叠属于后者。区分的方式很简单,如果父容器 overflow:auto,层叠区域超出父 容器的时候,没有滚动条出现,则是纯视觉的;如果出现滚动条,则会影响尺寸、影响布局。
- 实际上,对于非替换元素的内联元素,不仅 padding 不会加入行盒高度的计算,margin和 border 也都是如此,都是不计算高度,但实际上在内联盒周围发生了渲染。
// 首先,我们可以在不影响当前布局的情况下,优雅地增加链接或按钮的点击区域大小 article a { padding: .25em 0; } // 利用内联元素的 padding 实现高度可控的分隔线 // HTML: // <a href="">登录</a><a href="">注册</a> // css a + a::before { content: ''; font-size: 0px; // 消除幽灵空白节点 padding: 10px 3px 1px; margin-left: 6px; // padding-left 和 padding-right的和 border-left: 1px solid gray; }
- padding 的百分比值: 其一,和 margin 属性不同,padding 属性是不支持负值的;其二,padding 支持百分比值,但是,和 height 等属性的百分比计算规则 有些差异,差异在于:padding 百分比值无论是水平方向还是垂直方向均是相对于宽度计算的!
// 实现了一个宽高比为 5:1 的比例固定的头图效果
.box {
padding: 10% 50%;
position: relative;
}
.box > img {
position: absolute;
width: 100%; height: 100%;
left: 0; top: 0;
}
// 修改button
// <button id="btn"></button> <label for="btn">按钮</label>
button {
position: absolute;
clip: rect(0 0 0 0);
}
label {
display: inline-block;
line-height: 20px;
padding: 10px;
}
// padding 属性和 background-clip 属性配合
.icon-menu {
display: inline-block;
width: 140px; height: 10px;
padding: 35px 0;
border-top: 10px solid;
border-bottom: 10px solid;
background-color: currentColor;
background-clip: content-box;
}
- margin 同样可以改变元素的可视尺寸(元素的 padding box的尺寸),但是和 padding 几乎是互补态势。什么意思呢? 对于 padding,元素设定了 width 或者保持“包裹性”的时候,会改变元素可视尺寸;但是 对于 margin 则相反,元素设定了 width 值或者保持“包裹性”的时候,margin 对尺寸没有 影响,只有元素是“充分利用可用空间”状态的时候,margin 才可以改变元素的可视尺寸。
CSS 世界默认的流方向是水平方向,因此,对于普通流体元素,margin 只能改变元素水平方向尺寸;但是,对于具有拉伸特性的绝对定位元素,则水平或垂直方向都可以,因为此时 的尺寸表现符合“充分利用可用空间”。
// ---------------margin 与元素的内部尺寸--------------
// 此时元素宽度还是 300 像素,尺寸无变化。因为只要宽度设定,margin 就无法改变元素尺寸, 这和 padding 是不一样的。
.father {
width: 300px;
margin: 0 -20px;
}
// 但是,下面.son 元素的宽度就是 340 像素了,尺寸通过负值设置变大了,因为此时的宽度表现是“充 分利用可用空间”
//<div class="father"><div class="son"></div></div>
.father { width: 300px; } .son { margin: 0 -20px; }
// 需求:列表块两端对齐,一行显示 3 个,中间有 2 个 20 像素的间隙,可以通过给父容器添加 margin 属性,增加容器的可用宽度来实现
ul {
margin-right: -20px;
}
ul > li {
float: left;
width: 100px;
margin-right: 20px;
}
- 对于外部尺寸,margin 属性的影响则更为广泛,只要元素具有块状特性,无论有没有 设置 width/height,无论是水平方向还是垂直方向,即使发生了 margin 合并,margin 对外 部尺寸都着着实实发生了影响。(推荐使用 table-cell 实现等高布局)。
-
上述 margin 对尺寸的影响是针对具有块状特性的元素而言的,对于纯内联元素则不适用。 和 padding 不同,内联元素垂直方向的 margin 是没有任何影响的,既不会影响外部尺寸, 也不会影响内部尺寸,有种石沉大海的感觉。对于水平方向,由于内联元素宽度表现为“包裹性”,也不会影响内部尺寸。
-
和 padding 属性一样,margin 的百分比值无论是水平方向还是垂直方向都是相对于宽度计算的。和 padding 不同,元素设置 margin 在垂直方向上无法改变元素自身的内部尺寸,往往需要父元素作为载体,此外,由于 margin 合并的存在,垂直方向往往需要双倍尺寸才能和 padding 表现一致。
- margin 合并: 1)块级元素,但不包括浮动和绝对定位元素,尽管浮动和绝对定位可以让元素块状化。 (2)只发生在垂直方向(不考虑 writing-mode 的情况下)。
- margin 合并的 3 种场景: 1)相邻兄弟元素 margin 合并。这是 margin 合并中最常见、最基本的; (2)父级和第一个/最后一个子元素。(3)空块级元素的 margin 合并。
对于 margin-top 合并,可以进行如下操作(满足一个条件即可): • 父元素设置为块状格式化上下文元素; • 父元素设置 border-top 值; • 父元素设置 padding-top 值; • 父元素和第一个子元素之间添加内联元素进行分隔。 对于 margin-bottom 合并,可以进行如下操作(满足一个条件即可): • 父元素设置为块状格式化上下文元素; • 父元素设置 border-bottom 值; • 父元素设置 padding-bottom 值; • 父元素和最后一个子元素之间添加内联元素进行分隔; • 父元素设置 height、min-height 或 max-height。
- margin:auto 的填充规则如下: (1)如果一侧定值,一侧 auto,则 auto 为剩余空间大小(注意只设置一侧的时候,由于margin 的初始值大小是 0,相当于左或者右对齐)。 (2)如果两侧均是 auto,则平分剩余空间。
// 为什么明明 容器定高、元素定高,margin:auto 却无法垂直居中?
.father {
height: 200px;
}
.son {
height: 100px;
margin: auto;
}
// 原因在于触发 margin:auto 计算有一个前提条件,就是 width 或 height 为 auto 时, 元素是具有对应方向的自动填充特性的。比方说这里,假如说把.son 元素的 height:100px 去掉,.son 的高度会自动和父元素等高变成 200px 吗?显然不会!因此无法触发 margin:auto 计算,故而无法垂直居中。
// 让水平垂直同时居中的方法--绝对定位元素的 margin:auto 居中
.father {
width: 300px; height:150px;
position: relative;
}
.son {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
width: 200px; height: 100px;
margin: auto;
}
// 绝对定位下的 margin:auto 居中的块级 元素垂直居中对齐方式,比 top:50%然后 margin 负一半元素高度的方法要好使得多。
-
display 计算值 inline 的非替换元素的垂直 margin 是无效的,虽然规范提到有 渲染,但浏览器表现却未寻得一点踪迹,这和 padding 是有明显区别的。对于内联替换元素,垂直 margin 有效,并且没有 margin 合并的问题,所以图片永远不会发生 margin 合并。
- border-width 却不支持百分比; border属性的默认宽度大小是 medium,也就是 3px; border-color 有一个很重要也很实用的特性,就是“border-color 默认颜色就是 color 色值”。
- border 与透明边框技巧:
// 1.右下方 background 定位的技巧 .box { border-right: 50px solid transparent; background-position: 100% 50%; } // 2.优雅地增加点击区域大小 .icon-clear { width: 16px; height: 16px; border: 11px solid transparent; } // 3.三角等图形绘制 div { width: 0; border-width: 10px 20px; border-style: solid; border-color: #f30 transparent transparent; }
内联元素与流
- 字母 x 的下边缘(线)就是我们的基线;
- ex 是 CSS 中的一个相对单位,指的是小写字母 x 的高度,没错,就是指 x-height。ex 的价值就在其副业上—-不受字体和字号影响的内联元素的垂直居中对齐 效果。
.icon-arrow { display: inline-block; width: 20px; height: 1ex; background: url(/images/5/arrow.svg) no-repeat center/20px 20px; }
- 对于非替换元素的纯内联元素,其可视高度完全由 line-height 决定。注意这里的措辞—- “完全”,什么 padding、border 属性对可视高度是没有任何影响的,这也是我们平常 口中的“盒模型”约定俗成说的是块级元素的原因。
- line-height 可以影响替换元素(如图片的高度)吗?答案是,不可以!
- 对于块级元素,line-height 对其本身是没有任何作用的,我们平时改变 line-height, 块级元素的高度跟着变化实际上是通过改变块级元素里面内联级别元素占据的高度实现的。
- 为什么 line-height 可以让内联元素近似“垂直居中”: 行高可以实现“垂直居中”原因在于CSS 中“行距的上下等分机制”,如果行距的添加规则是在文字的上方或者下方,则行高是无法让文字垂直居中的。说“近似”是因为文字字形的垂直中线位置普遍要比真正的“行框盒子”的垂直中线位置低。
- 多行文本或者替换元素的垂直居中实现原理和单行文本就不一样了,需要 line-height 属性的好朋友 vertical-align 属性帮助才可以。
// <div class="box"> // <div class="content">基于行高实现的...</div> </div> .box { line-height: 120px; background-color: #f0f3f9; } .content { display: inline-block; line-height: 20px; margin: 0 20px; vertical-align: middle; }
- 凡是 line-height 起作用的地方 vertical-align 也一定起作用,只是很多时候, vertical-align 默默地在背后起作用,你没有感觉到而已。很多人都有这样一个错误的认知,认为对于单行文本,只要行高设置多少,其占据高度就是多少。比方说,对于下面非常简单的 CSS 和 HTML 代码:
// <div class="box"><span>文字</span> </div> .box { line-height: 32px; } .box > span { font-size: 24px; } // .box 元素的高度是多少? // 很多人一定认为是 32px:因为没有设置 height 等属性,高度就由 line-height 决定,与 font-size 无关,所以这里明摆着最终高度就是 32px。但是事实上,高度并不是 32px,而是要大那么几像素。之所以最终.box 元素的高度并不等于 line-height,就是因为行高的朋友属性 vertical-align 在背后默默地下了黑手
- vertical-align 属性值分为以下 4 类: 1) 线类,如 baseline(默认值)、top、middle、bottom; 2)文本类,如 text-top、text-bottom; 3)上标下标类,如 sub、super; 4)数值百分比类,如 20px、2em、20%等。
- vertical-align 的默认值是 baseline,即基线对齐,而基线的定义是字母 x 的 下边缘。因此,内联元素默认都是沿着字母 x 的下边缘对齐的。对于图片等替换元素,往往使 用元素本身的下边缘作为基线。
-
vertical-align 的属性值支持数值,也支持负值,其兼容性非常好,可以精确控制内联元素的垂直对齐位置。 vertical-align 的百分比值是相对于 line-height 计算的。
- vertical-align 起作用是有前提条件的: vertical-align 属性只能作用在 display 计算值为 inline、inline- block,inline-table 或 table-cell 的元素上。因此,默认情况下,span、strong、 em等内联元素,img、button、input等替换元素,非 HTML 规范的自定义标签 元素,以及 td 单元格,都是支持 vertical-align 属性的,其他块级元素则不支持。
// <div class="box"><img src="1.jpg"></div>
.box {
height: 128px;
line-height: 128px; /*关键CSS属性*/
}
.box > img {
height: 96px;
vertical-align: middle;
}
// 这种情况看上去是 vertical-align:middle 没起作用,实际上,vertical-align 是在努力地渲染的,只是行框盒子前面的“幽灵空白节点”高度太小,如果我们通过设置一个足够大的行高让“幽灵空白节点”高度足够,就会看到 vertical-align:middle 起作用了
// 告诉你,那是因为对 table-cell 元素而言,vertical-align 起作用的是 table-cell 元素自身
// <div class="cell"><img src="1.jpg"></div>
.cell {
height: 128px;
display: table-cell;
vertical-align: middle;
}
.cell > img {
height: 96px;
}
- 第8点中: vertical-align对齐导致容器高度不等于行高的现象解释
// <div class="box"><span>文字</span> </div> .box { line-height: 32px; } .box > span { font-size: 24px; } // <span>标签前面实际上有一个看不见的类似 字符的“幽灵空白节点”; 由于都受 line- height:32px 影响,因此,这两个“内联盒子”的高度都是 32px。下面关键的来了,对字符 而言,font-size 越大字符的基线位置越往下,因为文字默认全部都是基线对齐,所以当字 号大小不一样的两个文字在一起的时候,彼此就会发生上下位移,如果位移距离足够大,就会 超过行高的限制,而导致出现意料之外的高度; // 知道了问题发生的原因,那问题就很好解决了。我们可以让“幽灵空白节点”和后面<span> 元素字号一样大,或者改变垂直对齐方式,如顶部对齐
- 常见的图片底部留有间隙的问题—现象是这样的:任意一个块级元素,里面若有图片,则块级元素高度基本上都要比图片的高度高。
当 line-height 计算值是 20px,而 font-size 只有 14px,因此,字母 x(幽灵空白节点) 往下一定 有至少 3px 的半行间距(具体大小与字体有关),而图片作为替换元素其基线是自身的下边缘。 根据定义,默认和基线(也就是这里字母 x 的下边缘)对齐,字母 x 往下的行高产生的多余的 间隙就嫁祸到图片下面,让人以为是图片产生的间隙,实际上,是“幽灵空白节点”、 line-height 和 vertical-align 属性共同作用的结果。
- vertical-align 属性的默认值 baseline 在文本之类的内联元素那里就是字符 x 的下边缘,对于替换元素则是替换元素的下边缘。但是,如果是 inline-block 元素,则规则要 复杂了:一个 inline-block 元素,如果里面没有内联元素,或者 overflow 不是 visible, 则该元素的基线就是其 margin 底边缘;否则其基线就是元素里面最后一行内联元素的基线。
// 最佳图标实践 CSS
.icon {
display: inline-block;
width: 20px; height: 20px;
background: url(sprite.png) no-repeat;
white-space: nowrap;
letter-spacing: -1em;
text-indent: -999em;
}
.icon:before {
content: '\3000';
}
/* 具体图标 */
.icon-xxx {
background-position: 0 -20px;
}
// 使用纯 CSS 实现 大小不固定的弹框永远居中的效果
// <div class="container"><div class="dialog"></dialog></div>
.container {
position: fixed;
top: 0; right: 0; bottom: 0; left: 0;
background-color: rgba(0,0,0,.5);
text-align: center;
font-size: 0;
white-space: nowrap;
overflow: auto;
}
.container:after {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.dialog {
display: inline-block;
vertical-align: middle;
text-align: left;
font-size: 14px;
white-space: normal;
}
流的破坏与保护
- float 都有哪些有意思的特性呢?具体如下: 包裹性; 块状化并格式化上下文; 破坏文档流; 没有任何 margin 合并;
- clear 属性只有块级元素才有效的,而::after 等伪元素默认都是内联水平,这就是借助伪元素清除浮动影响时需要设置 display 属性值的原因。
- BFC全称为block formatting context,中文为“块级格式化上下文”。如果一个元素具有 BFC,内部子元素再怎么翻江倒海、翻云覆雨,都不会影响外部的元素。所以,BFC 元素是不可能发生 margin 重叠的,因为 margin 重叠是会影响外面的元素的;BFC 元素也可以用来清除浮动的影响,因为如果不清除,子元素 浮动则父元素高度塌陷,必然会影响后面元素布局和定位,这显然有违 BFC 元素的子元素不会 影响外部元素的设定。
- 那什么时候会触发 BFC 呢? 常见的情况如下:
- html根元素;
- float 的值不为 none;
- overflow 的值为 auto、scroll 或 hidden;
- display 的值为 table-cell、table-caption 和 inline-block 中的任何一个;
- position 的值不为 relative 和 static。
- 单行文字溢出点点点效果
.ell { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } // 对-webkit-私有前缀支持良好的浏览器还可以实现多行文字打点效果,但是却无 须依赖 overflow:hidden .ell-rows-2 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
- 当 absolute 和 float 同时存在的时候,float 属性是无任何效果的。因此,没有任何理由 absolute 和 float 同时使用。
- 包含块(containing block)这个概念实际上大家一直都有接触,就是元素用来计算和定位 的一个框:
- (1)根元素(很多场景下可以看成是html)被称为“初始包含块”,其尺寸等同于浏览 器可视窗口的大小。
- (2)对于其他元素,如果该元素的 position 是 relative 或者 static,则“包含块” 由其最近的块容器祖先盒的 content box 边界形成。
- (3)如果元素 position:fixed,则“包含块”是“初始包含块”。
- (4)如果元素 position:absolute,则“包含块”由最近的 position 不为 static 的祖先元素建立。边界是 padding box 而不是 content box。
- absolute 定位效果实现完全不需要父元素设置 position 为 relative 或其他什么属性就可以实现,我把这种没有设置 left/top/ right/bottom 属性值的绝对定位称为“无依赖绝对定位”。很多场景下,“无依赖绝对定位”要比使用 left/top 之类属性定位实用和强大很多,因 为其除了代码更简洁外,还有一个很棒的特性,就是“相对定位特性”。明明 absolute 是‘绝对定位’的意思,怎么又扯到‘相对定位特性’了呢?没错,“无 依赖绝对定位”本质上就是“相对定位”,仅仅是不占据 CSS 流的尺寸空间而已。
// <span class="icon-x"><i class="icon-warn"></i>邮箱格式不准确</span> .icon-x { line-height: 20px; padding-left: 20px; } .icon-warn { position: absolute; margin-left: -20px; width: 20px; height: 20px; background: url(warn.png) no-repeat center; }
- 如果 overflow 不是定位元素,同时绝对定位元素和 overflow 容器之间也没有定位元素,则 overflow 无法对 absolute 元素进行剪裁。
- clip 属性要想起作用,元素必须是绝对定位或者固定定位,也就是 position 属性值必须是 absolute 或者 fixed。
.clip { position: absolute; clip: rect(0 0 0 0); }
- 当 absolute 遇到 left/top/right/bottom 属性的时候,absolute 元素才真正变成 绝对定位元素。当一个绝对定位元素,其对立定位方向属性同时有具体定位数值的时候,流体特性就发生了。
-
当绝对定位元素处于流体状态的时候,各个盒模型相关属性的解析和普通流体元素都是一模一样的,margin 负值可以让元素的尺寸更大,并且可以使用 margin:auto 让绝对定位元 素保持居中。
- relative 的定位有两大特性:一是相对自身;二是无侵入。relative 的定位还有另外两点值得一提:相对定位元素的 left/top/right/bottom 的百分比值是相对于包含块计算的,而不是自身。注意,虽然定位位移是相对自身,但是百分 比值的计算值不是。
当相对定位元素同时应用对立方向定位值的时候,也就是 top/bottom 和 left/right 同时使用的时候,其表现和绝对定位差异很大。绝对定位是尺寸拉伸,保持流体特性,但是相 对定位却是“你死我活”的表现,也就是说,只有一个方向的定位属性会起作用。而孰强孰弱 则是与文档流的顺序有关的,默认的文档流是自上而下、从左往右,因此 top/bottom 同时使 用的时候,bottom 被干掉;left/right 同时使用的时候,right 毙命。
- relative 的最小化影响原则: 1)尽量不使用 relative,如果想定位某些元素,看看能否使用“无依赖的绝对定位”; (2)如果场景受限,一定要使用 relative,则该 relative 务必最小化。
CSS 世界的层叠规则
- 层叠上下文的创建: (1)天生派:页面根元素天生具有层叠上下文,称为根层叠上下文。 (2)正统派:z-index 值为数值的定位元素的传统“层叠上下文”。 (3)扩招派:其他 CSS3 属性。
- 对于 position 值为 relative/absolute 以及 Firefox/IE 浏览器(不包括 Chrome 浏览 器)下含有 position:fixed 声明的定位元素,当其 z-index 值不是 auto 的时候,会创建 层叠上下文。
<div style="position:relative; z-index:auto;">
<!-- 美女 -->
<img src="1.jpg" style="position:absolute; z-index:2;">
</div>
<div style="position:relative; z-index:auto;">
<!-- 美景 -->
<img src="2.jpg" style="position:relative; z-index:1;">
</div>
<!-- z-index: auto 所在的<div>元素是一个普通定位元素,于是,里面的两个<img>元 素的层叠比较就不受父级的影响,两者直接套用“层叠黄金准则”。这里, 两个<img>元素有着明显不一的 z-index 值,因此遵循“谁大谁上”的准 则,于是,z-index 为 2 的那个“美女”就显示在 z-index 为 1 的“美 景”上面了。 -->
<div style="position:relative; z-index:0;">
<!-- 美女 -->
<img src="1.jpg" style="position:absolute; z-index:2;">
</div>
<div style="position:relative; z-index:0;">
<!-- 美景 -->
<img src="2.jpg" style="position:relative; z-index:1;">
</div>
<!-- 而 z-index 一旦变成数值,哪怕是 0,就会创建一个层叠上下文。此时,层叠规则就发 生了变化。层叠上下文的特性里面最后一条是自成体系。两个<img>元素的层叠顺序比较变成 了优先比较其父级层叠上下文元素的层叠顺序。这里,由于外面的两个<div>元素都是 z-index:0,两者层叠顺序一样大,此时遵循“层叠黄金准则”的另外一个准则“后来居上”, 根据在 DOM 文档流中的位置决定谁在上面,于是,位于后面的“美景”就自然而然显示在“美 女”上面了。对,没错,<img>元素上的 z-index 没起作用! -->
- CSS3 新世界的出现除了带来了新属性,还对过去的很多规则发出了挑战,其中对层叠上 下文规则的影响显得特别突出。
- (1)元素为 flex 布局元素(父元素 display:flex 或 inline-flex),同时 z-index 值不是 auto。
- (2)元素的 opacity 值不是 1。
- (3)元素的 transform 值不是 none。
- (4)元素 mix-blend-mode 值不是 normal。
- (5)元素的 filter 值不是 none。
- (6)元素的 isolation 值是 isolate。
- (7)元素的 will-change 属性值为上面 2~6 的任意一个(如 will-change:opacity、 will-chang:transform 等)。
- (8)元素的-webkit-overflow-scrolling 设为 touch。
- 层叠上下文与层叠顺序: 层叠上下文background/border => 负z-index => block块状水平盒子 => float 浮动盒子 => inline水平盒子 => z-index为auto或看成z-index为0,不依赖z-index的层叠上下文 => 正z-index
这下大家应该知道为什么定位元素会层叠在普通元素的上面了吧?其根本原因就是:元素 一旦成为定位元素,其 z-index 就会自动生效,此时其 z-index 就是默认的 auto,也就是 0 级别,根据上面的层叠顺序表,就会覆盖 inline 或 block 或 float 元素。而不支持 z-index 的层叠上下文元素天然是 z-index:auto 级别,也就意味着,层叠上下文元素和定位元素是 一个层叠顺序的,于是当它们发生层叠的时候,遵循的是“后来居上”准则。
- z-index 负值深入理解: 首先明确一点,z-index 是支持负值的; 其次,依据上面的层叠顺序,明确z-index 负值元素的层级是在层叠上下文元素上面、block 元素的下面,也就是 z-index 虽然名为负数层级,但依然无法突破当前层叠上下 文所包裹的小世界。
// <div class="box"><img src="1.jpg"></div>
.box {
background-color: blue;
}
.box > img {
position: relative;
z-index: -1;
right: -50px;
}
// 此时.box是一个普普通通的元素,图片元素所在的层叠上下文元素一定是.box的某个祖先元素,图片是 z-index 负值元素,.box 是 block 元素,也就是图片应该在.box 元素的后面显示,因此,图片会被.box 元素的蓝色背景覆盖。
.box {
background-color: blue;
transform: scale(1); // 使其具有层叠上下文
}
.box > img {
position: relative;
z-index: -1;
right: -50px;
}
// 此时由于 z-index 负值在层叠上下文元素的背景色之上,也就是说,这里 z-index 是负值的图片元 素应该在.box 元素的上面。
- 务必牢记的层叠准则:(1)谁大谁上:当具有明显的层叠水平标识的时候,如生效的 z-index 属性值,在同一 个层叠上下文领域,层叠水平值大的那一个覆盖小的那一个。 (2)后来居上:当元素的层叠水平一致、层叠顺序相同的时候,在 DOM 流中处于后面的元素会覆盖前面的元素。
- 对于非浮层元素,避免设置 z-index 值,z-index 值没有任何道理需 要超过 2。由于 z-index 不能超过 2,因此,我称其为“不犯二”准则。(调整结构或者relative 的最小化原则)
强大的文本处理能力
- 在 CSS 中,1em 的计算值等同于当前元素所在的 font-size 计算值,可以将 其想象成当前元素中(如果有)汉字的高度。
- rem,即 root em,顾名思义,就是根元素 em 大小。em 相对于当前元素,rem 相对于根元素,本质差别在于当前元素是多变的,根元素是固定的,也就是说,如果使用 rem,我们的计算值不会受当前元素 font-size 大小的影响。
- 等宽字体的实践价值:
// HTML: https://demo.cssworld.cn/8/2-1.php
/*
<select class="monospaced">
<option value="solid" selected>———————</option>
<option value="dashed">-------</option>
<option value="dotted">·······</option>
</select>
<div id="border" class="border"></div>
*/
// CSS:
.monospaced {
width: 110px;
font-family: Consolas, Monaco, monospace;
font-size: 14px;
letter-spacing: -.2px;
}
.border {
width: 120px; height: 40px;
border: 10px solid #cd0000;
margin: 30px auto 10px;
}
- @font face 的本质是变量
@font-face {
font-family: ICON;
src: url('icon.eot');
src: local('☺'),
url('icon.woff2') format("woff2"),
url('icon.woff') format("woff"),
url('icon.ttf');
}
// src 表示引入的字体资源可以是系统字体,也可以是外链字体。如果是使用系统安装字体, 则使用 local()功能符;如果是使用外链字体,则使用 url()功能符。由于 local()功能符 IE9 及其以上版本浏览器才支持
// format()功能符的作用是让浏览器提前知道字体的格式,以决定是否需要加载这个字体
// 不同的 font-weight 会加载不同的图标字体,然后就能根据具体的场景细化我们的图标显示细节。(font-style功能类似)
@font-face {
font-family: ICON;
src: url(icon-large.eot);
src: local("☺"),
url(icon-large.woff);
font-weight: 700;
}
@font-face {
font-family: ICON;
src: url(icon-medium.eot);
src: local("☺"),
url(icon-medium.woff);
font-weight: 400;
}
@font-face {
font-family: ICON;
src: url(icon-small.eot);
src: local("☺"),
url(icon-small.woff);
font-weight: 100;
- text-indent用得比较多的是 负值隐藏文本内容,负值缩进在部分浏览器下会影响元素的 outline 区域,通常需要 再设置 overflow:hidden。
- word-break:break-all 的作用是所有的都换行,毫不留情,一点儿空 隙都不放过,而word-wrap:break-word 则带有怜悯之心,如果这一行文字有可以换 行的点,如空格或 CJK(中文/日文/韩文)之类的,就不打英文单词或字符的主意了,在 这些换行点换行,至于对不对齐、好不好看则不关心,因此,很容易出现一片一片空白区域的情况。
- text-align 与元素对齐: justify属性
元素的装饰与美化
-
隐藏元素的 background-image 到底加不加载呢? —> 一个元素如果 display 计算值为 none,在 IE 浏览器下(IE8~IE11,更 高版本不确定)依然会发送图片请求,Firefox 浏览器不会,至于 Chrome 和 Safari 浏览器则似乎更加智能一点:如果隐藏元素同时又设置了 background-image,则图片依然会去加载; 如果是父元素的 display 计算值为 none,则背景图不会请求,此时浏览器或许放心地认为这个背景图暂时是不会使用的。
-
与众不同的 background-position 百分比计算方式:
positionX = (容器的宽度 - 图片的宽度) * percentX;
positionY = (容器的高度 - 图片的高度) * percentY;
元素的显示与隐藏/用户界面样式
-
visibility 的继承性: 父元素设置 visibility:hidden,子元素也 会看不见,究其原因是继承性,子元素继承了 visibility:hidden,但是,如果子元素设置 了 visibility:visible,则子元素又会显示出来。这个和 display 隐藏有着质的区别。
-
万万不可在全局设置 outline:0 none:
// <input id="t" type="submit"><label class="btn" for="t">提交</label>
[type="submit"] {
position: absolute;
clip: rect(0 0 0 0);
}
.btn {
display: inline-block;
padding: 2px 12px;
background-color: #cd0000;
color: #fff;
font-size: 14px;
cursor: pointer;
}
:focus + label.btn {
outline: 1px dotted Highlight;
outline: 5px auto -webkit-focus-ring-color;
}
- 真正的不占据空间的 outline 及其应用
// 头像剪裁的矩形镂空效果
.crop {
overflow: hidden;
}
.crop > .crop-area {
width: 80px; height: 80px;
outline: 256px solid rgba(0,0,0,.5);
cursor: move;
}
// 自动填满屏幕剩余空间的应用技巧
// <p>Designed & Powered by zhangxinxu</p><div class="footer"></div>
.footer {
height: 50px;
}
.footer > p {
position: absolute;
left: 0; right: 0;
text-align: center;
padding: 15px 0;
background-color: #a0b3d6;
outline: 9999px solid #a0b3d6;
clip: rect(0 9999px 9999px 0);
}