前言
我们很小的时候什么都不知道,于是什么都会是别人对我们解释,也许是父母,也许是师长,但是随着年龄的增大,我们会逐步形成自己的世界观,并且当我们有小孩时候,他会问我们很多问题,我们会为他解答,那么我们的答案有何而来呢?
我们的答案来自我们自己的世界,来自我们自己形成的世界观!
我们初学CSS时候什么也不知道,于是我们从书上、博客上获取了很多知识,那么我们是不是也应该形成自己的世界观呢?我们碰到的问题是不是都可以用我们形成的世界观解释呢?
以上是我最近思考的问题,我觉得我们有必要形成自己的世界观了,形成世界观才是长大的标志,我形成的世界观可以不坚固,可以很小但是他必须存在,你们的也必须存在。
我们需要捍卫我们的世界观,我们需要建造我们的世界观,当我们的世界足够大,足够发达的时候,我们就会被称为高手啦,哇哈哈!!!
师尊,我们的页面是哪里来的?
在我们的浏览器中输入了一个url后,我们的服务器便会返回一堆字符串给我们,这个字符串就是传说中html。
从得到html字节开始,dom树便开始勾践了,遇到以下情况时候dom树的构建会被暂时阻塞:
① 网络卡
② 有未加载的脚本
③ 样式还未加载结束就遇到script
dom树是基础,dom树构建结束以后便根据样式与dom构建我们的渲染树了,这个时候样式文件便会阻塞我们的页面渲染。
PS:有些网页会把CSS写在页面里,而不是外部文件是为了避免页面闪烁,或者出现裸奔的局面。
当样式表加载结束后,渲染树也被构建好了,我们的页面就基本成型了。
渲染树一旦构建完成后,若是js脚本操作dom,就很可能引起页面回流,过多的回流是前端性能的杀手。
浏览器下载的顺序是由上到下的,渲染顺序也是由上到下的,下载样式表与渲染树形成是同步完成的
在渲染到页面某一部分时,上面的所有部分已经下载完成,并且渲染结束(一旦有js引起改变,边可能引起之前元素发生回流)
若是浏览器中有多个样式表,在所有样式表下载结束后浏览器又会将所有的样式表放到一起重新解析,会对之前的所有元素重新渲染,所以样式表过多也不是太好的。
PS:我们在做页面时候要注意页面的大小开始不宜过大,这样可以渲染的很快,以延迟加载的方式进行。
以上的逻辑可以分割如下:
① 构建dom树
② 构建render树
PS:渲染树,写英文为了防止以后被问到不知道是什么,包含颜色和属性的矩形块。
③ 布局render树,确定每个节点在屏幕上的确切坐标,然后开始绘制。
师尊,我们的页面如何布局呢?
以上为浏览器干的事情,他干完了就形成了我们所看到的页面,我们不需要过于关注,但是我们需要关注他的布局。
当渲染树被创建并添加到树中,他并没有位置和大小,计算他位置与大小的过程便是layout或者reflow。
每个渲染对象都有一个layout或者reflow方法,每个渲染对象须有布局的children的layout方法。
每个小变化都可能导致重新布局,浏览器使用一个dirty bit系统,一个渲染对象发生变化就会标记他以及他的children胃dirty,就会重新布局之,若是仅仅是其children有问题的话,就只会搞他的children。
全局回流(reflow)是需要避免的,因为其很耗性能,窗口改变会引起全局回流是可以理解的,但是改变整个浏览器字体大小的事情我们要少做。
渲染一个对象时候,这个元素的尺寸(高度不定)由其parent决定,他又会决定其children对象,children积累高度与margin、padding便为自己的尺寸,总之这个过程中浏览器很忙。
浏览器在渲染页面的时候很忙,所以你一个不小心哪里不如他意了他就会使坏的,所以不要一来就认为浏览器有bug,他忙自然关注不了太多。
PS:元素绘制的过程就是讲元素压入堆栈的过程,一个渲染对象的堆栈顺序为:背景色->背景图->border->children->outline。所以我们在写css时候规则可言参照之
CSS规定所有元素都应该具有盒模型(内容区、padding、border、margin),但是不同元素又有差异:
块级元素——块级盒模型
行内元素——生成一个或者多个inline boxes ,inline boxes组成line boxes确定其行高
none——不生成盒模型
师尊,什么是盒模型?
盒模型对我们后面的布局至关重要
浏览器要定位元素就必须知道其定位与尺寸,浏览器有三种方式布局:
① normal 根据自身和模型大小布局
② float 开始与普通流类似,然后脱离文档尽可能靠左或者靠右
③ absolute 与dom无关,根据top等决定位置,盒模型决定尺寸
以上三种无论如何都应该有其支点,这个支点就是传说中的containing block(包含快),也就是元素所处容器,再简单点就是依赖于其parent了(这块可能有误)
前面我们说过,每个元素皆遵循盒模型定理,所以各个元素可以简单看做一个个盒子,小盒子摆放依赖于大盒子。
① static/relative元素包含快为其父元素的内容区(出去padding部分)
② absolute包含快为最近定位元素(absolute/relative)
③ fixed为根元素(html)
④ float包含快为最近的块级元素
师尊,BFC/IFC又是什么?
而在盒子们布局时候为了减除彼此间的影响,便出现了block formatting context(块级上下文)这种布局特性,我理解为隔开盒子的隔板。
以下行为会产生bfc:
① float不为none
② overflow不为visible
③ display为table-cell,table-caption,inline-block中的任何一个
④ position不为relative和static时
在IE7以下没有BFC的概念,其为了解决的这个问题便提出了haslayout,两者之间可以画等号,但是haslayout bug较多,所以IE7以下有很多bug。
相邻的块级元素之间会发生margin collapse现象,便是外边距叠加行为。
这个原因便是相邻且在同一bfc时垂直外边距叠加行为。
垂直外边距便会叠加要解决的话,
有两种方案(不让其相邻,处在不同的bfc)可以为外部设置padding属性将彼此隔开,当然也可以使用overflow触发器bfc导致其处在不同的bfc,便不会造成叠加
师尊,块级元素又是什么?
有了以上知识后,我们再来看看块级元素
块级元素会独占一行,在normal中,其排布由其盒模型确定
PS:IE6盒模型解析有误,需要向下兼容需要处理
块级元素为布局大户,他与position的配合便是布局的瑞士军刀。
我这里对absolute布局的块级元素有两种理解:
1 absolute破坏了元素的高宽,并且将其剥离正常文档流,而形成了一个会飞的inline-block元素,其初始原点(top/left)与文档流中正常元素一致,但不会影响其它元素
2 absolute拥有了自己的bfc环境,自成一格与主流bfc分割开后,大小由盒模型确定,位置由top等确定
因为页面上可能出现多个absolute,所以彼此间的显示可能出现遮盖的现象,所以我们有了z-index遮盖家伙帮我们干事。
PS:我猜测,要让元素靠近我们其实是让其bfc靠近我们,而ie7以下不存在bfc,取而代之的是haslayout,所以在ie7以下便会有这样那样的bug,并且元素需要依赖其父元素的z-index,事实上便是子元素的haslayout需要依赖父元素的haslayout,他这样的真相便是,标准浏览器的bfc是各自独立的,ie7/6的haslayout是依赖于父元素的(猜测,欢迎拍砖)
行内元素
对于行内元素来说,每个字会形成一个匿名inline boxes,每个行内元素也会有一个inline boxes,一行的inline boxes便会形成一个line boxes,行框决定着这行的高度。
但是,我们这里的inline boxes干了什么事呢?
既然有块级格式上下文,便会有inline formatting contexts(行内格式化上下文)
ifc中,inline boxes都是水平排列的,起点是其containing block的头部,
PS:这块我有所欠缺,后面再补上
inline boxes会撑开line boxes,line boxes才给予了我们一行的高度,所以文字撑不开高度,是inline boxes撑开的高度,最后便是line-height决定高度(若是块级元素的高度未设定)。
float
我们知道float也会创建独立的bfc,这里我对他的理解也形成了两种:
1 float这家伙破坏了元素的高度,将之变为会左右移动的inline-block,虽然高度不存在了,但是宽度还在,所以其它文本会围绕之,块级元素(边框等)却会覆盖之。
2 float拥有了自己的bfc了,所以脱离了文档流,其margin属性与其它元素无关了(该理念还无法成型,暂时依赖第一个吧)
你的世界观形成了吗?
至此,我们便了解了css中的很多东西了,我们以此形成了世界观,于是我们今后需要在此世界中找到所有我们需要的答案,若是找不到就说明这个世界还不够发达,需要你在建,我们需要维护他,不让他崩毁,但他若是真的崩毁了也不要紧,因为你在形成的世界会无比的辉煌!!!
好了我们以此世界观来解释我们遇到的一些问题:
兼容性问题?
其实我们说的兼容性问题主要是IE7以下有问题,IE7以下因为不存在BFC而替用了haslayout,所以会有很多bug,针对bug,
高手会避免haslayout产生问题,而一般人会选择使用hack技术
为什么会高度坍塌?
因为float破坏了元素的inline boxes,而我们的inline boxes撑开了我们的块级元素,所以不动态指定高度的话,其实不会具有高度的。
如何解决高度坍塌,其原理是什么?
clear:我这里猜测清除浮动强制修复了行内元素的inline boxes,所以元素又能撑开块级元素了(但是我不能证明自己)
overflow:overflow触发了元素的bfc,让元素具有独立的bfc,所以其元素不用坍塌了!以上就是坑爹的!因为我自欺欺人都不行,何况忽悠你们,所以我们这里换个说法,这里我想换个思路,我们知道bfc其实就是格式化上下文,说白了他会包裹着我们的元素(我们在IE7中有时候用a标签模拟按钮,但是没戏,触发layout后便可以了,应该就是这个原理),若是我们来看看触发了bfc的元素,他本来都没了高度,但是我要包括你,我们不能包裹没有的东西吧,所以浏览器又被迫恢复了其inline boxes。
PS:我第一是确实一时间找不到还有什么问题可以让我自说自答了,二来是怕真的出现问题答不起,我好不容易搭建起了的世界就给崩毁了就太伤心啦,所以我暂时不在问自己问题了。
为什么我在js操作dom的时候风扇会不停的转?
因为操作dom后可能引起大量回流reflow,所以页面又要重新布局,这个过程很耗资源的。
为什么我们要指定图片的容器宽度
因为图片加载后,若是宽度不固定,会撑开他所在页面,以下部分会发生下层现象,也是一种reflow,(dom构建结束后才加载图片)
结语
我形成了自己的CSS时间观了,虽然他还很脆弱,但是我会慢慢建设他,让我的CSS世界坚固而美丽。
各位,若是你们觉得有什么不足以及错误,请提出哦。