Fork me on GitHub

《CSS世界》阅读笔记

 《CSS世界》这本书感觉可以说是张鑫旭的一本CSS领域的内功心法,阅读这本书其实是为了印证一些自身在CSS学习上的一些东西,所以有了这篇读书笔记,记录一些我不是很清晰的知识点。

  1、伪类选择器:一般指前面有个英文冒号(:)的选择器,如first-child:last-child等。
  2、伪元素选择器:就是有连续两个冒号的选择器,如::first-line::first-letter::before::after等。P.S:单、双冒号都是现在的规范,为了区分伪类和伪元素。IE8仅支持单冒号的伪元素。
  3、后代选择器:选择所有合乎规则的后代元素。用空格连接。
  4、相邻后代选择器:仅选择儿子(一层后代)元素,用>连接。
  5、>、~、+选择器适用于IE7以上版本。
  6、通常把HTML标签分为两种:块级元素和内联元素。
  7、块级元素和display: block不是一回事,但是它们都具备一个基本特征:一个水平流只能单独显示一个元素。
  8、具有换行特性的”块级元素”(笔记7的综合体),可以配合clear属性来清除浮动带来的影响。
  9、实际开发中不会使用display: list-item来配合清除浮动。
   理由①:会出现不必要的项目符号·,但是可以通过list-style: none规避。
   理由②:IE不支持伪元素设置display: list-item,普通元素设置有效。
  10、a标签默认display是inline。
  11、替换元素:根据其标签和属性来决定元素的具体显示内容,即内容可被替换,如input, textarea, select, img, video, object等。它们具备了一些其他特性,如内容的外观不受页面上的CSS影响有自己的尺寸:像video、iframe、canvas等这些默认尺寸为300X150pximg等则是0,表单无明显规则。在很多CSS属性上有自己的一套表现规则:如vertical-align的默认值为baseline,在非替换元素,对应西方字符x的下边缘,而替换元素由于几乎不可能出现字符这种,所以变成了元素的下边缘。替换元素尺寸的计算优先级:CSS样式设置 > HTML内联属性 > 固有。如果发生了只设置了width没有设置height的情景怎么办?最终height = width X 原图高宽比例。
  12、理解样式属性的意义,规避不必要的样式书写,减少性能损耗:
  栗子1:当我们修改a标签成display: block的时候,它已经具备了块级特性,即它本身会有流的自然填充性,它会像流一样自动铺满外部容器空间。但是,如果你设置了宽度,不论是百分比还是固定值,它的流动性就丢失了。见书中提供的width: 100%流破坏和自然流填充对比Demo
  栗子2:*{box-sizing: border-box},这种通配符的属性选择器应当尽量避免,因为比如search类型的搜索框,其默认的box-sizing就是border-box,这种重复赋值就是一种损耗,再比如普通内联元素(非图片等替换元素),box-sizing无论是什么值,对渲染表现都没有影响,同样设置这种就是无意义的赋值。
  13、在本书中,作者将CSS的盒模型分为了”外盒”以及”内盒”,两者对应具有”外部尺寸”以及”内部尺寸”。流的自然填充性就是依赖于外部尺寸的作用。
  14、格式化宽度:该宽度仅出现在position: absoluteposition: fixed情形中,这种情形下,宽度表现为”包裹性”,宽度由内部尺寸决定。但是对于非替换元素,如果left/right,top/bottom这种对向属性同时存在的时候,宽度将会呈现为”格式化宽度”,表现形式就是相对于最近的具有定位特性的祖先元素计算,适应于该包含块的padding box
  15、在本书中作者有提到”宽度分离原则”,文中的解释为CSS中的width属性不与影响宽度的padding/border属性共存,即外层容器单独设置width属性,margin、border、padding利用流动性在内部自适应实现。这种设置的目的在于:使宽度严格按照我们预期的设计图宽度生效,用”人话”来说,width = content-width + padding-width + border-width
  16、当然我们实际使用的时候,提供了box-sizing: border-box,这种设置的效果与笔记15中的宽度分离原则一致。默认情况下是
box-sizing: content-box,即content-width = width+ padding-width + border-width
  17、对height属性,如果父属性height为auto,只要子元素在文档流中,其设定的百分比值会被完全忽略。举一个冗余的为div设置背景的样式。

1
2
3
4
5
div {
width: 100%; /*多余*/
height: 100%; /*无效*/
background: url(bg.jpt);
}

  这样设置的结果就是高度永远为0,实践的结果是百分比高度值要生效,其父级必须有一个可以生效的高度值。规范中如此描述:如果包含的高度没有显示指定(即高度由内容提供),且该内容非绝对定位,则计算值为auto,而auto自然是没办法跟百分比计算的。
  18、根据浏览器渲染顺序,其实按DOM自上而下渲染,可以看出嵌套的样式外部是先固定下来的,所以不存在那种不断根据自适应改变进行无限的宽高变化。
  19、max-widthmax-height的应用场景一定是自适应布局或流体布局中:以一个最常见的适配场景为例,虽然我们现在使用的显示器大多数都是默认1920X1080分辨率的,但是,还是有很多以前的小屏幕分辨率机型,这种可能是古董台式机,也有可能是小屏的笔记本电脑。我自身在工作时,就遇到过笔记本是1600X900分辨率的业务,此时,通过这两个属性就能让宽度在设定的区间内自适应:

1
2
3
4
.container {
min-width: 1600px;
max-width: 1920px;
}

  除此之外,它们的兼容性很好,IE7开始就支持了。
  20、以前我的认知里面!important对样式的权重是最高的,但是像max-width属性如果小于width属性将会直接将其覆盖,如果大于,当然还是以width显示。
  21、同时存在min-widthmax-width的描述,那么最大者生效。
  22、max-widthmax-height的初始值是nonemin-widthmin-height的初始值是auto
  23、max-height的一种应用:任意高度元素的展开收起动画技术传送门。这种是原生的CSS3实现,传统可以用JQ的slideUp()slideDown()。如果元素内容是固定的,即高度固定时,可以用height+overflow: hidden实现。当内容是不确定的时候,想通过动画操作实现从0到内容高度,那么动画结束的样式应该是height: auto,前面我们也记录过,auto没办法和百分比计算。此时我们改用max-height,只需要保证它是一个比展开的内容高度值更大的值即可。那么在动画计算的时候,取的就是height的计算高度。当然这个max-height在文中还有别的限制,因为其在过高的情况下,由于收起恢复到原本高度需要时间,并且在变化过程中区域不会被隐藏,会给人一种延迟感。综上,max-height的取值应当是一个比内容高度高,同时不能高出太多的值,怎么界定太多呢,即视觉残留不能有明显的延迟感。
  24、移动端的CSS3动画支持良好,所以移动端的JS框架都是没有动画模块的(原文,本人没确认过)。
  25、假想盒:规范中有如此描述,每一个行框盒子前,会有一个宽度为0但是具有元素字体和行高属性的内联盒子,我们把这个假想盒称为支柱。注:假想盒仅在HTML5文档声明中出现。
  26、Web开发时,为了提高加载性能以及节约带宽费用,首屏以下的图片会通过滚屏的方式异步加载。常采取的方案是直接使用<img>占位,然后设置样式:

1
2
img { visibility: hidden; }
img[src] { visibility: visible; }

  注,此处的<img>是直接没有src属性。因为即便是src="",在很多浏览器下依然会有请求,并且请求的是当页数据。
  27、内联标签设置宽高样式是无效的,但是可以通过转换display成块级生效。
  28、img标签在Firefox下带src属性时,不会被识别为替换元素,而是普通内联元素,即会有笔记27的问题。
  29、基于伪元素的图片内容区域预处理技术,这个demo我觉得挺有意思的,见传送门。主要的知识点是,::before::after这种伪元素作用在img上是有限制的,对IE来讲,暂不支持这样操作,对CHROME和FF,有额外的附加条件:①不能有src属性(Both),②不能使用content属性生成图片(Chrome),③需要有alt属性并有值(Chrome),④::before伪元素的content值会被无视,::after则无问题(FF)。
  30、作者观点:替换和非替换元素之间只隔一个src属性。对于CHROME而言,它还需要一个alt不为空的值才会成立。对于IE而言,它的确在没有src属性的时候还是表现为替换元素,这是因为IE有个默认的占位替换内容,当src缺失的时候,会默认用这个占位内容去替换(高版本的IE透明化处理了,IE8下会显示)。
  31、作者观点:替换元素和非替换元素之间只隔了一个CSS content属性。见传送门,这是一个EMOJI替换的处理,不过这种hover下只是切换样式,实际上img里的资源在渲染的时候已经下载了,所以不管切不切换显示,保存的都是老图。
  32、替换元素的固有尺寸无法修改,即使用content设置了背景图后,我们无法调整大小,若是在移动端使用这种方法设置背景,原比例的图会导致图片模糊(retina屏幕需要2倍图),推荐使用SVG图,矢量图随意缩放不会失真。
  33、使用content属性生成的文本无法被选中也无法被屏幕阅读设备读取也无法被搜索引擎抓取,即不利于SEO,它只适合用来生成一些无关紧要的内容,如装饰图、序号
  34、:empty伪类选择器用来匹配无内容的元素,用伪元素::after生成的content内容不会影响实体内容。
  35、content动态生成值无法获取。
  36、getComputedStyle可以获取伪元素的计算样式,window.getComputedStyle(DOM,"::after").content
  37、content内容生成应用:
  ①辅助元素生成,如清除浮动:

1
2
3
4
5
.clear:after {
content: '';
display: 'block';
clear: both;
}

  再如等分空间的柱状图,传送门,核心在于通过:before实现底对齐,:after实现两端对齐。
  ②字符内容生成:传送门,原理就是通过@font-face自定义字体集合,然后替换文本内容。除此之外,这个content也可以为Unicode字符,比如\A换行(LF),\D回车(CR)。配合CSS3 animation的loading demo,传送门
  ③图片生成,content: url(),适用于png、jpg、svg、ico、base64URL等,但是不支持CSS3渐变背景图(linear-gradient)。
  ④利用content开启符号闭合,一种使用open-quoteclose-quote实现的方式:通过 选择器 { quotes: '前引号插入内容' '后引号插入内容'; }配合选择器:before { content: open-quote; }以及选择器:after { content: close-quote; }实现。另一种则是直接把这种quote放到content内容中直接书写:伪元素before/after选择器: { content: '你要加的内容'; }
  ⑤通过attr属性设置content内容:img::after { content: attr(alt) },注:attr内可以传入原生HTML属性以及自定义data-X属性且这些属性不能带引号。
  ⑥content计数器:这种应用,需要先掌握几个核心的方法属性,{ counter-reset: 变量命名1 数值1 变量命名2 数值2 ···; }这是一个初始化计数器的动作并且能够同时指定多个计数器,数值内容在CHROME下可以是负数,如果是小数则向下取整;但在FF和IE下不会识别,视作0处理;除了指定数值,还能够设置noneinherit来取消重置和继承重置。具体见传送门counter-increment属性的值可以是counter-reset指定的一个或多个关键字,后面可选跟随数字,表示每一次增加的值,缺省值为1。counter-increment可以被多次触发,即在::before::after中的该属性都会被触发,然后通过counter(关键字)输出结果。counter()/counters()方法类似于CSS3的calc()方法,比较有意思的一点是,counter()还能接收第二个参数style,它对应的是list-style-type支持的属性值,即递增的显示可以不只是单纯数字,也可以是罗马字、英文等,见传送门content里可以调用多个counter()counters(name, string,style可选)string传参需要引号包围,并且是必传,它用来表示子序号的连接字符串,那子序号需要重新定义关键字么?其实不需要,counter-reset设定的关键字仅对他最近的层级生效(唯一性),即同一个初始名,但其实不同嵌套初始化的不共享这个值,见传送门
  注:设置了counter/counters方法显示输出样式的DOM在文档流中必须在设置counter-increment元素的后面才有技数效果。
  38、HTML5可以接受自定义标签,浏览器默认样式没有规范,会被应用缺省inline,向下兼容,IE8等低版本不识别,会直接显示其内容。
  39、笔记16中,我们知道了设置box-sizing: border-box以后,width成了真正意义上的总宽度。但如果是具有块状特性的元素且内部padding足够大,怎么样算足够大?比如总宽度是100px,横向左右padding和为120px,那么最终宽度是120px。
  40、对内联元素来说,它们没有可视宽度和高度,即clientHeightclientWidth永远是0。垂直方向上的行为表现完全受line-heightvertical-align的影响。
  41、内联元素的垂直padding,可以用来扩大链接或按钮的点击区域,同时不会影响到现有布局,还有一种登陆 | 注册管道符的demo,见传送门
  42、对于非替换元素的内联元素,不仅padding不会加入行盒高度计算,margin和border也不会参与计算,它们的表现形式是在内联盒周围发生渲染
  43、padding属性:
  ①不支持负值。
  ②支持百分比,块级元素div { padding: 50%; }可以撸出一个正方形,但是内联元素由于有假想盒的存在(笔记25),会有个额外的高度导致最终宽高不等,解决方案很简单,其实就是用控制内联高度的方式即font-size解决该问题:

1
2
3
4
5
span {
padding: 50%;
font-size: 0;
background-color: gray;
}

  注:padding百分比无论是水平还是垂直方向上都是相对于宽度计算的。
  44、头图兼容性较好的做法(包括IE6在内的大部分浏览器),传送门
  45、内联元素的padding在文字较多的时候可能会出现断行。
  46、标签元素存在内置padding,ol/ul内置padding单位是px。如果列表中的font-size很小,则li元素内的ulol左边缘就会离文本内容区域很远,反之font-size很大就会出现项目符号跑到元素外的情况。当font-size在12px-14px时,22px是一个较好的padding-left设定值,所有浏览器都能正常显示。不过为了更佳的体验,用content计数器用法更舒服。
  47、button的padding在设置为0的时候,在FF下依旧会保留左右的padding。可以通过button::-moz-focus-inner { padding: 0; }来解决这个兼容问题。
  48、IE7下button内文字过多会使左右padding逐渐变大。
  49、padding可以配合background-clip属性实现一些CSS图形的绘制效果
  50、元素偏移尺寸:对应元素的border box尺寸,如offsetWidthoffsetHeight
  51、元素内部尺寸:对应元素内部区域尺寸,即padding box尺寸,包括padding但不包括border。如clientWidthclientHeight
  52、元素外部尺寸:对应元素外部区域尺寸,包括padding、border以及margin。即margin box尺寸,没有原生DOM API,JQ中可以使用$().outerWidth(true)$().outerHeight(true)来控制。
  53、对于margin,元素设定width值或者保持”包裹性”的时候,margin对尺寸没有影响。只有在空间可被充分利用的条件下是可以被影响的,那啥是空间可被充分利用呢?比如说有父子DOM嵌套关系,分别有fatherson的class,那么如果在father设置width,son不设置宽度,设置margin就会影响到自身的宽度,以下面代码为例,最后son宽度就是340px,并且这种条件下,垂直方向的高度也可以改变。

1
2
3
4
5
6
7
8
9
<div class="father">
<div class="son"></div>
</div>
.father {
width: 300px;
}
.son {
margin: 0 -20px;
}

  那这种充分利用的特性带来了什么实际场景中的应用?比如:一侧定宽的两栏自适应布局,见传送门。其实本质就是margin来扩充了父级的宽度,然后内部两栏,一栏为固定死的,另一栏自适应剩余部分的结果。再比如表格间隙多余的最后一项消除的替代方案,举个例子,我们想要我们的每一条li之间产生20px的间隙,那么一般来讲会设置一个margin-right: 20px;,但事实上,换行的时候,最后一项就会多出一个间隙,消除手段通常是在这个元素上生成的时候,附加一个margin-right: 0;的样式类或用CSS3的nth-of-type选择器(不考虑IE8)。现在充分利用margin这种改变布局的特性,我们可以在父容器给一个margin-right: -20px;,子元素则根据剩余部分自适应,那么多余的20的px相当于就被抹除了!
  54、不同浏览器的滚动条触发规则:Chrome是子元素超过content-box尺寸触发,IE和FF则是超过padding-box触发。这种规则会导致padding-bottom在IE和FF下失效。
  55、笔记54中我们知道了padding-bottom有兼容性问题,即在页面底部留白时,我们不应使用padding来控制,而可以转投笔记53中的利用特性,使用margin扩充纵向留白。
  56、利用margin外部尺寸来实现等高布局,传送门,核心见下面代码:

1
2
3
4
5
6
7
8
.column-box {
overflow: hidden;
}
.column-left,
.column-right {
margin-bottom: -9999px;
padding-bottom: 9999px;
}

  57、margin的百分比值同padding一样,无论是水平还是垂直方向上都是相对于宽度计算的。
  58、<h1>、<p>、<ul>这些标签是有默认垂直方向的margin值的,并且单位是em这种相对字体的单位。这里作者说了他的理解,我觉得没啥毛病,即如果margin使用px这种绝对单位,当字体font-size变大了,那么整个容器其实宽高还是那么大就会造成内容臃肿在一起。而使用em它是根据父元素的font-size按比例算的,所以margin会跟着自适应变大,整个容器的排版依旧能够保持一致。
  59、margin的合并问题:
  ①:只发生在块级元素上(不包括那些通过浮动和绝对定位产生块级特性的元素)。
  ②:只发生在垂直方向上(前提是不通过writing-mode改变方向)。
  60、margin的合并场景:
  ①:相邻兄弟元素margin合并。
  ②:父级和第一个子元素或者最后一个子元素的合并(如果父级没有声明垂直margin,子级声明的垂直margin将被合并到父级去,传送门)。
  ③:空块级元素的margin合并(这里这个空的块提不提供margin垂直方向上的值,它都会产生合并特性)。
  61、引出笔记61前,让我们先温习一下啥是BFC,BFC英文全称是Block Formatting Context,即块状格式化上下文。BFC指的是页面布局中的一块区域,它拥有自己独有的内部渲染规则,不受外部影响,同时也不会影响到外部区域,所以BFC元素是不会发生margin重叠的情况;另外BFC也可以清除浮动带来的影响,原因也是那个不影响外部区域,假设它无法清除,那就会造成高度坍塌,破坏外部结构。除此之外,BFC还有一个很关键的用处:自适应布局,怎么自适应?当我们的元素形成BFC以后将不受外部影响,打个比方,如果他们同在一块浮动容器控制下,那么这块BFC将脱离控制,自动填满刨去其他浮动元素的剩余空间。
  62、如何触发BFC?
  ①根元素(即html)。
  ②float属性不为none。
  ③position属性为absolute,fixed(不为relative和static)。
  ④display为inline-block,table-cell,table-caption,flex,inline-flex。
  ⑤overflow不为visiable时(auto、scroll或hidden)。
  63、消除margin合并的方式:
  对于margin-top合并的情况:
  ①父元素设置为BFC。
  ②父元素设置border-top。
  ③父元素设置为padding-top。
  ④父元素和第一个子元素之间添加内联元素进行分隔。
  对于margin-bottom合并的情况:
  ①父元素设置为BFC。
  ②父元素设置border-bottom。
  ③父元素设置为padding-bottom。
  ④父元素和最后一个子元素之间添加内联元素进行分隔。
  ⑤父元素设置height、min-height或max-height。
  64、margin合并后的计算值:
  ①正正取大。
  ②正负相加。
  ③负负最负(转成绝对值,取大)。
  65、margin合并的意义:
  ①兄弟元素合并:和em作用类似,为了排版更加舒适。
  ②父子元素合并:在页面任何地方嵌套或直接插入空div都不会影响原本的块状布局。
  ③自身margin合并:避免不小心遗落或者生成的空标签影响原本的排版和布局。
  66、margin: auto的问题:这个问题我觉得可以分为两种情况,第一种是元素没有设置widthheight注意这里的设置即便值是auto也算设置,它会自动填充父容器。另一种则是设置了宽高,这个时候前者的填充性被覆盖,根据”剩余空间”进行分配。
  67、关于利用margin: auto来进行水平垂直居中的应用,我在<<到底怎么样才能水平垂直居中喔>>一文中有对其进行应用的例子,但是那只是在水平方向上利用了该特性,垂直方向上其实使用的是transform来移动。那为什么容器定高,元素定高,margin: auto无法垂直方向上居中呢?因为触发margin: auto计算的一个前提条件是当width或height为auto时,元素是具有对应方向的自动填充特性的。见笔记66中第二种情况,设置宽高后该特性将被覆盖。所以没办法在按这种规则计算分配空间。在前文我提到的另一篇博客中有另一个方案对绝对定位元素的垂直居中进行控制,即在对向属性上同时设置值,这个时候该元素会表现为”格式化宽度和格式化高度”,见笔记14。
  68、margin: auto的计算需要IE8及以上的浏览器才能支持。
  69、内联非替换元素的垂直margin无效,但替换元素的垂直margin有效,并且没有margin合并的问题,所以图片永远不会发生margin合并
  70、trtd或者display: table-celldisplay: table-row的元素margin都是无效的。
  71、绝对定位元素非定位方向的margin值无效。
  72、定高容器的子元素的margin-bottom或定宽容器的子元素的margin-right无效,这个就比较经典了,我自己在写需求的时候,就有一个地方需要使用绝对定位设置margin-right定位,但是却发现无效了。怎么理解这个问题呢?当我们想通过margin属性改变自身位置时,必须是和当前元素定位方向一样的margin属性才行,否则设定的margin只能影响后面的兄弟元素或父元素。这里的定位方向又是啥?对一般元素,默认流是左侧以及上方,那么只能通过margin-leftmargin-top来影响元素定位。但是如果通过float: right或者绝对定位设置right属性,就会改变定位方向,就可以通过另一侧设置了。
  附:当absolute遇到left/top/right/bottom属性时,才变成真正的绝对定位元素。其实这里涉及到一个相对性问题,当设置了一个方向的属性,那么那个水平或者垂直方向上的相对性将丢失,那这个相对性到底是个啥呢?
  73、border-width不支持百分比值,除了使用固定数值,还支持关键词如thin,等同1px;medium,默认值等同3px;thick,等同4px。
  74、border-style默认值为none你也可以通过设置border-width: 0来重置。文中描述说如果同时对这两种属性进行设置,渲染性能最高?

1
2
3
4
div {
border: 1px solid;
border-bottom: 0 none; /* 渲染性能高的写法 */
}

  75、border-style: dotted在IE下和在CHROME、FF下表现形式不同,前者是小圆点,后者是小方点。由于CSS的border-radius是在IE9浏览器才开始支持的,所以之前版本的IE圆角实现可以利用这种特性来hack模拟,本质就是结合overflow: hidden来隐藏多余点(当我们想单独得到一个圆的时候)。

1
2
3
4
5
6
7
8
9
10
.box {
width:150px;
height: 150px;
overflow: hidden;
}
.dotted {
width:100%;
height: 100%;
border: 149px dotted #cd0000;
}

1
2
3
<div class="box">
<div class="dotted"></div>
</div>

  76、border-style: double上下两线border实线,值为1px和2px时,与solid表现形式一致。当3px开始才有双线表现,所以有笔记73中的medium默认值。
  77、border-color在没有设定时,默认取color色值。
  78、bordertransparent的巧妙配合:color: transparent在IE9以上才支持,而border-color: transparent在IE7就支持了。
  ①右下角background定位:现在CSS3操作直接background-position: right 数值 bottom 数值即可。 文中提到的下面这种操作…em…我没实践出来。
1
2
3
4
.box {
border-right: 50px solid transparent;
background-position: 100% 50%;
}

  ②增大移动端点击按钮的可触区域:第一种是在外层嵌套标签专门控制区域,第二种则是利用其自身的paddingbottom扩充区域大小。而设定padding在我们使用外部font库时,可能会造成中间图案定位问题,所以最佳方案是使用透明border增加点击区域传送门
  ③三角形等图片绘制。

1
2
3
4
5
div {
width: 0;
border: 10px solid;
border-color: #f30 transparent transparent;
}

  79、块级元素负责结构,内联元素负责排版。
  80、line-height行高的定义是两条baseline的间距,而baseline又对应着英文字母x的下边缘。vertical-align的默认值为baseline。而CSS中有一个概念x-height,它对应字母x的高度,等于等分线mean-line到基线baseline的距离。、
  81、我们常用的vertical-align: middle并不是等分线mean-line处,而是基线往上1/2个x-height处。所以我们有通过vertical-align: middle来进行垂直居中时,其实它并不是容器的垂直居中,而是我们字体样式的垂直居中。
  82、ex单位对应的就是x-height的高度,它是一个相对单位,不管字体字号如何改变,永远相对于这个变化。那么这个单位可以怎么利用呢?比如基于ex单位的天然垂直居中对齐效果实例页面,见传送门
  83、<div>内容为空的情况高度为0,当添加文字后,高度被撑起,但本质上这个撑起的高度是由行高line-height属性绝对的而不是font-size
  84、前面我们提到了font-size,现在我们来看看font-size到底作用在啥子地方。首先,line-height的数值属性和百分比属性值都是相对于font-size计算的。而vertical-align又是根据line-height计算的,见笔记80。以下面的代码块为计算样例,最终的vertical-align = 16px * 1.5 * -0.25 = -6px

1
2
3
4
5
6
7
p {
font-size: 16px;
line-height: 1.5;
}
p > img {
vertical-align: -25%;
}

  然后我们看看font-size的关键字属性值。
  相对当前元素font-size计算的有:
  ①larger,<big>标签对应font-size大小。
  ②smaller,<small>标签对应font-size大小。
  与当前元素font-size无关,仅受浏览器设置的字号影响:
  ①xx-large,和<h1>元素计算值一样。
  ②x-large,和<h2>元素计算值一样。
  ③large,和<h3>元素计算值相似(偏差值在1px以内)。
  ④mediumfont-size的初始值,和<h4>的元素计算值一样,为16px。
  ⑤还有与large相对格式的small。
  85、浏览器默认font-size大小是16px,所以设置font-size: 87.5%font-size: 14px是等价的。
  86、Chrome下有一个12px的字号限制,就是文字的font-size计算值不能小于12px,由于Chrome的特殊性,我们通常进行移动端em、rem适配的时候,就不能直接设置

1
2
3
html {
font-size: 62.5%;
}

  这样计算结果是10px,换算成em,如果是直属父级,或rem就是1em/1rem,但是Chrome老哥说,我觉得不行,因为只要小于12px且不为0的大小我就觉得它是12px大小的,什么?你问是0的时候Chrome怎么看?那当然是0咯。那怎么弄呢,可以设置成625%,即100px。既便于计算又不会有之前的问题。
  87、希望隐藏logo对应元素内的文字,除了text-indent缩进隐藏外,还可以通过设置font-size: 0
  88、font-family默认值由操作系统和浏览器共同决定。它支持两类属性值,一类是“字体名”,一类是“字体族”,如果字体名包含空格需要使用引号包裹,不区分大小写,且如果有多个字体设定将遵从从左往右依次匹配本地是否有对应的字体。
  字体名用法:

1
2
3
4
5
6
body {
font-family: simsun;
}
body {
font-family: 'Microsoft Yahei', 'PingFang SC';
}

  字体族分类:
  ①serif 衬线字体,即那些横竖撇捺、张弛有度,有深有浅的字体。
  ②sans-serif 无衬线字体(现在更普适的使用字体),即那些所有笔画都差不多粗细的字体。
  以上两者还可以和具体字体名写在一块,但是必须写在最后,因为大多数浏览器下,写在这两种属性后面的字体会被忽略。

1
2
3
body {
font-family: "Microsoft Yahei", sans-serif;
}

  ③monospace 等宽字体,这种一般针对英文字体而言,即每个字符在同等font-size下宽度相同。这种特性的其中一种应用就是在模拟选择栏中的soliddashed这些效果时,使它们长度相当,见穿送门ch单位结合等宽字体特性进行手机长度校验这类的宽度控制。ch本身是一个相对单位,它对应着阿拉伯数字0的宽度,CSS3才开始支持该单位。
  ④cursive 手写字体
  ⑤fantasy 奇幻字体
  ⑥system-ui 系统UI字体
  89、font-weight同样支持关键词属性和具体的数值,如normalboldlighterbolder,数值从100到900(间隔100为一个关键词),其中400对应normal,700对应bold。关于lighterbolder是对继承的font-weight进行解析的,解析规则如下,这里需要注意的是,系统里面需要安装了该字体家族的全部字重字体才能将所有解析情景呈现,否则缺失的字重字体是无法解析的,即没有表现形式。

继承的值bolderlighter
100400 100
200400100
300400100
400700100
500700100
600900400
700900400
800900700
900900700

  90、font-style属性值有normalitalicoblique,其中要提的一点差异是italicoblique,这两者都是指斜体控制,那么有什么区别呢,答案就是如果当前字体有设定专门的斜体字体,那么italic会取那个专门的“样式”,如果没有就会适应成obliqueoblique仅单纯地让文字倾斜。
  91、缩写的font属性:它的基本语法组成有[ [ font-style || font-variant || font-weight ] ? font-size [ / line-height ] ? font-family ],其中font-sizefont-family是必选的。值得注意的是这种缩写的font属性将会破坏部分属性的继承性。原文对这块的例子解释,我觉得有点绕人的意思,概括下来就是当你想用font内的font-weight属性时,line-height将会被覆盖成这个值,并且不同浏览器的这个值是不一样的,存在兼容性问题。另外,由于font-family是必选项,当这个属性很长的时候,后面继承的时候就会挂很长的列表。文中提供了如下两种解决方式:
  ①设置一个不存在的字体名占位,然后再设置font-family: inherit来重置这个占位字体。
  ②利用@font face将我们的字体列表重定义为一个字体。
  92、关于@font face,我们常在字体图标技术中应用它:本质是一个定义字体或字体集的变量,它不仅可以简单定义字体,还包括字体重命名,默认字体样式设置等。需要我们关注的属性包括font-familysrcfont-stylefont-weightunicode-range。这里主要记录一下srcunicode-range,其余的前文我们有过描述。src表示引入的字体资源,如果使用系统安装字体可以使用locale()功能符,该功能符IE9及以上版本才支持。而unicode-range则是可以替换特定字符或者特定范围内的字符为我们指定的字体(IE8不支持),如下面这个替换前后双引号的demo。

1
2
3
4
5
6
7
8
@font-face {
font-family: quote;
src: local('SimSun');
unicode-range: U+201c, U+201d;
}
.font {
font-family: quote, 'Microsoft Yahei';
}

  93、text-indent用于对文本进行缩进控制,我们可以使用text-indent负值隐藏文本内容,这种操作可以应用在将网站的标记放在<h1>这种标题标签中然后隐藏,利于SEO。关于text-indent为负值的情景,要注意百分比和数值的区别:百分比是根据当前元素的包含块来运算的,而数值则是当前内联盒子,见实例有一点需要注意,一些设备在text-indent负值特别大的时候可能会存在卡顿和性能风险,以及对于一些屏幕阅读软件不会读取越界的内容,将给无障碍阅读用户带来困扰。
  94、text-indent仅对第一行内联盒子内容有效。
  95、非替换元素意外的display计算值为inline的内联元素设置text-indent无效。在生效时,注意是否存在嵌套的子元素,由于继承性,如果你还想对其进行别的控制,需要在子元素上覆盖这个值。
  96、<input>text-indent值无效,<button>text-indent有效但是存在兼容性问题,IE下百分比根据容器计算,Chrome和FF以及其他Shadow DOM元素浏览器百分比按照自身尺寸计算。
  97、letter-spacing用来控制字符之间的间距,具有继承性。默认值是normal而非0,支持负值,当值足够大的时候,会让字符重叠甚至反向排列。
  98、word-spacingletter-spacing特性类似,但前者仅作用在空格字符上。啥意思呢?它生效的条件是你首先得有空格存在。
  99、word-break属性有normal:默认的换行规则;break-all:允许任意非CJK(中日韩)文本单词断行;keep-all:不允许CJK单词换行,只能在半角空格或连字符处换行。非CJK的文本行为实际上和normal一致。目前移动端不支持keep-all属性
  100、word-wrap在CSS3中有了另外的命名overflow-wrap,但是考虑到兼容性问题我们还是用以前的写法,属性有normal,正常换行规则;break-world,一行单词中是在没有其他靠谱的换行点再换行,这个换行点比较关键,具体见传送门
  101、white-space用于处理元素内的空白字符(包含了Space、Enter、Tab产生的空白)。属性有normal:合并空白字符和换行符;pre:空白字符不合并,并且内容只在有换行符的地方换行;nowrap:合并空白字符,但不允许文本环绕;pre-wrappre的作用上同时允许文本环绕;pre-line:合并空白字符,但只在换行符的地方换行,允许文本环绕。
  102、white-space设置nowrap时,元素宽度表现为”最大可用宽度”,换行符和一些空格合并,文本一行显示。以下是常见的应用场景:
  ①包含块尺寸过小处理。
  ②单行文字溢出点点点效果(配合text-overflow: ellipsis)。
  ③水平列表切换效果,DEMO
  103、text-decoration下划线和文本重叠问题如何解决?结合text-decoration: none以及设置border-bottompadding-bottom
  104、text-transform这个属性就比较有趣了,它是为英文字符定制的,可以将这些字符进行大小写转化。属性也比较简单uppercaselowercase。应用价值也极高,比如我们在输入验证码、身份证这些信息时,如果有强校验大写,这种转化无异于帮我们省了一个重大工序。
  105、:first-letter是用来选择首字符进行操作的,不过这里的首字符比较特殊,里面有个比较神奇的设定:就是一些常见的标点符号在:first-letter眼中是”附赠品”,什么意思呢?当这些附赠品出现在头部时,它们就像赠品一样默认受我们的选择器影响,然后直到我们真正意义上的首字符(商品)变化为止。其次:first-letter生效的前提是display值为blockinline-blocklist-itemtable-celltable-caption,其他如tableflex都无效。另外:before伪元素的content内容会影响:first-letter,即里面的内容将会被优先作用。下面看看它支持的CSS属性:
  ①所有字体相关属性。
  ②所有背景相关属性。
  ③所有margin相关属性。
  ④所有padding相关属性。
  ⑤所有border相关属性。
  ⑥color属性。
  ⑦text-decoration等修饰用属性。
  不能使用visibilitydisplay这些去控制显隐性。
  :first-letter具有嵌套选择的能力,比如<p>下嵌套了一个<span><span>外没内容,能够直接选择到span内的首字符。
  :first-letter其实是作为子元素存在的,所以在衡量特指度权重的时候,相同属性声明,它的级别一定会比父级高,因为先继承再覆盖。
  实际应用:如在字段、金额前加符号标记。
  106、:first-line没有笔记105中”附赠品的”操作,两者支持的CSS属性相近。这一类的伪元素选择器视作子元素,跟前文中一样,存在总是高一级样式权重的特征。在标签嵌套的时候有所不一样,它不支持table相关属性(inline-block/inline-table),DEMO。文中对该选择器的应用举了个覆盖父级的例子:按钮具有一个全局的颜色控制,但是按钮的字体不就被遮了么,用:first-line指定颜色,就可以规避这个问题。
  107、关于颜色的关键字:如果浏览器能够识别关键字,不会有什么问题,但如果浏览器无法识别的话,在HTML和CSS中定义的这个关键字将会产生不同的解析结果。前者,会有特殊的算法替换这个颜色,后者则会直接使用默认颜色。
  108、background-color: transparentIE6就开始支持,border-color: transparentIE7开始支持,但color: transparent从IE9才开始支持(高版本的IE8兼容可以透明化,但是用户实际上使用的都是原生IE8)。
  109、currentColor使用当前color计算值,但这是个CSS3变量,IE9+才支持。
  110、rgbahsl,CSS3属性,IE9+才支持。rgba在低版本中可以使用透明度PNG图片以及filter渐变滤镜来兼容。
  111、background-color背景色永远是最低的。
  112、一些没见过的隐藏操作:
  ①不占据空间、辅助设备无法访问、同时不渲染,可以使用<script>标签。

1
2
3
<script>
<img src="1.jpg">
</script>

  ②不占据空间,辅助设备无法访问,显隐的时候可以有transition淡入淡出效果(其实这种应用场景我没有接触过,先记录下)。

1
2
3
4
.hidden {
position: absolute;
visibility: hidden;
}

  ③不能点击,不占据空间,键盘可访问,可使用clip裁剪。

1
2
3
4
5
6
7
8
.clip {
position: absolute;
clip: rect(0, 0, 0, 0);
}
.out {
position: relative;
left: -999em;
}

  ④可以点击,不占据空间,可以使用透明度。

1
2
3
4
5
.opacity {
position: absolute; /* 是否占据空间控制 */
opacity: 0;
filter: Alpha(opacity=0); /* 兼容 */
}

  113、display: nonebackground-image的问题: FF中,display: none元素的background-image是不加载的;但在Chrome和Safari中,若父元素是display: none,图片才会不加载,仅是本身元素的背景图display: none,图片依旧会去加载。而IE老哥表示,任何情况他都会去加载图片。<img>标签则不受display: none影响,所有浏览器都会去请求图片资源。有了这种特性,我们就可以利用这种方式去优化我们轮播的加载体验。
  114、visibility具有继承性,父元素设置hidden后子元素也会被隐藏。另外visibility: hidden并不会影响CSS计数器的计算,但是display: none时,就完全不会参与计算。
  115、visibility可以配合transition实现显隐的过度效果,如transition: opacity 延迟时间。CSS3中的transition支持CSS属性visibility。这种延迟显示的场景有个比较经典的例子:光标移动的过程中,如果不设置延迟效果将会瞬间触发一些hover动作,可能会造成一些不必要的遮挡,见传送门
  116、关于视觉障碍用户的体验:其实这个问题目前我做的需求都是没有涉及的,作者对display: nonevisibility: hidden两种情景的屏幕阅读进行了对比,即visibility的显隐性在视觉障碍用户进行操作时,体验更佳,它能够精准地读取当前操作状态的title信息。而display显隐无法通知。另外,普通元素的title属性不会被朗读,需要辅助按钮等控件元素,如role="button"注意:visibility: hidden的元素是不会被朗读的。见文中DEMO,似乎是个反例,但是其实在从显示到隐藏的这个过程中,区域还没有消失,所以会被朗读出来。
  117、outline表示元素的轮廓,语法和border属性非常类似;outlinefocus状态以及键盘访问关系密切。Tab键可以依次不断切换focus元素,包括链接、按钮、输入框等表单,甚至设置了tabindex的普通根元素。Shift+Tab可以反向focus。默认状态下,focus元素会通过虚框或者外发光的形式进行区分和提示,当元素被focus后,敲击回车键相当于触发了该元素的click事件。现代浏览器,点击链接按钮后已经不会触发outline效果了,但通过Tab或element.focus()才会触发发光效果。
  118、outline的应用:outline是真正意义上的不占据任何空间的属性。轮廓宽度设置再厚也不会影响任何其他元素的布局。并且outline轮廓是可穿透的。书中例子有二,①头像裁剪的矩形镂空效果。②自动填满屏幕剩余空间。
  119、cursor光标属性:auto,cursor的默认值,会跟着内容而变化成不同的光标形态;default系统默认光标形态,不会变化,指那种未选定的情形。none,隐藏光标,比如观看视频全屏时,静止几秒我们就将鼠标图标隐藏掉,有mouseover再重新显示,注意这里cursor: none的兼容性是IE9+,即IE8下要做兼容处理,可以通过自定义透明光标(Chrome弄一张透明PNG)实现,传送门。代码中出现了:root选择器,首先这是一个根元素选择器,html就是我们的根,其次这是一个CSS3属性,兼容性IE9+。还有一些常用的如pointertext就不全部赘述了。
  120、direction主要关注2个属性ltr默认值以及rtl,分别代表从左到右left to right以及右到左。它负责的东西很关键,就是改变水平流向,比如交换按钮位置,图片左右互换等等。
  121、unicode-bidi,这个属性是配合direction一起使用的,因为direction其实只能改变图片或按钮的呈现顺序,而对纯字符内容无能为力(尤其是中文字符),这个时候就需要兄弟unicode-bidi帮忙了。bidi的全写英文是bidirectionality,它意味着双向性(阿拉伯文是从右往左读的),它帮助规范字符出现双向性时该有的表现,默认值为normal,表示正常排列,而embed只能作用于内联元素上,并且embed属性不会受外部嵌套的元素属性设置影响(相当于自身开了个内嵌区域,自己操作),传送门bidi-override,会强制所有字符按照direction设置的方向反向排列。embedbidi-override可以使用特殊字符替代。
  122、writing-mode就比较牛逼了,它可以将页面默认的水平流改成垂直流。默认值为horizontal-tb很好理解,horizontal水平,tb,topbottom,即水平方向从上到下排列。由于不同浏览器和版本支持的属性都有所不同,作者整理出了几个需要关注的属性:

1
2
3
4
.example {
writing-mode: lr-tb | tb-rl | tb-lr; /* IE8+ */
writing-mode: horizontal-tb | vertical-rl | vertical-lr;
}

  123、关于float,浮动的本质就是为了实现文字环绕的效果,文章原话。
  124、float特性:
  ①包裹性,由两部分组成,包裹和自适应性。包裹可以理解为,具有float设定的容器的宽高将会以嵌套的内容宽高为表现。自适应则是浮动元素嵌套的元素如果是多个,将会自适应分配剩余空间。
  ②块状化格式上下文(BFC)
  ③破坏文档流
  ④无任何margin合并
  125、笔记124中的第二条中,强调了块状化的说法,那么什么是块状化?即一旦float属性不为none,则display计算值将是block或者table。像以下的写法都是冗余的:

1
2
3
4
5
6
7
8
9
span {
display: block; /* 多余 */
float: left;
}
span {
float: left;
vertical-align: middle; /* 无效 控制内联的你还指望在块级里搞事情? */
text-align: center; /* 无效 */
}

  126、行框盒子如果和浮动元素的垂直高度有重叠,则行框盒子在正常定位状态下只会跟随浮动元素,而不会发生重叠。行框盒子怎么理解呢,其实就是我们内联元素所在的那一层,当浮动元素导致高度塌陷时,其实块盒的确发生重叠了,但是内联元素所在的层则由于有这种特性不会发生重叠。
  127、文字环绕其实是由”父级高度塌陷”和”行框盒子区域限制”(笔记126中描述)两方面作用的结果。”父级高度塌陷”可以通过设定高度来cover但是”行框盒子区域限制”就没办法了,所以当你出现设定容器高度与内嵌图片高度一样时,由于内联下图片底部的间隙导致实际高度大于这个高,后面的文本就会产生环绕。见传送门
  128、IE8以下的浏览器产生浮动,文字会浮动到下一行内容显示。这与我现在的认知IE8+的同行浮动显示不同。
  129、浮动元素的作用机制:
  ①浮动锚点:float所在流中的一个点,这个点本身并不浮动,表现得像一个没有margin、border和padding的空内联元素。作用就是产生”行框盒子”:在没有”行框盒子”进行浮动参考时(比如浮动元素前后都是块级时),提供参考。
  ①浮动参考:浮动元素对齐参考的实体。浮动元素进行对齐的实体就是当前float元素的”行框盒子”,而非外部包含块盒。
  130、官方文档对clear属性的解释是:元素盒子的边不能和前面的浮动元素相邻。所以其实这个值真正意义上定义的是设置了clear属性元素本身的行为,而不是float元素的行为。默认是none,即左右浮动正常作用于本身,left左侧抗拒浮动,right右侧抗拒浮动,both两侧抗拒浮动。在我们实际应用场景中使用clear来清除浮动其实使用clear: both即可,因为clear: left\right都可以用前者替代。文中有一个DEMO比较好地阐释了什么clear针对的前面的浮动元素

1
2
3
4
5
6
7
8
li {
width: 20px; height: 20px;
margin: 5px;
float: left;
}
li: nth-of-type(3) {
clear: both;
}

  以上样式为第三个li设置clear: both,假设我们有10个<li>元素,最终只会形成2行排列而不是三行。首先最基本的一点,li是块级元素,在float: left;的作用下,才会出现单行的情景,然而clear: both事实上只针对前面的浮动,所以第三个li本身恢复块级排列到了第二行,其后的浮动不受影响跟着第三个li到第二行。综上所述,当我们遇到需要屏蔽浮动的场景统一使用clear: both
  131、clear属性只有块级元素才生效,而::after等伪元素默认都是内联水平,这就是为什么我们在清除浮动的时候往往还需要同时设置一个display属性的原因,比如下面这种:

1
2
3
4
5
.clear:after {
content: '';
display: table/block/list-item;
clear: both;
}

  132、clear只能在一定程度上消除浮动的影响,因为clear: both这种本质上是使自身不和float元素在一行显示,所以float一些特性还是会被保留。比如:
  ①clear: both元素前也是浮动元素,即使margin-top负值设为-9999px也无效。
  ②clear: both后面元素依旧可能发生文字环绕现象。
  133、再看看overflow,它才是最适合进行清除浮动的控制属性。为什么呢?因为它不会影响原本的流体特性或宽度表现。而其他的CSS声明基本都会让元素产生”包裹性”。
  134、overflow属性本身是为了对溢出元素的内容进行裁剪而设计的,并且裁剪边界的判定是以border box为基准而非padding box实例
  135、overflow属性有一个典型的兼容问题,即在Chrome浏览器下如果容器支持滚动,则padding-box也会被计入滚动尺寸内,表现形式就是拖到容器最下方,若有设定padding,Chrome下将会有留白,而IE和FF不会计算这个padding,即不会有留白问题。
  136、IE8以上开始支持overflow-xoverflow-y属性,它们提供的属性跟overflow一致:
  ①visible: 默认值。
  ②hidden: 剪裁。
  ③scroll: 滚动条区域一直在。
  ④auto: 不足以滚动时没有滚动条,可以滚动时滚动条出现。
  但是,overflow-xoverflow-y有相互约束:除非overflow-xoverflow-y属性值都是visible,否则visible会被当作auto解析。看看下面这个例子:

1
2
3
4
html {
overflow-x: hidden;
overflow-y: auto; /* 多余,如果不设置,默认是visible,又因为其中一个不是visible,所以这个默认最终会被当auto解析 */
}

  137、textareahtml元素是默认可以产生滚动条的。因为它们默认的overflow不是visible,IE8开始都是使用auto作为默认属性,即默认状态下是没有滚动栏的,只有当内容溢出时才出现。而IE7的表现就是如同设置了overflow-y: scroll一样(为什么说如同,见笔记136),一直保有垂直滚动栏。
  138、PC端,无论什么浏览器,默认滚动条都是来自html,如果想去除默认滚动条可以直接通过如下样式设置剔除:

1
2
3
html {
overflow: hidden;
}

  139、移动端使用笔记138中的方式就不一定能够隐藏默认滚动条了,PC端的滚动高度可以使用document.documentElement.scrollTop获取,而移动端需要使用document.body.scrollTop获取。那结果已经很明显了,使用body元素选择器即可:

1
2
3
4
5
body {
width: 400px;
height: 100px;
overflow: auto;
}

  这里的宽度虽然是400px,但要注意到其实滚动条本身会占据空间,在WIN7系统下的IE7+、Chrome、FF浏览器滚动栏所占据的宽度均为17px。关于滚动条占据空间带来最大的影响是水平居中布局可能会产生晃动,因为窗体默认没有滚动条,而HTML内容是自上而下加载的,就会发生一开始没有滚动条,然后突然出现滚动条的情况,此时页面的可用宽度发生变化,水平居中重新计算,就会发生页面晃动。比较简单的做法是:

1
2
3
html {
overflow-y: scroll;
}

  但这样虽然横向的overflow最终计算就是auto了,并且在页面比较高的时候还凑合,但是如果页面就只用一屏,右侧还是始终有滚动栏就不合适了。下面是作者提供的让页面滚动条不发生晃动的技巧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
html {
overflow-y: scroll; /* for IE8 */
}
:root {
overflow-y: auto;
overflow-x: hidden;
}
:root body {
position: absolute;
}
body {
width: 100vh; /* 移动端100% */
overflow: hidden;
}

  140、自定义浏览器滚动条:IE的自定义效果要比原生的还差;支持-webkit-前缀的浏览器可以使用以下属性:
  ::-webkit-scrollbar整体部分。
  ::-webkit-scrollbar-button两端按钮。
  ::-webkit-scrollbar-track外层轨道。
  ::-webkit-scrollbar-track-piece内层轨道。
  ::-webkit-scrollbar-thumb滚动滑块。
  ::-webkit-scrollbar-corner边角。
  实际开发中使用其中3个就够了:

1
2
3
4
5
6
7
8
9
10
11
12
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
background-color: rgba(0,0,0,.3);
border-radius: 6px;
}
::-webkit-scrollbar-track {
background-color: #ddd;
border-radius: 6px;
}

  141、锚点是如何跳转的就不赘述了,主要记录一下锚点行为的本质:通过改变容器滚动高度或者宽度亦可以说是修改scrollTopscrollLeft来实现(注意不是浏览器的滚动高度或宽度)。锚点的定位可以发生在普通容器元素上,并且由内而外,这个由内而外的意思是当普通元素和窗体同时可滚动的时候,会由内而外触发所有可滚动窗体的锚点定位,假设目前一个是容器盒子的锚点定位,另一个则是页面的视窗锚点定位,即先定位到内部锚点再在整个页面视窗定位,见DEMO
  142、设置了overflow: hidden的元素仅是隐藏了滚动条,当内容溢出时,依然可以进行滚动。当然此时滚动条已经消失,无法通过鼠标滚轮进行操作,但是锚点定位还是可以使得页面滚动。
  143、结合笔记141和笔记142,可以通过锚点切换来做一些简单的选项卡切换动作。但是在笔记141中的锚点交互中存在由内而外触发锚点定位的页面跳动问题,所以我们可以使用另外一种锚点定位方式:focus锚点定位,即类似链接或按钮、输入框那种在被focus时发生的重定位现象。这种方式只要定位的元素在窗体当中,就不会触发窗体的滚动。见DEMO。操作的原理就是往列表里加入一个隐藏的input框并设置id,然后关联一个label,这一步其实跟那篇<<input与label标签的关联>>文章原理一致,只不过当我们点击关联label的同时也focus了我们的输入框,这才真正实现了滚动切换,并且这种focus实现还能通过TAB来控制。
  144、position: absolutefloat都兼具”块状化”、”包裹性”、”破坏性”等特性。但是当absolutefloat同时存在时,float属性是无效的,所以这两者没有理由同时出现。
  145、absolute元素的宽高百分比取决于它的包含块,而这包含块指的是该元素第一个position不为static的祖先元素。一些基本的计算规则:
  ①position: statc\relative以最近的块级元素祖先的content-box计算。
  ②positoin: fixed以根元素,即浏览器可视窗口大小计算。
  ③position: absolute前文提及。
  对于absolute元素,内联元素也能成为它的包含块;包含块不是它的父级元素,而是最近的非static祖先或根元素;边界取padding-box
  146、在移动端,列表和模块域往往会有一定的留白来反馈手指按压的感觉,比如加深颜色背景,这种留白往往都是通过padding来实现的,那为什么不用margin呢?因为margin box永远是透明的。
  147、在页头放置一个标签,使用透明border设置,可以规避paddingtop/right这种方向属性的耦合(两者的数值都要同时修改)。
  148、absolute是非常独立的CSS属性值,起样式和行为表现不依赖其他任何CSS属性就可以完成。我们很多时候使用绝对定位的时候,都习惯在外层嵌套一层relative控制,但其实它自己就能完成这件事,见DEMO。作者将那些没有设置方向属性left/top/right/bottom的绝对定位称为”无依赖绝对定位”,它可以理解为不占据空间的相对定位。见DEMO。后面作者举的输入框校验提示语的DEMO也很亮,就是利用absolute的不占据空间的优势而不会破坏最初定好的容器总宽度。传送门。虽然以上足以说明”无依赖绝对定位”好处多多,但是最好只在静态交互效果上使用,如导航二级菜单的显示与定位。
  149、IE9及其以下版本的浏览器不支持placeholder占位符效果。那怎么模拟呢?可以使用前文提到过的labelinput关联,然后focus转变样式,定位使用前面的”无依赖绝对定位”就很合适,不会占据空间。
  150、absolute在遇到left/top/right/bottom后才真正具有绝对定位的特性,如果仅有一个方向设定了值,那么没有设定值的方向依然保有相对特性。
  151、前文中,我们曾提到过当对立方向同时发生定位的时候会产生”格式化宽度”,对于absolute元素而言,当它具备”格式化宽度”时,也同时具备了流体特性,如果包含块的padding box发生变化,这个块的宽度也会跟着一起变。
  152、如果想让绝对定位元素宽高自适应于包含块,没有理由不使用流体特性写法。因为其不仅跟普通元素持有一样的水平流动性,在垂直方向上它也可以保持流动性。
  153、当绝对定位元素处于流体状态的时候,它的盒模型相关解析和普通流体元素都是一模一样的:
  ①:margin负值可以让元素尺寸更大。
  ②:一侧margin定值,一侧autoauto为剩余空间大小。
  ③:如果两侧均为auto,则平分剩余空间。
  ④:绝对定位元素的margin: auto从IE8开始才支持,而普通元素的很早就支持了。
  ⑤:百分比transform在部分场景可能会造成IOS微信闪退。
  154、relative定位具有”无侵入性”,即relative元素自身进行偏移时,不会影响周围元素的布局。见DEMO
  155、关于relative的定位问题:
  ①:letf/top/right/bottom的百分比值是相对于包含块计算的,垂直方向上的属性百分比值计算跟height的百分比值一样,都是相对高度计算。所以当包含块高度是auto时,计算值为0,会导致偏移无效。即我们要注意到父元素没有设定高度或者不是”格式化高度”的情况。
  ②:relative的对向属性同时出现的时候,和absolute表现非常不一样;当水平方向属性同时出现,只保留left;当垂直方向属性同时出现,只保留top。因为默认文档流是从左到右,自上而下的。
  156、relative的最小化影响:
  ①尽量不要使用relative,如果想定位某些元素,可以考虑是否能用”无依赖绝对定位”,优势在笔记148中有记录。
  ②如果场景受限,必须使用relative时,务必使其最小化,这个最小化可以理解为便于之后的维护以及规避场景复杂后的样式问题。前文中,我们曾提到过relative有无侵入性,即它能够保证不影响之后的元素布局。按书中的一个例子,场景是在某个模块右上角定位一个图标:

1
2
3
4
5
<img src="xx.jpg" style="position: absolute; top: 0; right:0;"> <!-- not good -->

<div style="position: relative"> <!-- better -->
<img src="xx.jpg" style="position: absolute; top:0; right:0;">
</div>

  其实这种relative限制还有一个好处,那就是层叠级别提升relative比普通元素的层级要高,那么后面的元素就不会出现可能覆盖前者的情况。
  157、position: fixed正常来讲,不管在啥地方,都是根据根元素即html来定位的;但我们可以操作一波把它也按照我们的想法根据包裹的父容器定位,因为fixedabsolute一样,在没有方向属性的时候具有相对定位特性。
  158、position: fixedabsolute模拟:说实话一开始我看这个解释挺懵逼的,什么既不跟随滚动,又被定位元素限制。后面看了下DEMO代码大概能理解其行为了:

1
2
3
4
5
6
<html>
<body>
<div class="page">
<div class="fixed">
</body>
</html>

1
2
3
4
5
6
7
8
9
10
11
html, body {
height: 100%;
overflow: hidden;
}
.page {
height: 100%;
overflow: auto;
}
.fixed {
position: absolute;
}

  首先同时适配移动端隐藏根的滚动条,然后自行生成一个page容器来配置滚动条,最后将绝对定位元素脱离文档流塞进去。由于这个绝对定位元素不在这个滚动容器内,所以它不会滚动,ok符合第一种情况,然后自身绝对定位,可以使用relative或者overflow等定位剪裁,满足第二个情况。
  那么这种模拟可以应用在哪种场景呢?比如说我们有一个Modal框点击然后会弹出一个蒙层,如果通过fixed定位,蒙层会无法覆盖浏览器右侧的滚动栏,即当有滚动条时,背景内容在蒙层下依旧可以滚动,无法被锁定,但是如果用absolute模拟这种问题就被修复了。
  不过,如果我们的页面结构已经固定了,不太适合全局调整的时候,可以结合JS,移动端,我们阻止touchmove事件就能防止滚动,PC端可以通过overflow: hidden来隐藏,但这么玩前文中有记录,会导致页面晃动,因为滚动框也占据了可视宽度,我们可以通过透明border修复这个问题:
  蒙层显示:

1
2
3
4
5
6
7
var widthBar = 17; //通常情况是17px
var root = document.documentElement;
if (typeof window.innerWidth == 'number') {
widthBar = window.innerWidth - root.clientWidth;
}
root.style.overflow = 'hidden';
root.style.borderRight = widthBar + 'px solid transparent';

  蒙层隐藏:

1
2
3
var root = document.documentElement;
root.style.overflow = '';
root.style.borderRight = '';

  159、CSS层叠上下文和层叠水平:其实关于层叠的问题,我在<<CSS特指度与布局层叠顺序>>一文中曾经结合水印需求讨论过一次,不过那个时候其实只是取了作者博客中的一张图示,在这本书中其实有更为细致的讲解:
  ①谁大谁上:当具有明显的层叠水平标识时,如z-index,在同一层叠上下文领域,层叠水平值大的那一个覆盖小的那一个。
  ②后来居上:当元素层叠水平一致、顺序相同时,DOM流处于后面的元素会覆盖前面的元素。
  ③独立性:每个层叠上下文和兄弟元素独立,进行层叠变化或渲染的时候,只需要考虑自身的后代元素;且元素发生层叠的时候,整个元素被认为在其父元素的层叠上下文当中。
  ④根元素html本身就具有层叠上下文。
  ⑤对于positionrelative/absolute以及FF/IE下含有position: fixed的元素(注意不包括Chrome)当它们的z-index不是auto时,会创建层叠上下文。这里可以参见一个提供的DEMO。从DEMO中看到,当元素默认z-indexauto的时候就是一个普通定位元素,容器内的元素进行层叠比较将不会受到父级的影响,可以通过①和②的规律来判断。就算z-index的值为0,它也会创建层叠上下文;所以DEMO中,相当于后面的覆盖了之前的,内部由于两块都是独立的层叠上下文,都作用在自己的父容器当中,故不会作用于外面对比,真正进行比较的是两个父容器。另外,作者提及在IE6/IE7下,z-index: auto同样会创建层叠上下文;以前的position: fixedabsolute/relative一样都需要z-index有值才会产生层叠,但是后面,在-webkit-内核的浏览器中fixed定位不需要z-index就可以产生层叠,而IE和FF还是和以前保持一致。
  160、clip从英文看就可以知道是个剪裁属性,并且它仅在positionfixedabsolute时生效,它的基本语法为clip: rect(top right bottom left)clip: rect(top, right, bottom, left)这种有逗号的写法其实才是标准的,不过前者兼容性更好,IE6、IE7也支持,并且字符更少。那么它的应用场景在那里呢?
  ①首先是对fixed定位进行裁剪,因为fixed本身的包含块是htmloverflow虽然也能进行剪裁作用,但是它主要还是应用于普通元素或绝对定位元素,对fixed元素除了滚动条区域,其他区域也没办法操作。
  ②隐藏主页上SEO的文本,仅展示图片,比如:

1
2
3
<a href="/" class="logo">
<h1>CSS世界</h1>
</a>

1
2
3
4
.logo h1 {
position: absolute;
clip: rect(0 0 0 0); /* 相当于整块切割了 */
}

  这种做法与其他的一些隐藏做法相比优势在于具有更强的普适性,任何元素和场景都可以无障碍使用(我们前文有记录过一些隐藏元素的方案,但是像vibility: hidden;display: nonetext-indent: 足够到屏幕外的负值这些最终都会导致屏幕阅读设备无法读取)。同时元素原本的行为特征也被保留,比如原本能够被focus的元素,即使剪裁了依旧能够继续focus,再利用”无依赖绝对定位”的特性可以实现一种替换默认按钮样式的hack操作。文中提供了一个使用关联label替代input的提交按钮做法:

1
2
3
4
.clip {
position: absolute;
clip: rect(0 0 0 0);
}

1
2
3
4
<form>
<input type="submit" id="someID" class="clip">
<label for="someID">提交</label>
</form>

  以上,书中有一种”可访问隐藏”的叫法我觉得挺不错的,并且在如何进行隐藏的方案中,color: transparent是移动端推荐的做法,但是在PC端IE8浏览器并不支持。
  作者对clip的总结:
  ①clip隐藏仅仅是决定哪部分可见,非可见部分无法响应点击事件;
  ②视觉上隐藏,但是元素尺寸依然是原本尺寸;IE/FF浏览器下抹去了不可见区域尺寸对布局的影响比如生成的滚动条,Chrome则保留了影响。