Jun 24

结论:

CSS是一种描述文档样式的语言,它不依赖于HTML,可以用于许多其他标记语言。它也不只是用于视觉媒介,还用于听觉媒介。

在CSS的世界里只有线框,用CSS思考就是用线框去思考,它给文档上所有可视或可读的东西都画了线框。这些线框的嵌套关系和文档结构上元素嵌套关系是不一样的,特定的排版方式都会改变它们的嵌套关系。首先确认线框的嵌套关系,再确认这个线框里所有线框的互相影响,记住关于尺寸,摆放位置,材质皮肤的计算规则。

我觉得把box翻译成盒子是欠妥的,还不如线框。在中文里盒子是个立体实物的概念,如果用盒子去理解CSS box会带来不必要的副作用,CSS更适合用传统印刷排版术语来理解。比如子box溢出父box的情况,如果用盒子去理解就会很怪,但用线框去理解就简单多了,类似出版术语bleed。在印刷排版领域大量使用的框术语,和CSS的box极其类似,为什么不直接用,非要生造个盒子出来。其实不光是box,还有很多地方的翻译都能套用排版术语。

最新的草案描述和老规范的术语定义区别大。而且现在CSS规范划分成独立的子模块形式发布,一些基础模块的术语定义没有确定,造成依赖这些模块的其他模块术语定义也很混乱。阅读不同模块规范能发现互相用到了相同术语,但是定义却不一样。他们换了不同的说法描述这些规则,他们想建立更好的术语体系。

规范是对现实中厂商的具体实现方案和开发者的具体开发方案的标准化。其实就是让不同方案的主导者互相妥协,通过谈判达成一致意见,用来规范和要求不同的厂商和开发者必须按统一的方案执行。

Use tomorrow’s CSS syntax, today. http://cssnext.io/
这个类似JS的babel。让我们提前使用CSS新规范的内容,而不用等到浏览器支持。但是因为CSS的特殊性,cssnext和babel比起来,还太low了。在CSS这块,估计在很长时间里都只能使用老旧但安全的方案。

关于不同浏览器的坑,就该http://browserhacks.com/https://modernizr.com/上场了。browserhacks可以找到hacks方案。
modernizr提供了优雅降级或渐进增强开发方案。先确实页面需要使用哪些CSS特性,然后用modernizr检测,如果用户浏览器不支持某个CSS特性,采用什么替代方案。modernizr提供了方便强大的检测功能,会为使用了新CSS特性,但浏览器却不支持的元素自动添加特定CSS类名,方便开发者完成替代方案的编写。

理解CSS规范: 就算你不是一名计算机科学系的学生,甚至不用满十八岁或拿到学士学位,都可以读懂 W3C 的 CSS 文档,前提是你得乐于钻研,能耐下心,以及注重细节。 http://www.chinaw3c.org/archives/369/

最新CSS规范草案 https://drafts.csswg.org/

 

相关内容汇总:

一个文档和一个文件是不一样的。不过你可以在一个文件中存入一个文档。

你现在读的这个文档没有存在一个文件中。当你的浏览器请求这个页面,服务器查询一个数据库并且生成这个文档,这个文档的组成部分采集自不同的文件。

在正式的CSS术语中,把文档呈现给用户的程序叫做用户代理者user agent(UA)。浏览器只是UA的一种。CSS不仅仅只用于浏览器或视觉呈现。

CSS Writing Modes
CSS书写模式模块定义了CSS支持的国际上多样的书写模式,比如从左向右left-to-right,从右向左,双向,垂直向。

在CSS中是通过writing-mode, direction, text-orientation属性决定采用哪种书写模式。书写模式的基础术语是inline base direction and block flow direction:

inline base direction是指在一行内的内容按一个方向排列的这个方向,定义了一行的开始start一侧和结束end一侧。direction属性指明了一个线框的行内基准方向,它和unicode-bidi属性,文本内容的固有方向,共同决定了一行内的inline-level内容的排列。

block flow direction是指在一个块容器内的block-level线框按一个方向堆叠成一行的这个方向。writing-mode属性决定了block flow direction。

property
Name: direction (inline-level)
Value: ltr (left-to-right) | rtl (right-to-left)

Name: writing-mode (block-level)
Value: horizontal-tb (top-bottom) | vertical-rl (right-left) | vertical-lr (left-right) | sideways-rl | sideways-lr

补充说明:

新规范增加了很多start和end为后缀的属性值,它们和书写模式writing-modes相关,start和end所表示的方位是会变化的,最终的确切方位,依赖于writing-mode属性,direction属性,或者以direction为后缀的属性。通常都是从上边开始(top start)到下边结束(bottom end)的垂直向vertical和从左边开始(left start)到右边结束(right end)的水平向horizontal。

 

CSS Cascading and Inheritance

这个CSS模块描述如何整理样式规则和赋值给所有元素的所有属性。通过级联和继承的方式,所有元素的所有属性的值是可以传播的。

CSS的一个基本设计原则就是级联,它允许不同的样式表同时影响一个文档的呈现。当不同的声明尝试设置同一个元素的同一个属性的值时,就需要以某种方式解决这种冲突。当没有声明尝试一个元素的一个属性时,与前面相反的问题出现了。在这种情况下,通过继承或者通过寻找属性的初始值的方式发现一个值。级联和默认进程获得一组声明作为输入,然后为所有元素的所有属性输出一个指定值。这个规范描述了为文档中所有元素的所有属性发现一个指定值的规则。

Value Processing
1. Declared Values
2. Cascaded Values
3. Specified Values
4. Computed Values
5. Used Values
6. Actual Values

Filtering 过滤
首先找出应用于各个元素的声明值,生成每个元素的声明值列表。可能元素没有声明值,则是个空列表。

Cascading 级联
按声明的优先权重新排序每个元素的声明列表,得到级联值列表,列表中第一个作为级联值。如果是空列表,则没有级联值。赢得优先权的规则,Origin and Importance,Scope,Specificity,Order of Appearance。

Defaulting 默认处理
如果没有得到级联值,则默认使用继承值或者初始值。
Initial Values
每个元素都有个初始值,如果元素属性既没有级联值,也没有继承值,则使用初始值作为指定值。
Inheritance
一个元素的属性的继承值是来自其父元素同名属性的计算值,根元素没有父元素,那么属性的继承值就是属性的初始值。只有部分属性默认就是继承属性,不是继承属性的,可以通过给属性赋值inherit,使其变成继承属性。
如果一个属性的级联值是unset关键字,则使用属性的继承值或初始值,根据其是否为继承属性。
如果一个属性的级联值是revert关键字,则回滚到其origin值。

补充说明:

常用的默认继承属性,’color’ ‘font’ ‘letter-spacing’ ‘line-height’ ‘list-style’ ‘text-align’ ‘text-indent’ ‘visibility’。

Filtering对应Declared Values,Cascading对应Cascaded Values,Defaulting对应Specified Values和Computed Values,最后是Used Values,主要是把Computed Values中还剩下的相对值计算为绝对值,通常是些依赖最终排版结果的属性,比如元素的width属性Computed Values就可能还是auto,要换算为绝对长度,通常单位为像素的具体数字。Actual Values通常和Used Values一致,但因为UA实现和规范可能存在差异造成值不一样。

CSS Object Model中还有个Resolved Values的概念,它是对getComputedStyle()方法的返回的样式值的定义,大部分样式属性值是Computed Values,少部分是Used Values,比如宽高,上下左右,边距是Used Values。

 

Selectors Level 4

选择器类别
ID selectors E#id
Class selectors E.class
Pseudo-class E:hover
Attribute selectors E[attr] E[attr=”val”]
Type (tag name) selector E
Pseudo-elements E::before E::after E::first-line E::first-letter
Universal selector *

selectors 3新加的常用选择器
E:not(s1, s2)
E:nth-child(n [of S]?)
E:enabled
E:disabled
E:checked
E[foo^=”bar”]
E[foo$=”bar”]
E[foo*=”bar”]

combinator
E F or E >> F
E > F
E + F
E ~ F

Calculating a selector’s specificity
计算选择器的权重

选择器权重的计算步骤如下:
在一组选择器中ID选择器的计数(=A)
在一组选择器中class类选择器,attribute属性选择器,pseudo-classes伪类的计数(=B)
在一组选择器中type类型选择器和pseudo-elements伪元素的计算(=C)
忽略universal通配选择器

如果选择器是一个选择器列表的形式,计算列表中每组选择器的数量,整个列表中,用权重最大的那组选择器应用于元素。

权重的比较是通过按顺序的比较三个部分完成。用A部分权重大的那个;如果A部分相同,用B部分权重大的那个;如果B部分还相同,用C部分权重更大的那个;如果所有都相同,那么两组选择器的权重是相等的。

由于存储限制,解析器可能限制每个部分的大小。如果这样,超出的会被强制转换成最大值,不会溢出。

补充说明:

记住一组选择器中选择器的所在位置和ABC没有关系,有关系的只是同类型选择器出现的次数。
比如#a .b 和.a #b,这两组选择器的ABC是一样的,都是A=1 B=1 C=0,也就是说它们的权重是相等的。

注意:selectors-4和selectors-3在ABC分类的规则上是一样的,但比较方式不一样,selectors-3老规范是把ABC按一个规则算出一个总数后比较,selectors-4新规范是按顺序依次比较,而且只有当前面的相等后才继续比较后面的。

最终应用于元素的样式,选择器权重Specificity只是样式优先权规则的一个因素。其他因素有Origin and Importance,Scope,Order of Appearance。

权重大优先于小的,权重相等的,看其他因素。
CSS Device Adaptation Module

The viewport
在老规范里面,viewport术语只适用于continuous media,@viewport applies to continuous media, and @page to paged media。现在viewport适用于所有media。

这个规范介绍了一种通过the user agent (UA)重写viewport尺寸的方法。 因此我们需要提出初始视口the initial viewport和实际视口the actual viewport的不同。

initial viewport
初始视口是指在任何UA或作者的样式把UA的屏幕窗口或可视区域的视口覆盖前的那个视口。注意初始视口的尺寸将随着UA的窗口或视区的尺寸而变化。
actual viewport
实际视口是指通过串联所有样式表的视口描述符viewport descriptors,并且按CSS规则应用后的视口。
当实际视口不能全部显示于当前UA的窗口或视区时,如果不是因为实际视口大于初始视口,那就是因为缩放导致实际视口只能显示部分。UA应该提供滚动条或者拖拽机制。
也就是初始视口是最终显示媒介的可视区域尺寸,而实际视口则是样式表指定的尺寸,可以设置得和初始一样,也可以比它大,如果大了就会有部分内容看不到,需要滚动或拖拽才能看到。比如window.innerWidth/Height就是initial viewport的尺寸。document.documentElement.clientWidth/Height就是actual viewport的尺寸。

如果文档根元素的方向direction属性值是ltr,推荐实际视口的左上角和UA窗口或视区的左上角是对齐的,同理,direction属性值是rtl则右上角对齐。

Media Queries

由于渲染文档的媒介有很多,初始包含块的尺寸和设备方向都会影响一个媒介查询计算的结果,意思是在media queries上要特别注意@viewport rules的影响。

补充说明:

@viewport { 
    width: device-width; 
    zoom: 1; 
} 

指定设备宽度相匹配

 

Media Queries Level

媒介查询允许作者检测和查询UA或显示设备的值或者特征,据此把文档渲染成独有的样式。通过CSS @media rule按条件给文档应用不同的样式。

Media Queries Level 4叙述了媒介查询 Media Queries,媒介类型Media Type,媒介特征Media Features的句法和机制。

一个媒介查询是一个逻辑运算表达式,它的值是true或false。由media type和media condition两部分组成,如果都为真,那么这个表达式的值为真,否则为假。

多个媒介查询可以合并成一个用逗号分隔媒介查询列表。

媒介类型是指UA的宽泛类别。最初媒介类型集合的定义是在HTML4规范中,用于link元素的media属性。

从以往情况看,Media Types不能很好的区分日益复杂的UA情况。所以放弃了扩展媒介类型来解决问题,而是采用更精细的Media Features。句法上,media features看起来像CSS属性。每个媒介特性分两大类,范围range类或者单独discrete类。范围类特性的名字通常带有min-或max-这样的前缀。单独类特性值通常是规范指定关键字或者布尔数字0或1之类。

多个媒介特性可以使用逻辑运算符(not and or)组成一个媒介条件判断语句。

补充说明:

Media Queries
media_query_list:  [,  ]*
media_query: [[only | not]?  [ and  ]*] |  [ and  ]*
expression: (  [: ]? )
media_type: all | handheld | screen |*
media_feature: min-width | max-width  | min-height | max-height  | orientation |*

@media not|only mediatype and (media feature) {
}

 

CSS Display Module

这个模块描述如何从文档元素树the document element tree生成CSS编排线框树CSS formatting box tree,并且定义了display和box-suppress属性,用来控制线框boxex。

The viewport and the canvas 视口和画布 视口是浏览文档的Media的可视区域。对于所有媒体来说,术语画布用来描述格式化结构体渲染后的显示空间。这个画布的尺寸是无限的。

CSS是一种描述结构化文档(比如HTML和XML)在显示屏,印刷品,语音流等媒介上如何渲染的语言。

CSS把一个组织成元素树的源文档渲染在画布canvas上(比如显示屏,一张纸,一段语音流)。要做到这点,它生成一个中介结构,线框树box tree,它表示已渲染文档的编排结构。

每个线框表示它对应的元素或伪元素在画布上出现的空间或时间。

创建线框树box tree的过程。

CSS首先使用级联cascading和继承inheritance规则给源节点树上的每个元素的每个CSS属性赋一个值。

然后按每个元素的display和box-suppress属性设置来为其生成零个或多个线框boxes,通常一个元素生成一个单独的线框box。然而一些display属性值 (e.g. display: list-item)会生成多个线框 (e.g. a principal block box and a marker box),并且一些属性值(比如display:none, display: contents, and box-suppress: discard) 会造成这个元素或者其后代根本不生成任何线框boex。

除非另有说明,线框boxes的样式和生成它们的元素一样。它们通常被叫成它们的显示类型display type,比如一个display属性是block的元素生成的线框box叫做块状线框“block box”或者块“block”。

一个匿名线框anonymous box是一个不与任何元素相关的线框box。

匿名线框Anonymous boxes是在需要特殊组织线框树the box tree的情况下生成,这种情况是需要一个特殊的嵌套结构,这个结构中的线框boxes不是从元素树生成的。

例如,当一个table cell box需要一个特殊类型的父box (the table row box)的时候,如果它的父box不是一个table row box,将生成一个anonymous table row box来嵌套它. (See [CSS2] § 17.2.1.) 不同于元素生成的box,元素生成的box样式是严格通过元素树继承的,只存在于box tree中的匿名boxes样式继承自它们的box tree。

在排版的过程中,一个box线框可能拆成多个片段. 是这么发生,例如, 当一个inline box分拆穿过多行的时候, 或者当一个block box分拆穿过一页或一列的时候,因此一个box由一个或多个box片段组成. See [CSS3-BREAK] for more information on fragmentation.

 

CSS basic box model

CSS假定文档的呈现是以元素树为模型。每个元素是一个拥有零个以上子元素的有序列表,和一个可选的文本字符串,在这个列表前后以及子元素之间。每个子元素都有一个父元素,除了唯一一个元素没有父元素,它叫做根元素。

CSS描述每个元素element和每个文本字符串string of text如何从文档树模型转换为一组矩形框rectangular boxes来排版,其在画布上的尺寸,位置,堆叠层级都依赖于boxes的属性。

我们说一个元素生成一个或多个线框boxes。它们是许多不同类型的线框boxes。

The flow 流,有时也叫做normal flow正常流,是CSS中排版的两个基本类型之一,另一个是line layout [CSS3LINE]。其他CSS模块, 比如tables [CSS3TBL], positioning [CSS3POS], flex boxes [CSS3-FLEXBOX] and grid templates [CSS3LAYOUT]都是基于流模型flow model实现的,通过把一个文档分拆成不止一个流,在画布上通过这些不同的流来进行定位和校准。

一个flow是从一个box开始构建,当一个box满足以下规则时,它叫做flow root:
The value of ‘float’ is not ‘none’.
The used value of ‘overflow’ is not ‘visible’.
The value of ‘display’ is ‘table-cell’, ‘table-caption’ (see [CSS3TBL]), ‘inline-block’ or ‘inline-table’.
The value of ‘position’ is neither ‘static’ nor ‘relative’ (see [CSS3POS]).
The value of ‘block-progression’ is ‘lr’ or ‘rl’ and the value of ‘block-progression’ of its parent box is ‘tb’
The value of ‘block-progression’ is ‘tb’ and the value of ‘block-progression’ of its parent box is ‘lr’ or ‘rl’.

flow root术语在CSS level 2 规范中定义是不同的. 在老规范中一个flow root定义为 “an element that establishes a new formatting context.”

我们说flow从flow root引出。注意flow root本身不是它引出的流flow的一部分,每个flow root最多引出一个flow。

一个flow root的flow是一组boxes。当一个元素的box是flow root,而且它的子元素的box满足以下规则时,则属于这个flow:
The used value of its ‘display’ is ‘block’, ‘list-item’, ‘table’ or <template>.
The used value of its ‘float’ is ‘none’.
The used value of its ‘position’ is ‘static’ or ‘relative’.
It is either a child of the flow root or a child of a box that belong to the flow.

注意元素树element tree和框树box tree不见得一样,比如在DOM树中的某个元素的框,通过position属性的改变,它的框的父框,可能不是父元素的框,而是某个祖先元素的框。

如果需要一个box忽略前后的floating box影响时,则可以把它的clear属性值设为和前后box的float一样的值,或者both。

注意由于一个浮动元素是一个flow root,对这样一个元素设置‘clear-after’,仅去掉了这个元素自己flow里子孙的浮动。

 

补充说明:

改变所有元素的box模型,默认是box-sizing: content-box;改为box-sizing: border-box;这样指定的width和height包含了内边距padding。

*, *:before, *:after { box-sizing: border-box; }

margin/padding之类速写属性的写法,一个值是表示全部;两个值表示vertical(top bottom),horizontal(left right);三个值表示top,horizontal(left right),bottom;四个值是top, right, bottom, left(顺时针)。

默认书写模式下,当元素box的float属性值不为none默认值时,它会从父box的flow中分离出来,生成一个新flow,并且会浮动在原来父box内的左边或者右边。如果前面的兄弟box也是相同的浮动属性值,则会浮动在其旁边。前面的兄弟块级元素box的float值是none,则会浮动在它下面。后面的其他普通兄弟块级元素box会忽略浮动元素的box尺寸,但是后面元素包括后代在内所有行内元素环绕会在前面第一个浮动元素box旁,如果float是left,则在box右边,如果float是right,则在box左边。

如果引入containing block概念,则float元素的containing block和父元素的containing block一样。float值为left,则float on the left side of its containing block,float值为right,则float on the right side of its containing block。

inline-start和inline-end依赖书写模式,inline-start是float on the start side of its containing block,inline-end是float on the end side of its containing block。

containing block是用于box的位置和尺寸计算的矩形框。通常containing block就是一个box。一个box的containing block不一定就是父元素的box。

记住float元素神奇的margin负值特性。虽说依次相邻的float元素在排版上就像inline-block,但是当新行第一个float元素的margin的负值大于自身的宽度时,会重新回到上一行,后面元素叠在前面元素上面。利用这个特性,可以实现特别的布局。

浮动元素、inline-block 元素、绝对定位元素的 margin 不会和垂直方向上其他元素的 margin 折叠。

浮动元素的 margin 在垂直方向上也不会发生 margin 折叠,即使和它相邻的子元素也不会。

清除浮动(clearfix hack)
解决原父box忽略浮动box的高度
用于父元素的常用方法,选一个就行。IE11之前的IE已死,如果非要照顾IE6/7,可以加上zoom:1触发hasLayout。

.clearfix { overflow: auto; }
.clearfix :after{ content: ""; display: block; clear:both; }
.clearfix { display: table; }

 

CSS Positioned Layout Module

这个模块包含关于定位元素和叠加元素的CSS level 3特性。

CSS Positioned Layout Module最新草案的术语定义还是老的,它依赖CSS basic box model,可还没用CSS basic box model新草案的相关术语定义。CSS basic box model新草案定义‘position’ is neither ‘static’ nor ‘relative’则生成新的flow。而且flow也和formatting context术语没有关系了。

本模块描述了如何安排元素树中任何元素的位置,而不依赖于其在文档结构中的顺序。(即从“流”中取出)

Containing Blocks 包含块

在CSS中,许多线框boxex的位置和尺寸是相对于一个矩形框的边缘计算的,这个矩形框叫做包含块containing block。在一般情况下,生成的框就是其包含的子框的包含块; 我们说一个框为包含的子框“建立”了一个包含块。短语“一个框的包含块”的意思是“这个框存在于这个包含块内”,而不是说这个框生成的包含块。

每个框安排的位置都是相对于它们的包含块,但它们不受包含块限制,它们可能溢出。也就是说包含块只是提供了一个参考坐标体系。

根元素的顶层box的包含块是一个视口尺寸的矩形,这个包含块叫做initial containing block 初始包含块,The containing block of the root element根元素的包含块。

一个元素的线框box的位置和尺寸往往是相对于一个确定的矩形计算出来的,这个矩形叫做元素的包含块。

元素box的position属性,默认值是static,The top, right, bottom, left and z-index properties 无效。

默认书写模式下:

当元素box的position属性值是relative时,保留了box占位空间。设置box位置坐标时,用的是原始containing block左上角为原点的坐标体系。

当元素box的position属性值是absolute时,生成新的flow,不再影响原flow中box排版,设置box坐标时,用的是最近的position属性不是static的祖先box的containing block 左上角为原点的坐标体系,如果没有这样的祖先box,则是以根box的containing block左上角为原点。

当元素box的position属性值是fixed时,生成新的flow,不再影响原flow中box排版,设置box坐标时,用的是以视口左上角为原点的坐标体系,无视滚动条。它的containing block is the viewport。

当元素box的position属性值是sticky时,就是relative和fixed的结合,它通过一个临界点sticky offset设置把box的position切换成relative或fixed。

当元素box的position属性值不是static时,可能会出现box重叠的情况,这时候可以设置它们的z-index属性来调整它们的Z轴顺序,大的在上面。

 

补充说明:

当根元素到父元素高度或宽度是100%,当前元素position属性值是absolute时,位置属性是top:0; bottom:0;或left:0; right:0时, 可以达到其高度或宽度是100%效果。当配合其他固定宽高元素时,通过修改位置属性,可以实现自动填满剩余空间,实现类似FlexBox的伸缩排版。

如果元素position值指定为absolute或fixed,则就算float指定值非none,实际值为none, 就算display指定值为inline类别的值,实际值也为block类别的值。

在元素position值不为absolut或fixed时,float值指定为非none时,则就算display指定值为inline类别的值,实际值也为block类别的值。

position:relative对table-*-group, table-row, table-column, table-cell, table-caption无效。

position排版的居中方法

.container {  
  position: relative;  
}

Absolute Centering,居中元素的高度类别属性必须显式赋值。

.center1 {  
  width: 50%;  
  height: 50%;  
  overflow: auto;  
  margin: auto;  
  position: absolute;  
  top: 0; left: 0; bottom: 0; right: 0;  
}

Transforms Centering

.center2 {   
  width: 50%;  
  margin: auto;  
  position: absolute;  
  top: 50%; left: 50%;  
  transform: translate(-50%, -50%);  
}

 

CSS Multi-column Layout Module

一个多列元素是指一个元素的’column-width’或’column-count’属性值不是’auto’,因此作为一个多列排版的容器。

在传统CSS线框模型CSS box model中,元素内容是直接属于元素内容线框box。多列排版在内容box和内容之间引入了新的类型容器,叫做列box。一个多列元素的内容是属于它的列box。(应该就是CSS Display Module规范中所说的匿名线框anonymous box)。

在多列元素中,列线框column boxes排列成行。就像表格单元格,列框在行内是按多列元素的横线方向有序排列。列的宽度是这个列框在横线里占的长度。列的高度是这个列框在竖线里占的长度。在一行里面所有列框的宽度是相等的,高度也是相等的。也就是把横线均分为相等长度的线段。在多列元素的每一行里面,相邻的列框有列间隙隔开,也可以有列界线。如果它们出现在同一行内,所有间隔都是相等的,所有列界线也是相等的。列界线仅出现在两个有内容的列之间。

在最简单的情况下,一个多列元素一列只有一行,并且每一列的高度值和这个多列元素的内容线框box的高度值是相等的。如果多列元素跨页了,那么它每行的高度受制于页面,结构上连续的内容跨页后,另一页的部分属于新行的新列框。一个列框是不会分到不同页面的。

同样的结果出现在一个spanning element分割多列元素时,当多列元素内一个元素的column-span属性为none时,是适用于正常分列规则,当column-span属性为all时,它将建立一个新行的列框。

不可能去设置列线框column boxes的属性值,例如,设置一个列框的background,padding,margin,border属性。将来可能会支持。。。

列框Column boxes充当它们内容的包含块containing block。就是说列框column boxes的表现就像CSS21规范里的block-level, table cell和inline-block boxes。不管怎样,column boxes不会为它所属的多列元素建立用于定位属性‘position: fixed’ or ‘position: absolute’的包含块containing blocks。

column box内容的样式值是基于column box计算的。

‘columns’属性是一个速写属性,用于设置’column-width’ 和 ‘column-count’属性.

实际column box的宽度可能会和设置的column-width属性值不一样,它受到多列元素的width值影响,可能大于或小于设置的值,如果把元素按column-width均分后,小于元素宽则会自动加宽,大于元素宽,则会自动变窄,最终实际的column-width乘以column-count,再加上column-gap的宽度后等于元素的width。

列间距gaps和界线rules存在一个多列元素的列之间。它们的长度等于列的长度,是说竖线方向的长度,也就是高度是相等的。列距是占空间的。就是说,列距会推开同一个多列元素里相邻列的内容。

列间距属性column-gap 列界线属性column-rule

列界线是画在列间距中间,并且终点在元素上下边上。列界线是不占空间的。就是说,列界线的存在不会影响任何排版相关的属性值。如果线的宽度超过了间距,则看起来是叠在列框上面,甚至可以超出整个框。界线刚好在元素的背景上面。多列元素的后代元素可以用z-index属性值来叠到它上面。界线仅画在有内容的两列之间。

多列元素的后代元素,有很多属性可以改变默认的内容分割规则。比如break-,column-span之类的。

当一个多列元素的后代元素的column-span属性值为all时,可以独占一行,自成一列,而且列宽就是多列元素的宽度。

注意那种超过列宽的连续字母,无法对其实现分栏。

 

CSS Flexible Box Layout Module

伸缩线框排版

CSS 2.1定义了四种排版模式 – 决定线框boxes的尺寸和位置的规则系统,基于它和它的兄弟祖先线框boxes的关系:

1 block layout 区块排版,设计用于编排文档
2 inline layout 行内排版,设计用于编排文本
3 table layout 表格排版,设计用于编排表格形式的数据
4 positioned layout 定位排版,设计用于在文档中非常明确的定位,不用过多考虑其他元素

这个模块介绍一种新的排版模式,flex layout伸缩排版,设计用于更多复杂的应用和页面。

伸缩排版flex layout表面上看类似区块排版block layout。它缺乏许多在区块排版中用于更复杂的以文本或文档为中心的特性,比如浮动floats和多列columns。

作为交换,它获得了纯粹又强大的手段,用于空间分布和对齐内容,这常常是复杂web应用和页面需要的。

一个伸缩容器flex container的内容contents:

内容能往任何流方向flow direction排列(向左,向右,向下,甚至向上!)

内容的显示顺序能在样式层上反转或者重新排列(也就是说,看见的内容顺序可以和源码或语音流顺序无关)

内容能顺着单一主轴线排列或者把内容包入多行顺着十字交叉穿过主轴线的次轴线排列

内容的尺寸能伸缩响应可用空间的变化

内容能相对于所属容器对齐或者它们彼此相对次轴线对齐

内容能顺着主轴线折叠或不折叠,同时保留容器的次轴线长度

Flex Layout Box Model and Terminology
伸缩排版线框模式和术语

一个伸缩容器是由一个元素生成的线框,它的dsplay属性值是flex或者inline-flex。一个伸缩容器的流的孩子叫做伸缩项,它们的排版是采用伸缩排版模式。

不同于基于区块和行内流方向计算排版数值的区块和行内排版,伸缩排版是基于伸缩方向。为了让关于伸缩排版的讨论变得不费劲,这节定义了一组伸缩流相关flex flow–relative术语的集合。flex-flow属性值和书写方式决定了这些术语如何映射到物理方向 (top/right/bottom/left), 轴线 (vertical/horizontal), 和尺寸。

二维空间

main axis 第一维轴线
main dimension 第一维度
伸缩容器的第一维轴线是伸缩项排版采用的主要坐标轴线。它在第一维维度上延伸。

main-start 第一维开始
main-end 第一维结束
伸缩项被这样摆放在容器里,从第一维开始的一侧延伸到结束的一侧。

main size 第一维长度
main size property 第一维长度属性
一个伸缩项的宽或者高,哪个在第一维度上,它就是项目的第一维长度。项目的第一维长度属性就是项目的宽或者高属性,哪个在第一维度上就是哪个。

cross axis 第二维轴线 (和第一维轴线十字交叉)
cross dimension 第二维度
这条垂直于第一维轴线的轴线叫做第二维轴线。它在第二维度上延伸。

cross-start 第二维开始
cross-end 第二维结束
放满伸缩项的伸缩行被这样摆放在容器里,从第二维开始的一侧到结束的一侧。

cross size 第二维长度
cross size property 第二维长度属性
一个伸缩项的宽或者高,哪个在第二维度上,它就是项目的第二维长度。项目的第二维长度属性就是项目的宽或者高属性,哪个在第二维度上就是哪个。

一个元素的display属性值为flex,则生成一个区块级别的伸缩容器box。

一个元素的display属性值为inline-flex,则生成一个行内级别的伸缩容器box。

在伸缩box里面浮动box无效,伸缩box的margin不会和它内容的margin发生折叠。和区块容器一样,伸缩容器box就是它内容box的包含块。overflow属性在伸缩容器上也适用。多列相关属性无效,浮动相关属性float和clear无效,vertical-align属性无效, ::first-line and ::first-letter 伪元素无效,

宽泛的说,伸缩容器的伸缩项是表示它的流内容的线框。每个伸缩容器流的孩子都会变成伸缩项,没有子元素嵌套的文本,则会自动创建一个匿名线框把文本包起来,作为匿名伸缩项。匿名线框是没法独立应用样式,只能继承父元素的样式。

伸缩容器和其伸缩项的boxes也叫做flex-level boxes。和block-level boxes没关系。

相邻的伸缩项的margin不折叠。伸缩项的order属性可以设置其在所有伸缩项中显示顺序,而且它们是可以叠加的,z-index属性自动生效,默认值是auto。

伸缩项的visibility属性设置成collapse,这个不同UA实现不一样。看起来和visibility:hidden一样。有的隐藏但保留占位,有的隐藏不保留占位。

Display Order: the order property
Reordering and Accessibility
默认情况下,伸缩项的显示顺序和文档结构中内容顺序一样,可以通过order属性改变顺序。值小的在前面,可以用负数。

CSS一再强调,在组织文档结构时,不要考虑样式,一定要语义优先,语义为大。在具体显示的时候,完全可以用CSS实现和语义结构不同排版。CSS一般不会去改变文档的语义结构,它是通过为内容建立对应的box,用box去做重新的排版。

Flex Lines
伸缩项在伸缩容器中的排版,是排成一条线(横线或竖线)放在伸缩行(横行或竖行即列)里,假设容器用分组对齐的排版算法。一个伸缩容器可以是单行或者多行,取决于flex-wrap属性值:
一个单行的伸缩容器,比如flex-wrap: nowrap,它的内容都排版成一行,即使会溢出。
一个多行的伸缩容器,比如flex-wrap: wrap or flex-wrap: wrap-reverse,它的内容会分成多行,当一行满了就会把超出的内容分入新行。当追加的行创建时,它们是根据flex-wrap属性值沿着交叉轴线堆放。每一行至少有一个伸缩项,除非伸缩容器是空的。

Flexibility
伸缩排版的一个特点是,它可以让伸缩项伸缩。在第一维度上修改它们的宽或高去充满可用空间。这是用flex属性做到的。伸缩容器把空闲的空间分给伸缩项去充满容器,按伸展系数flex-grow的比例伸展,剩余空间的情况,或者按收缩系数flex-shrink的比例去收缩,溢出空间的情况。

如果flex-grow和flex-shrink的值是0,则伸缩项没有伸缩特性,值不是0,才可以伸缩。

flex属性是伸缩相关属性的速写属性,可以同时指定计算伸缩长度的属性值:flex-grow,flex-shrink,flex-basis。当一个box是flex item时,flex属性会征求取代main size属性来决定box的第一维长度。如果box不是一个flex item,那么flex属性无效。

flex-grow的值是数字,指定伸缩的伸展系数,它决定了一个伸缩项如何相对于同一容器中其他伸缩项来伸展长度,当确定有空闲空间分配的时候。如果在flex属性中没有指定,默认值是1。负值无效。

flex-shrink的值是数字,指定伸缩的收缩系数,它决定了一个伸缩项如何相对于同一容器中其他伸缩项来收缩长度,当空闲空间不够分配的时候。如果在flex属性中没有指定,默认值是1。负值无效。
注意:当分配有限空间的时候,收缩系数要乘以伸缩项长度。按百分比确定如何收缩,比如在特别长的项目大幅收缩前,短的项目不会收缩为0。

flex-basis是关键字或数字,指定伸缩项的初始长度采用哪种规则获得,然后用于和伸缩系数的运算。

当flex-basis值为auto时,检索flex item的main size属性的值用于flex-basis。

当flex-basis值是content时,表明为自动计算长度,基于伸缩项的内容。
注意:这个关键字是新加的,有些老的解析器可能不支持。它等同于flex-basis值为auto和main size为auto的情况。

其他情况值和伸缩项的宽或高的值规则一样。

如果在flex属性中没有指定,则默认值是0。

在flex属性中flex-grow,flex-shrink,flex-basis的默认值,和flex-grow,flex-shrink,flex-basis独立时的默认值不同。

flex属性常用配置:

flex: initial; 等同于 flex: 0 1 auto;
这就是默认值。基于伸缩项的宽或高属性确定伸缩项的长度。如果项目的main size属性计算为auto,那么项目的长度计算基于它的内容。当空间足够的时候,项目是固定长度。当空间不够,则项目的长度会收缩。

flex: auto; 等同于 flex: 1 1 auto;
基于伸缩项的宽或高属性确定伸缩项的长度。项目的长度会根据容器第一维长度情况,沿着第一维轴线按系数1来自动变长或短。如果多个项目中,同时有flex: auto, flex: initial, or flex: none的项目,则flex: auto的项目为自适应剩余空间。

flex: none; 等同于 flex: 0 0 auto;
基于伸缩项的宽或高属性确定伸缩项的长度。不能伸缩,可能会出现内容溢出容器的情况。

flex: <任意正数> 等同于 flex: <任意正数> 1 0;
伸缩项可以伸缩,并且基准数是0。按系数百分比分配空间。如果所有项都是这个属性配置,它们都会按指定系数的百分比来分配空间。

默认情况,flex item不能缩短到比内容长度还短,最小内容长度是最长的单词或固定长度的元素决定的。可以通过min-width或者min-height属性改变它。

规范鼓励作者使用速写法的属性,因为对于未指定值的属性组件,提供了常用的默认值。

Alignment
当完成了display属性值为flex或inline-flex的伸缩容器的flex-flow属性,内容的order属性值和flex属性配置,确定了伸缩的定向,排序,长度计算规则后,可以开始搞对齐校准了。

伸缩项的对齐校准,是通过margin属性和CSS Box Alignment类型属性。

margin值为auto的伸缩项表现和block流中的margin值为auto的box类似:

在计算伸缩基准值和伸缩长度时,自动外边距相当于「0」。
在使用「justify-content」和「align-self」控制分布对齐前,在对应维度上的所有正值空闲空间会分配给自动外边距使用。
溢出的boxes忽略自动外边距,在对应维度的结束方向溢出。
注意:如果空闲空间分配给了自动外边距,则对齐相关的属性在这一维度上将不起作用,因为外边距偷走了伸缩后所有的可用空间。

Axis Alignment: the justify-content property

justify-content属性沿着容器的行的第一维轴线分布行内所有伸缩项的位置。这个属性在伸缩长度和所有自动外边距的计算都已解决后才生效。当一行中所有伸缩项都是不可伸缩,或者伸到最大后,还额外剩下的空闲空间,用这个属性决定如何分配。就算项目溢出,这个属性依然生效。

justify-content: flex-start; 行内的伸缩项都靠向行的开始一侧。行内第一个项目在第一维度上的开始外边缘和这行在第一维度上的开始外边缘完全齐平摆放,它之后的项目依次紧跟着前面的项目,后面项目的开始边缘和前面项目的结束边缘完全齐平摆放。

justify-content: flex-end;
和flex-start相反。行内最后一个项目的结束边缘和这行的结束边缘完全齐平摆放,它之前的项目依次紧跟着后面项目,前面项目的结束边缘和后面项目的开始边缘完全齐平摆放。

justify-content: center;
行内的伸缩项都靠向行的中间。在行内所有伸缩项目彼此边缘完全齐平摆放,并且整体对齐于行的中间,还有这行的开始边缘和第一个项目的开始边缘之间的空间长度与这行的结束边缘和最后一个项目的结束边缘之间的空间长度是相等的。如果剩余空闲空间是负的,则这些项目整体在两个相反方向的溢出空间是相等的。

justify-content: space-between;
如果剩余空闲空间是负的,或者行内仅有单个项目,这种情况表现和justify-content: flex-start; 一样。
其他情况下,所有伸缩项目平均分布在行内,行内第一个项目的开始边缘和这行的开始边缘完全齐平摆放,行内最后一个项目的结束边缘和这行的结束边缘完全齐平摆放,剩下的项目平均分布在行内剩下的空闲空间,保证任何两个项目的相对的边缘之间的空间长度是相等的。

justify-content: space-around;
如果剩余空闲空间是负的,或者行内仅有单个项目,这种情况表现和justify-content: center; 一样。
其他情况下,行内的伸缩项目平均分布在行内,并且在行内任何两个项目的相对的边缘之间的空间长度是相等的,并且第一个项目的开始边缘到容器的开始边缘的空间长度和最后一个项目的结束边缘到容器的结束边缘的空间长度是两个项目的相对的边缘之间的空间长度的一半。
Cross-axis Alignment: the align-items and align-self properties
伸缩项可以在其所属容器的所属行的第二维轴线上对齐。作为一个整体来说,类似于justify-content,但是是在justify-content垂直的方向上对齐于行的边。
align-items设置flex容器内所有项目的默认对齐方式,包括匿名flex items。
align-self允许为单个flex items重写默认对齐方式。
对于匿名flex items来说,它的align-self永远和它所属的容器的align-items的值一样。
如果flex item的第二维度上的margin属性值是auto,那么align-self无效。
如果「align-self」的值为「auto」,则其计算值为元素的父元素的「align-items」值,如果该元素没有父元素,则计算值为「stretch」。

对齐属性值的定义如下:
flex-start
行内伸缩项目在第二维度上的开始外边缘和这行在第二维度上的开始外边缘完全齐平摆放。

flex-end
行内伸缩项目在第二维度上的结束外边缘和这行在第二维度上的结束外边缘完全齐平摆放。

center
行内伸缩项目在第二维度上的中间和这行在第二维度上的中间对齐在一条线上。如果行在第二维度上的长度小于项目在第二维度上的长度,那么项目会溢出,并且在两个相反方向的溢出空间是相等的。

baseline
行内伸缩项目根据基线对齐,然后算出基线到项目在第二维度上的开始外边缘的长度最大的项目,将它的第二维度上的开始外边缘和这行在第二维度上的开始外边缘紧靠齐平摆放。如果行内项目外边缘到基线的长度一样,则看起来和flex-start一样。

stretch
如果flex item的cross size属性值求出为auto,并且第二维轴线的margins不是auto,那么这个项目在第二维度上的长度是会伸展的。
使用这个值,行内的项目在第二维度上的长度会尽可能接近这行在第二维度上的长度,同时仍然接受min-height/min-width/max-height/max-width属性值对于项目长度的限制。
注意,如果容器指定了具体高度,可能会造成伸缩项目的内容溢出。
Packing Flex Lines: the align-content property

align-content属性和justify-content属性类似。和justify-content属性一样值的我就不翻译了,看后面补充说明。

注意,这个属性在单行的伸缩容器上无效。

align-content: stretch;
多行box会占据剩余空间。如果剩余空闲空间为负,它的表现和flex-start一样。
其他情况,空闲空间会等分给所有行,增加每行在第二维度上的长度。

Flex Container Baselines

为了一个伸缩容器本身参与到基线对齐。例如,当一个伸缩容器本身就是一个外层伸缩容器的伸缩项目时。它必须提交基线的位置,它将最能表示它的内容。

first/last main-axis baseline set

如果伸缩容器的第一或最后一行中的任何一个伸缩项目参与了基线对齐,伸缩容器的第一或最后的主轴基线设置是生成自这些伸缩项共用的基线。这种情况对应容器设置align-items: baseline;

其他情况,如果伸缩容器至少有一个项目,并且它的第一个或最后一个项目有一条基线平行于容器的主轴,这个容器的第一或最后的主轴基线设置生成自它的对齐基线。这种情况对应容器某个项目设置align-self:baseline;

其他情况,容器的第一或最后主轴基线设置是合成自第一个或最后一个项目内容box,或者,直接来自容器内容box。这种对应容器和项目都没有设置align-items: baseline;和align-self:baseline;的情况。

官方翻译版本 https://www.w3.org/html/ig/zh/wiki/Css3-flexbox/zh-hans

 

补充说明:

关于flex flow,它是flex排版的基础。

首先确定writing-mode的值是horizontal-tb还是vertical-rl,flex-direction的值是row还是column,只有这个确定了,后面所有的术语才有了确定的意义。main是二维空间中的哪个维度,main axis是XY轴中的哪个轴,reverse是反往哪个方向,line是横行还是竖行等等。

第一大类:writing-mode: horizontal-tb;

第一大类的第一小类:

第1种属性配置,也是默认情况 flex-direction: row; flex-wrap: nowrap; 或速写 flex-flow: row nowrap;

main axis 可理解为XY坐标系的X轴,伸缩项的宽度就是它在X轴上的长度。
伸缩项从X轴的原点往正值方向摆放,即从左往右沿着main axis摆放。

cross axis 可理解为XY坐标系的Y轴,伸缩项的高度就是它在Y轴上的长度。

原点是伸缩容器box的左上角。可以把容器box理解为XY坐标系的第四象限。
第2种属性配置,flex-direction: row; flex-wrap: wrap; 或速写 flex-flow: row wrap;

main axis 可理解为XY坐标系的X轴,伸缩项的宽度就是它在X轴上的长度。
伸缩项从X轴的原点往正值方向摆放,即从左往右沿着main axis摆放。

cross axis 可理解为XY坐标系的Y轴,伸缩项的高度就是它在Y轴上的长度。
当伸缩项触发换行时,伸缩行从Y轴的原点往负值方向摆放,即从上到下沿着cross axis摆放。

原点是伸缩容器box的左上角。可以把容器box理解为XY坐标系的第四象限。
第3种属性配置,flex-direction: row; flex-wrap: wrap-reverse; 或速写 flex-flow: row wrap-reverse;

main axis 可理解为XY坐标系的X轴,伸缩项的宽度就是它在X轴上的长度。
伸缩项从X轴的原点往正值方向摆放,即从左往右沿着main axis摆放。

cross axis 可理解为XY坐标系的Y轴,伸缩项的高度就是它在Y轴上的长度。
当伸缩项触发换行时,伸缩行从Y轴的原点往正值方向摆放,即从下到上沿着cross axis摆放。

原点是伸缩容器box的左下角。可以把容器box理解为XY坐标系的第一象限。
第4种属性配置,flex-direction: row-reverse; flex-wrap: nowrap; 或速写 flex-flow: row-reverse nowrap;

main axis 可理解为XY坐标系的X轴,伸缩项的宽度就是它在X轴上的长度。
伸缩项从X轴的原点往负值方向摆放,即从右往左沿着main axis摆放。

cross axis 可理解为XY坐标系的Y轴,伸缩项的高度就是它在Y轴上的长度。

原点是伸缩容器box的右上角。可以把容器box理解为XY坐标系的第三象限。
第5种属性配置,flex-direction: row-reverse; flex-wrap: wrap; 或速写 flex-flow: row-reverse wrap;

main axis 可理解为XY坐标系的X轴,伸缩项的宽度就是它在X轴上的长度。
伸缩项从X轴的原点往负值方向摆放,即从右往左沿着main axis摆放。

cross axis 可理解为XY坐标系的Y轴,伸缩项的高度就是它在Y轴上的长度。
当伸缩项触发换行时,伸缩行从Y轴的原点往负值方向摆放,即从上到下沿着cross axis摆放。

原点是伸缩容器box的右上角。可以把容器box理解为XY坐标系的第三象限。
第6种属性配置,flex-direction: row-reverse; flex-wrap: wrap-reverse; 或速写 flex-flow: row-reverse wrap-reverse;

main axis 可理解为XY坐标系的X轴,伸缩项的宽度就是它在X轴上的长度。
伸缩项从X轴的原点往负值方向摆放,即从右往左沿着main axis摆放。

cross axis 可理解为XY坐标系的Y轴,伸缩项的高度就是它在Y轴上的长度。
当伸缩项触发换行时,伸缩行从Y轴的原点往正值方向摆放,即从下到上沿着cross axis摆放。

原点是伸缩容器box的右下角。可以把容器box理解为XY坐标系的第二象限。
第一大类的第二小类:
第1种属性配置, flex-direction: column; flex-wrap: nowrap;
第2种属性配置, flex-direction: column; flex-wrap: wrap;
第3种属性配置, flex-direction: column; flex-wrap: wrap-reverse;
第4种属性配置,flex-direction: column-reverse; flex-wrap: nowrap;
第5种属性配置,flex-direction: column-reverse; flex-wrap: wrap;
第6种属性配置,flex-direction: column-reverse; flex-wrap: wrap-reverse;

和前面6种一一对应,区别就是,main axis从X轴变成了Y轴,cross axis从Y轴变成了X轴。row对应的是inline,是行,或叫横行。column对应的是block,是列,或叫竖行。
第二大类writing-mode: vertical-rl;的属性配置情况就不细说了。初始属性配置就类似第一大类的第二小类的第3种配置的表现。
关于flex属性

它是flex排版的标志,它决定了box能不能flex,怎么改变长度。从flex的默认值flex: 0 1 auto;,可以看出它默认是为了适应窄屏的情况,当空间足够时,它是没有flex特性的,只有空间不够的时候才触发flex。
关于分布和对齐

justify-content,从字面意思也能看出,它强调的是行的内容怎么相对于行的空间来分布它们的位置,整体是靠行的哪边或中间,确定整体大方向后,它们相对的位置间隔怎么分配。

align-content和justify-content规则一样,但是作用对象不同,它是作用于容器内所有行的分布。如果说justify-content是相对行box,怎么分配行内的item box的位置,那么align-content则是相对于容器box,怎么分配行box的位置。注意只有一行的情况无效。

align-items 和 align-self,它强调的是项目们如何对齐,项目上的一条线怎么对齐在行的一条线上。align-items是容器的属性,它同时作用于行内所有项目,align-self是项目的属性,作用于单个项目自身。

一定要注意,虽然规范大量使用line的术语,但是因为main axis和cross axis所代表的二维空间上的维度是可以互换的,也就是说可以指定二维空间的那个维度作为主维,所以行,有可能是横行,也可能是竖行。如果用中文一个字理解,就是行和列的意思。

flex-grow公式
1
Available space = (container size – flex-basis siblings total)
可用空间长度 = (容器长度 – 所有项目的flex-basis属性的总值)
2
Grow unit = (Available space / Sum Grow siblings total)
flex-grow值的单位长度 = (可用空间长度 / 所有项目的flex-grow属性的总值)
3
Flex item size = (Flex basis + (Grow Unit * Individual grow num))
单个伸缩项目的最终长度 = (项目的flex-basis值 + (flex-grow值的单位长度 * 项目的flex-grow值))

flex-shrink公式(适用于不会溢出的情况,如果算出的值小于规则要求的最小长度,则使用最小长度,最终出现溢出情况)
1
项目抽象长度(公式用的抽象长度) = 项目的flex-shrink值 * 项目的flex-basis值
2
所有项目总长度 = 项目抽象长度相加的总值
3
项目的shrink系数(公式用的抽象系数) = 项目长度 / 所有项目总长度
4
不足长度(负空间) = 容器长度减去所有项目的flex-basis值
5
最终项目缩短后的实际长度 = 项目的flex-basis值减去项目shrink系数乘以不足长度向下取整的绝对值

公式基于Flexbox adventures文章:https://chriswrightdesign.com/experiments/flexbox-adventures/

注意,公式里flex-basis属性值不一定是开发者指定的值,不同情况有所不同,可能会是min-content/width/min-width/height/min-height值所代表的main长度作为公式中flex-basis的值。

Flex居中
.container { display: flex; }
.center { margin: auto; }

 

CSSOM View Module

这个规范介绍了一些APIs,它们提供给作者一种方法,用来检查和操作一个文档的视觉显示。包括获得元素排版线框的位置数据,通过脚本取得视口的宽高,还可以滚动一个元素。

如果一个元素完全满足以下条件,则这个元素是存在可以滚动的可能性potentially scrollable:

这个元素有一个关联的CSS排版线框。
这个元素不是body元素,或者它是body元素,但根元素的overflow-x or overflow-y属性值不是visible。
这个元素元素的overflow-x or overflow-y属性值不是visible。

注意:一个存在可以滚动的可能性的元素可以没有一个滚动线框。比如,元素的overflow设置为auto,但是它的内容没有溢出内容区域。

一个视口或元素的滚动线框scrolling box有两个溢出方向,依赖于视口或元素的block flow direction and inline base direction。

默认书写模式,block flow direction is top-to-bottom and the inline base direction is left-to-right,向右Rightward和向下downward。

后面说明都以默认书写模式作为前置条件。

术语滚动区域scrolling area是指一个视口或元素的线框box,它有以下边线:

上边线top edge,如果是视口,则是根元素的containing block的上边线;如果是元素,则是元素的padding线框的上边线。
右边线right edge,如果是视口,则是initial containing block的右边线和视口所有后代线框中margin线框的右边线中最靠右的那条边线;如果是元素,则是元素的padding线框的右边线和元素所有后代线框中margin线框的右边线中最靠右的那条边线。
下边线bottom edge,如果是视口,则是initial containing block的下边线和视口所有后代线框中margin线框的下边线中最靠下的那条边线;如果是元素,则是元素的padding线框的下边线和元素所有后代线框中margin线框的下边线中最靠下的那条边线。
左边线left edge,如果是视口,则是根元素的containing block的左边线;如果是元素,则是元素的padding线框的左边线。

如果是一个视口的滚动区域,那么滚动区域的原点origin就是initial containing block的原点。如果是一个元素的滚动区域,则原点是元素的padding线框的左上角。它的x坐标向右增大,y坐标向下增大。

Extensions to the Window Interface

innerWidth属性会返回视口的宽度,如果有滚动条,则包括滚动条的尺寸,或者返回0,如果没有视口。
innerHeight属性会返回视口的高度,如果有滚动条,则包括滚动条的尺寸,或者返回0,如果没有视口。

scrollX属性会返回文档当前处于视口的左边的initial containing block的原点位置的x坐标,或者返回0,如果没有视口。
pageXOffset属性会返回scrollX属性的值。

scrollY属性会返回文档当前处于视口的上边的initial containing block的原点位置的y坐标,或者返回0,如果没有视口。
pageYOffset属性会返回scrollY属性的值。

Extensions to the Element Interface

标准模式下,根元素的scrollTop属性值就是window的scrollY属性值。根元素的scrollLeft属性值就是window的scrollX属性值。根元素的scrollHeigh属性值就是视口的滚动区域的高度。根元素的scrollWidth属性值就是视口的滚动区域的宽度。

clientWidth和clientHeight值计算规则:
1. 如果元素no associated CSS layout box or CSS layout box is inline,值为0;
2. 如果元素是根元素(“),并且不是quirks mode,或者如果是body元素,并且是quirks mode,值为viewport的width或height,不包括滚动条。 3. 其他情况,则值为CSS box的width或height,包括padding,不包括border,margin和滚动条,忽略transform属性的影响。

offsetWidth/offsetHeight
1. 如果元素没有关联的CSS排版线框,则返回值为0,并且结束这个算法。
2. 返回元素关联的第一个CSS layout box的边框宽或高,忽略transforms属性的作用。

补充说明:
滚动区域scrolling area是整个滚动内容的线框。滚动区域的尺寸通过元素的scrollWidth和scrollHeight属性获得。

默认书写模式,window.scrollX就是滚动区域相对于滚动原点的已经移动的宽度,window.scrollY就是滚动区域相对于滚动原点的已经移动的高度。window.pageXOffset/window.pageYOffset就是window.scrollX/window.scrollY。

默认书写模式和标准模式下,html元素的scrollTop/scrollLeft就是window.scrollY/window.scrollX。html元素的scrollHeigh/scrollWidth就是视口滚动区域的宽高。quirks mode下,html元素的scrollTop/scrollLeft的值返回0,body元素不能滚动,body元素的scrollTop/scrollLeft的值返回window.scrollY/window.scrollX。

CSS box的宽高属性的指定值可能和计算值不一样,比如出现滚动条,计算值可能是指定值减去滚动条的尺寸。

HTMLElement.offsetWidth/offsetHeight接口得到元素的排版宽度/高度。它是元素的css box的content,borders,padding,scrollbar的宽度/高度相加的总值。

clientTop和clientLeft接口得到元素的CSS box的border-top-width和border-left-width。

如果要完全满足兼容性需求,最好使用jQuery之类的库。

判断滚动条到底示例:

window.onscroll = scroll;

function scroll() {
  if(document.documentElement.scrollHeight === (document.documentElement.scrollTop+document.documentElement.clientHeight)){
    console.log("bottom");
    document.documentElement.scrollTop = 0;
  }
}

scroll事件会频繁触发,回调函数中大量代码执行,会影响页面滚动,应该分离出来,放在timer方法中执行。示例:

var scrolling = false;
$(window).scroll(function() {
    scrolling = true;
});
setInterval(function() {
    if ( scrolling ) {
        scrolling = false;
        // Check your page position and then load in more results
    }
}, 300);

 

CSS Transforms

transform

/* Keyword values */
transform: none;

/* Function values */
2D Transform Functions

translate( <translation-x> [, <translation-y> ]? )
scale( <x> [, <y> ]? )
rotate( <angle> )
skew( <x> [, <y> ]? )

scale方法第二个参数不写,y值为第一个参数。translate和skew方法第二参数不写,y为0。

transform-origin 更改原点

动画优化

通常多数layout相关属性都会触发trigger layout operations。比如width,height,top,bottom,left,right等。
就算启用了硬件加速,layout也是在CPU中完成了元素的属性改变后,再绘制成bitmap传给GPU渲染显示。虽然GPU渲染很快,但是加载bitmaps到GPU内存是相对慢的。使用 CSS transform property改变元素不会触发layout,只在transform开始的时候,生成元素的bitmap并上传给GPU,后面都在GPU中完成,没有more layout, painting, or bitmap uploading. 还有opacity属性也是这样。

CSS Transitions

It enables you to define the transition between two states of an element. Different states may be defined using pseudo-classes like :hover or dynamically set using JavaScript.

transition: <property> <duration> <timing-function> <delay>;

Initial value as each of the properties of the shorthand:
transition-property: all
transition-duration: 0s
transition-timing-function: ease
transition-delay: 0s

element.addEventListener(“transitionend”, endCallback, false);
element.removeEventListener(“transitionend”, endCallback, false);

用transition和transform实现滚动到顶部的动画,思路来自一个日本技术博客,scroll类的属性不能应用动画,所以换个思路,先把内容移动下来,能见到全部已滚出的内容,再恢复内容位置,同时滚动条直接设置回顶部,这样就和滚动条滚回顶部的表现一样,利用错觉才是动画的精髓。

var root = document.documentElement;
var rootStyle = root.style;
function scrollToTop() {
  var endCallback = function () {
    rootStyle.transition = 'all 0s ease 0s';
    rootStyle.transform  = 'none';
    root.scrollTop = 0;
    root.removeEventListener('transitionend', endCallback, false);
  };
  root.addEventListener('transitionend', endCallback, false);
  rootStyle.transition = 'transform 1s ease-in-out';
  rootStyle.transform = 'translate(0, ' + root.scrollTop + 'px)';
}
window.onscroll = scroll;
function scroll() {
  if(root.scrollHeight === (root.scrollTop+root.clientHeight)){
    console.log("bottom");
    scrollToTop();
  }
}

还可以用JavaScript的setInterval实现,生产环境中为了兼容等原因最好用第三方类库。

CSS Animations

animation: <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode> <play-state> <name>;

Initial value as each of the properties of the shorthand:
animation-duration: 0s
animation-timing-function: ease
animation-delay: 0s
animation-iteration-count: 1
animation-direction: normal
animation-fill-mode: none
animation-play-state: running
animation-name: none

每个属性都可以用逗号的形式赋多个值,按顺序和animation-name属性值对应。

animation-name 指定@keyframes规则的名字,描述了动画的关键帧。
关键帧使用<percentage>数据类型。0%的别名是from,100%的别名是to。

animation-fill-mode = none | forwards | backwards | both
这个属性决定是否把关键帧0%的样式应用于动画开始前和关键帧100%的样式应用于动画结束后。

animation-play-state = running | paused

无限循环动画
animation-iteration-count: infinite;
animation-direction: alternate;

动画事件
element.addEventListener(“animationstart”, animationListener, false);
element.addEventListener(“animationend”, animationListener, false);
element.addEventListener(“animationiteration”, animationListener, false);
最后一次动画结束,只会触发animationend事件,不会触发animationiteration事件。

 

HTML5规范中关于元素样式渲染的描述。

UA不是必须以一个特定的方式去呈现HTML文档。

一个元素已渲染如果它有关联到CSS排版线框,SVG排版线框,或者其他同类的样式语言。

一个元素只是出了屏幕不意味着没有渲染。可以通过重写样式表让元素的显示属性为隐藏才不会被渲染。

没有什么元素的display必须是block或者inline,可以重写UA提供的默认样式。

W3C正在大力推进默认值:在浏览器默认样式和作者样式起作用之前,所有所有元素的所有CSS声明都有规范定义的默认值。例如,所有元素的display属性默认值都是inline,因为这是规范定义的默认值。随后,浏览器样式表设置块级元素的display属性为block。web开发者可以写样式表再次改变display的属性值。

https://html.spec.whatwg.org/multipage/rendering.html
https://www.w3.org/TR/html5/rendering.html
http://www.quirksmode.org/blog/archives/2015/09/a_new_device_ad.html

规范给出的一些默认样式建议

14.3.2 The page
html, body { display: block; }

14.3.3 Flow content
address, blockquote, center, div, figure, figcaption, footer, form, header, hr,
legend, listing, main, p, plaintext, pre, xmp {
display: block;
}

14.3.7 Sections and headings
article, aside, h1, h2, h3, h4, h5, h6, hgroup, nav, section {
display: block;
}

14.3.8 Lists
dir, dd, dl, dt, menu, ol, ul { display: block; }

14.3.9 Tables
table { display: table; }
caption { display: table-caption; }
colgroup, colgroup[hidden] { display: table-column-group; }
col, col[hidden] { display: table-column; }
thead, thead[hidden] { display: table-header-group; }
tbody, tbody[hidden] { display: table-row-group; }
tfoot, tfoot[hidden] { display: table-footer-group; }
tr, tr[hidden] { display: table-row; }
td, th, td[hidden], th[hidden] { display: table-cell; }

14.3.13 The fieldset and legend elements
fieldset {
display: block;
}
css-tricks almanac https://css-tricks.com/almanac/
MDN CSS https://developer.mozilla.org/en-US/docs/Web/CSS

written by panhezeng \\ tags: ,

©panhezeng for 阿潘道, 2006-2017. 原文地址:http://apsay.com/?p=1679
本文遵循署名-非商业性使用共享协议,转载请注明。

Leave a Reply