文章提炼拓展于《css世界》中的第一章~第五章内容,若有侵权,请联系作者删除
一 : 宽度判断
案例一(图片最终的宽度是多少)
html
img { max-width: 256px; }
<img src="1.jpg" style="width:480px!important;">
知识点 :
!important比直接在元素的 style 属性中设置 CSS 声明还要高
max-width 会覆盖!important width
所以图片最后呈现的宽度最终表现为 256px
案例二(container最终的宽度是多少)
css
.container {
min-width: 1400px;
max-width: 1200px;
}
知识点 :
当min-width和max-width冲突的时,min-width会覆盖max-width
所以container 元素最终表现为 1400px
案例三(son最终的宽度是多少)
html
.father {
width: 400px;
height: 200px;
}
.son {
padding: 50%;
}
<div class='father'>
<div class='son'></div>
</div>
知识点 :
padding 百分比值无论是水平方向还是垂直方向均是相对于宽度计算的
所以,padding: 50%就相当于padding: 200px,也就是一个宽度为400px正方形,同样,如果设置 padding: 25% 50%; 那son就是一个宽高比为2:1的长方形
一个固定5:1头图的例子
同样,margin的百分比值与padding一样,也是相对于宽度计算的
二 : 高度判断
案例一(father的高度是多少)
html
.father { line-height: 30px; }
.son { line-height: 10px; }
<div class="father">
<div class="son">阿巴阿巴</div>
</div>
-----------------------------------------
.father { line-height: 30px; }
.son { line-height: 10px; }
<div class="father">
<span class="son">阿巴阿巴</span>
</div>
-----------------------------------------
.father { line-height: 10px; }
.son { line-height: 30px; }
<div class="father">
<span class="son">阿巴阿巴</span>
</div>
-----------------------------------------
.father { line-height: 10px; }
.son { line-height: 30px; }
<span class="father">
<div class="son">阿巴阿巴</div>
</span>
大家可以先简单思考一下
首先先揭晓一下上面四段代码中father的高度吧,分别是10px,30px,30px,30px
注意到的同学一定已经注意到了,除了1、4;2、3段代码的html其实是一样的,都是div里面包了一个span,只是把他们的行高互换了一下,但为什么最后father的高度竟然是相同的呢?
这就要提到css中的假想盒子,幽灵空白节点了(W3提及)
那么现在,我们可以给它下定义了 :
"幽灵空白节点"是内联盒模型中非常重要的一个概念,具体指的是:在 HTML5 文档声明中,内联元素 的所有解析和渲染表现就如同每个行框盒子的前面有一个"空白节点"一样。这个"空白节点"永远透明 ,不占据任何宽度,看不见也无法通过脚本获取,就好像幽灵一样,但又确确实实地存在,表现如同文本节点一样
现在回到上面的几个例子中再看
第一段代码不用多说,第二个div的行高覆盖了它父元素div的line-height,同时父div中也没有内容,所以最终的高度就等于子div的高度了;同样的,第四段代码也是相同的逻辑
第二段代码中,理论上子span的line-height只有10px,同时父div中又没有内容,那么最终father的高度应该是子span的高度才对;但是我们忽略了这里的幽灵空白节点,他会继承father的line-height: 30px,使得最终father的高度是30px
在css中,这种现象也有一个学名,叫 : 内联元素的"大值特性" : 无论内联元素 line-height 如何设置,最终父级元素的高度都是由数值大的那个 line-height 决定的
当然,还有另外的例子来更加形象的说明,幽灵空白节点真实存在
来看这段代码
html
div { background-color: #cd0000; }
span { display: inline-block; }
<div><span></span></div>
我们可以从实际的效果发现,div最终是有高度的
让我们再来总结一下,"幽灵空白节点"实际上也是一个盒子,不过是个假想盒,名叫"strut",中文直译为"支柱",是一个存在于每个"行框盒子"前面,同时具有该元素的字体和行高属性 的 0 宽度的内联盒。
案例二
让我们继续探究,这里father的高度是否是32px?
html
.father { line-height: 32px; }
.son { font-size: 24px; }
<div class="father">
<span class="son">阿巴阿巴</span>
</div>
很遗憾的是,这里的高度仍然不是我们猜想中的32px,而是要比32px大几个像素。为什么会出现这样的情况呢?
要想解答这个问题,我们要知道css中的两个概念 : 基线和行距
基线其实说的也就是我们vertical-align的默认属性值baseline
css中有一个概念叫做x-height,指的就是字母x的高度,而字母x的下边缘线就是我们的基线,在这里附一张图来说明一下
而为什么我们要提到x-height,因为vertical-align: middle指的是1/2的x-height高度
行距就是两条基线之间的距离,同时对于我们的元素,还有半行距,顾名思义就是一半的行距,半行距体现出了行距的上下等分机制(设置line-height可以让其中内联元素近似垂直居中的原因之一)
行距 = line-height - font-size(当计算出小数时,如果标注的是文字的上边距,则向下取整,如果是下边距,则向上取整)
那么现在,我们就可以来回答上面的问题,为什么高度不是32px
细心的同学一定发现了,这里的span设置了font-size,而我们知道,的display值是inline,他的前面有一个看不见的"幽灵空白节点",这个幽灵空白节点会继承father的行高和字体属性
这个空的假想盒与span都受line-height:32px的影响,因此,这两个盒子的高度都是32px,对字符而言,font-size越大的字符,基线的位置越往下
而又因为文字默认全部都是基线对齐,所以,当字号大小不一样的两个文字在一起时,彼此就会发生上下位移(注意,此刻位移时,行距的上下等分机制仍然生效),如果位移的距离足够大,就会超过行高的限制,而导致意料之外的高度
核心 : 基线对齐(默认是baseline),元素位移,导致总高度增加
那么如何解决这个问题呢?在不考虑flex布局的情况下,有以下几种方法 :
- 让"幽灵空白节点"的字号与后面元素的字号一样大
- 改变垂直对齐方式,如顶部对齐、底部对齐
这一案例同样说明了 : 凡是 line-height 起作用的地方 ,vertical-align 也一定起作用
让我们再回过头来看一下
1.为什么说line-height只能让内联元素近似的垂直居中,其实,是由于文字字形的垂直中线位置普遍要比真正的"行框盒子"的垂直中线位置低(譬如我们拿现在用得比较多的微软雅黑)
(什么!我听到有人说不知道行框盒子,传送)
2.上面提到了vertical-align: middle指的是1/2的x-height高度,那么设置vertical-align: middle是否是绝对意义上的垂直居中呢?
恰恰和line-height一样,vertical-align: middle通用指的是近似的垂直居中,原因是基本上所有的字体中,字符 x 的位置都是偏下一点儿的,font-size 越大偏移越明显,这才导致默认状态下的 vertial-align:middle 实现的都是"近似垂直居中"。
我们可以通过这个示例来直观的感受到近似垂直居中(图片上的红线代表图片的垂直中心位置,绿线代表容器的垂直中心位置)
此示例可以通过设置幽灵空白节点的font-size为0达到图片的垂直居中
其他
说了这么多,我们现在来正式的认识一下line-height与vertical-align这两个属性吧
line-height
line-height 的默认值是 normal,还支持数值、百分比值以及长度值
- 数值(font-size * 倍数)
- 百分比值(百分比值 * font-size)
- 长度值(20px,20em)
三种的区别(继承)
如果使用数值 作为 line-height 的属性值,那么所有的子元素继承的都是这个值;
但是,如果使用百分比值 或者长度值 作为属性值,那么所有的子元素继承的是最终的计算值。
(对于块级元素,line-height 对其本身是没有任何作用的,我们平时改变 line-height,块级元素的高度跟着变化实际上是通过改变块级元素里面内联级别元素占据的高度实现的。)
这里引申出一个点,line-height 的默认值 normal实际上是一个和normal 实际上是一个和font-family 有着密切关联的变量值,不同浏览器解析出来的数值有细微差别,同时,不同操作系统的默认字体也不一样。也就是说,就是不同系统不同浏览器的默认 line-height 都是有差异的
那么在实际开发的时候,对line-height的默认值应该重置为什么呢?
作者的观点是这样的 :
如果我们做的是一个重图文内容展示的网页或者网站,如博客、论坛、公众号之类的,那一定要使用数值作为单位,考虑到文章阅读的舒适度,line-height 值可以设置在 1.6~1.8。
如果是一个偏重布局结构精致的网站,使用长度值 或者数值都是可以的,因为,第一,我们的目的是为了兼容;第二,无论使用哪种类型值,都存在需要局部重置的场景。
vertical-align
vertical-align属性值
- 线类(baseline、top、middle、bottom)
- 文本类(text-top、text-bottom)
- 上下标(sub、super)
- 数值百分比(20px、-10px、20%)相对于基线位置计算,正值往上偏移,负值往下偏移(从这一点来看,vertical-align:baseline等同于vertical-align:0)
(这里的百分比是相对于谁的计算值计算的呢?)
vertical-align作用的前提
只能作用于内联元素和display是table-cell的元素(inline、inline-block、inline-table、inline-flex、table-cell)
注意,这里的display指的是最后的计算值
深入理解vertical-align: baseline
vertical-align 属性的默认值 baseline 在文本之类的内联元素那里就是字符 x 的下边缘,对于替换元素则是替换元素的下边缘
但是,如果是 inline-block 元素,则规则要复杂
一个 inline-block 元素,如果里面没有内联元素,或者 overflow 不是 visible ,则该元素的基线就是其 margin 底边缘 ;否则其基线就是元素里面最后一行内联元素的基线。
三 : 如何不在内容中直接编写顺序号来实现目录效果
先康康是怎么实现的
下面来介绍其中的一些关键属性、方法
- counter-reset : 给定义
- counter-increment : 定规则
- counter() / counters() : 显示计数
1.counter-reset(普照源)
主要作用就是给计数器起名字,顺便还可以设置个默认值,默认是0;同时还可以给多个计数器同时命名
2.counter-increment
指定普照源
定义每次计数器变化的值,即步长,默认值为1,同时值还可以是 none 或者 inherit
css
counter-increment: counterone countertwo;
counter-increment: counter 2
counter-increment: none
同时,还有一套普照规则 : 普照源(counter-reset)唯一,每普照(counter-increment)一次,普照源增加一次计数值。
此示例同时说明了计数器的数值变化遵循 HTML 渲染顺序 ,遇到一个 increment 计数器就变化,什么时候counter 输出就输出此时的计数值。
3.counter() / counters()
scss
// 这里的name就是counter-reset的名称
counter(name)
// style支持的关机键字值同 list-style-type 支持的那些值 : lower-roman,cjk-decimal... 当然,如果设置了没有数字意义的style,比如说circle,那么它只会展示一个圆圈
counter(name, style)
而counters()可以说是嵌套计数的代名词,比如1包含了1.1,1.1包含了1.1.1 ......
scss
// 这里的name同样还是counter-reset的名称
// 而string参数是字符串,表示子序号的链接字符串
counters(name, string);
counters(name, string, style)
要想实现嵌套,必须让每一个列表容器 拥有一个"普照源",通过子辈对父辈的 counter-reset 重置、配合 counters()方法实现计数嵌套效果。
下面来看这段html代码,他的效果是否与上面的案例一致呢?
html
<div class='reset'>
<div class="counter">我是王小二</div>
<div class="reset">
<div class="counter">我是王小二的大儿子</div>
<div class="counter">我是王小二的二儿子</div>
<div class="reset">
<div class="counter">我是王小二的二儿子的大孙子</div>
</div>
<div class="counter">我是王小二的三儿子</div>
...
</div>
注 : 显示 content 计数值的那个 DOM 元素在文档流中的位置一定要在 counter-increment元素的后面,否则是没有计数效果的。
css
.father {
counter-reset: demo 3;
font-size: 32px;
}
.father::before {
content: counter(demo);
}
.son:before,
.son:after {
counter-increment: demo;
}
<div class="father">
<div class="son"></div>
</div>
无计数效果,仍显示3
小结
优先级 :
arduino
!important比直接在元素的 style 属性中设置 CSS 声明还要高
max-width 会覆盖!important width
当min-width和max-width冲突的时,min-width会覆盖max-width
相对于xxx计算
css
padding/margin 百分比值无论是水平方向还是垂直方向均是相对于宽度计算的
line-height 百分比值是相对于 font-size计算的
vertical-align 百分比值是相对于 line-height计算的
幽灵空白节点
markdown
实际上也是一个盒子,不过是个假想盒,名叫"strut",中文直译为"支柱",是一个存在于每个"行框盒子"前面,同时具有该元素的**字体和行高属性**的 **0 宽度**的内联盒。
line-height & vertical-align
arduino
凡是 line-height 起作用的地方 ,vertical-align 也一定起作用
line-height与vertical-align: middle都是近似垂直居中
vertical-align只能作用于内联元素和display是table-cell的元素(inline、inline-block、inline-table、table-cell)
content计数器
css
普照源(counter-reset)唯一,每普照(counter-increment)一次,普照源增加一次计数值。