gtavcss原理

html-css05

gtavcss原理,第1张

探究 CSS 解析原理

吃早饭的时候,同事随意问了一句:你知道 CSS 是怎么解析的吗?我一头雾水。对哦,作为前端,每天都在与 CSS 打交道,我竟然忽视了最基本的原理。

一、浏览器渲染

开篇,我们还是不厌其烦的回顾一下浏览器的渲染过程,先上图:

正如上图所展示的,我们浏览器渲染过程分为了两条主线:

其一,HTML Parser 生成的 DOM 树;

其二,CSS Parser 生成的 Style Rules ;

在这之后,DOM 树与 Style Rules 会生成一个新的对象,也就是我们常说的 Render Tree 渲染树,结合 Layout 绘制在屏幕上,从而展现出来。

本文的重点也就集中在第二条分支上,我们来探究一下 CSS 解析原理。

二、Webkit CSS 解析器

浏览器 CSS 模块负责 CSS 脚本解析,并为每个 Element 计算出样式。CSS 模块虽小,但是计算量大,设计不好往往成为浏览器性能的瓶颈。

CSS 模块在实现上有几个特点:CSS 对象众多(颗粒小而多),计算频繁(为每个 Element 计算样式)。这些特性决定了 webkit 在实现 CSS 引擎上采取的设计,算法。如何高效的计算样式是浏览器内核的重点也是难点。

先来看一张图:

Webkit 使用 Flex 和 Bison 解析生成器从 CSS 语法文件中自动生成解析器。

它们都是将每个 CSS 文件解析为样式表对象,每个对象包含 CSS 规则,CSS 规则对象包含选择器和声明对象,以及其他一些符合 CSS 语法的对象,下图可能会比较明了:

Webkit 使用了自动代码生成工具生成了相应的代码,也就是说词法分析和语法分析这部分代码是自动生成的,而 Webkit 中实现的 CallBack 函数就是在 CSSParser 中。

CSS 的一些解析功能的入口也在此处,它们会调用 lex , parse 等生成代码。相对的,生成代码中需要的 CallBack 也需要在这里实现。

举例来说,现在我们来看其中一个回调函数的实现,createStyleRule(),该函数将在一般性的规则需要被建立的时候调用,代码如下:

CSSRule* CSSParser::createStyleRule(CSSSelector* selector) { CSSStyleRule* rule = 0 if (selector) { rule = new CSSStyleRule(styleElement) m_parsedStyleObjects.append(rule) rule->setSelector(sinkFloatingSelector(selector)) rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties)) } clearProperties() return rule }

从该函数的实现可以很清楚的看到,解析器达到某条件需要创建一个 CSSStyleRule 的时候将调用该函数,该函数的功能是创建一个 CSSStyleRule ,并将其添加已解析的样式对象列表 m_parsedStyleObjects 中去,这里的对象就是指的 Rule 。

那么如此一来,经过这样一番解析后,作为输入的样式表中的所有 Style Rule 将被转化为 Webkit 的内部模型对象 CSSStyleRule 对象,存储在 m_parsedStyleObjects 中,它是一个 Vector。

但是我们解析所要的结果是什么?

通过调用 CSSStyleSheet 的 parseString 函数,将上述 CSS 解析过程启动,解析完一遍后,把 Rule 都存储在对应的 CSSStyleSheet 对象中;

由于目前规则依然是不易于处理的,还需要将之转换成 CSSRuleSet。也就是将所有的纯样式规则存储在对应的集合当中,这种集合的抽象就是 CSSRuleSet;

CSSRuleSet 提供了一个 addRulesFromSheet 方法,能将 CSSStyleSheet 中的 rule 转换为 CSSRuleSet 中的 rule ;

基于这些个 CSSRuleSet 来决定每个页面中的元素的样式;

这里描述了大致过程,深入阅读可以查看如下链接:

Webkit CSS 引擎分析CSS 样式表解析过程Webkit CSS实现

三、CSS 选择器解析顺序

可能很多同学都知道排版引擎解析 CSS 选择器时是 从右往左 解析,这是为什么呢?

1.HTML 经过解析生成 DOM Tree(这个我们比较熟悉);而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。Render Tree 中的元素(WebKit 中称为「renderers」,Firefox 下为「frames」)与 DOM 元素相对应,但非一一对应:一个 DOM 元素可能会对应多个 renderer,如文本折行后,不同的「行」会成为 render tree 种不同的 renderer。也有的 DOM 元素被 Render Tree 完全无视,比如 display:none 的元素。

2.在建立 Render Tree 时(WebKit 中的「Attachment」过程),浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来确定生成怎样的 renderer。对于每个 DOM 元素,必须在所有 Style Rules 中找到符合的 selector 并将对应的规则进行合并。选择器的「解析」实际是在这里执行的,在遍历 DOM Tree 时,从 Style Rules 中去寻找对应的 selector。

3.因为所有样式规则可能数量很大,而且绝大多数不会匹配到当前的 DOM 元素(因为数量很大所以一般会建立规则索引树),所以有一个快速的方法来判断「这个 selector 不匹配当前元素」就是极其重要的。

4.如果正向解析,例如「div div p em」,我们首先就要检查当前元素到 html 的整条路径,找到最上层的 div,再往下找,如果遇到不匹配就必须回到最上层那个 div,往下再去匹配选择器中的第一个 div,回溯若干次才能确定匹配与否,效率很低。

对于上述描述,我们先有个大概的认知。接下来我们来看这样一个例子,参考地址:

<div> <div class="jartto"> <p><span>111 </span></p> <p><span>222 </span></p> <p><span>333 </span></p> <p><span class='yellow'>444 </span></p> </div></div>

CSS 选择器:

div >div.jartto p span.yellow{ color:yellow}

对于上述例子,如果按从左到右的方式进行查找:

1.先找到所有 div 节点;

2.在 div 节点内找到所有的子 div ,并且是 class = “jartto”;

3.然后再依次匹配 p span.yellow 等情况;

4.遇到不匹配的情况,就必须回溯到一开始搜索的 div 或者 p 节点,然后去搜索下个节点,重复这样的过程。

这样的搜索过程对于一个只是匹配很少节点的选择器来说,效率是极低的,因为我们花费了大量的时间在回溯匹配不符合规则的节点。

如果换个思路,我们一开始过滤出跟目标节点最符合的集合出来,再在这个集合进行搜索,大大降低了搜索空间。来看看从右到左来解析选择器:

1.首先就查找到 的元素;

2.紧接着我们判断这些节点中的前兄弟节点是否符合 P 这个规则,这样就又减少了集合的元素,只有符合当前的子规则才会匹配再上一条子规则。

结果显而易见了,众所周知,在 DOM 树中一个元素可能有若干子元素,如果每一个都去判断一下显然性能太差。而一个子元素只有一个父元素,所以找起来非常方便。

试想一下,如果采用从左至右的方式读取 CSS 规则,那么大多数规则读到最后(最右)才会发现是不匹配的,这样会做费时耗能,最后有很多都是无用的;而如果采取从右向左的方式,那么只要发现最右边选择器不匹配,就可以直接舍弃了,避免了许多无效匹配。

浏览器 CSS 匹配核心算法的规则是以从右向左方式匹配节点的。这样做是为了减少无效匹配次数,从而匹配快、性能更优。

深入阅读,请移步:

jQuery 源码解析CSS 选择器从右向左的匹配规则CSS 选择器

四、CSS 语法解析过程

CSS 样式表解析过程中讲解的很细致,这里我们只看 CSS 语法解释器,大致过程如下:

1.先创建 CSSStyleSheet 对象。将 CSSStyleSheet 对象的指针存储到 CSSParser 对象中。

2.CSSParser 识别出一个 simple-selector ,形如 “div” 或者 “.class”。创建一个 CSSParserSelector 对象。

3.CSSParser 识别出一个关系符和另一个 simple-selecotr ,那么修改之前创建的 simple-selecotr, 创建组合关系符。

4.循环第3步直至碰到逗号或者左大括号。

5.如果碰到逗号,那么取出 CSSParser 的 reuse vector,然后将堆栈尾部的 CSSParserSelector 对象弹出存入 Vecotr 中,最后跳转至第2步。如果碰到左大括号,那么跳转至第6步。

6.识别属性名称,将属性名称的 hash 值压入解释器堆栈。

7.识别属性值,创建 CSSParserValue 对象,并将 CSSParserValue 对象存入解释器堆栈。

8.将属性名称和属性值弹出栈,创建 CSSProperty 对象。并将 CSSProperty 对象存入 CSSParser 成员变量m_parsedProperties 中。

9.如果识别处属性名称,那么转至第6步。如果识别右大括号,那么转至第10步。

10.将 reuse vector 从堆栈中弹出,并创建 CSSStyleRule 对象。CSSStyleRule 对象的选择符就是 reuse vector, 样式值就是 CSSParser 的成员变量 m_parsedProperties 。

11.把 CSSStyleRule 添加到 CSSStyleSheet 中。

12.清空 CSSParser 内部缓存结果。

13.如果没有内容了,那么结束。否则跳转值第2步。

五、内联样式如何解析?

通过上文的了解,我们知道,当 CSS Parser 解析完 CSS 脚本后,会生成 CSSStyleSheetList ,他保存在Document 对象上。为了更快的计算样式,必须对这些 CSSStyleSheetList 进行重新组织。

计算样式就是从 CSSStyleSheetList 中找出所有匹配相应元素的 property-value 对。匹配会通过CSSSelector 来验证,同时需要满足层叠规则。将所有的 declaration 中的 property 组织成一个大的数组。数组中的每一项纪录了这个 property 的selector,property 的值,权重(层叠规则)。

可能类似如下的表现:

p >a { color : red background-color:black} a { color : yellow} div { margin : 1px}

重新组织之后的数组数据为(weight我只是表示了他们之间的相对大小,并非实际值。)

selector property weight 1, a color:yellow 1 2, p >a color:red 2 3, p >a background-color:black 2 4, div margin:1px 3

好了,到这里,我们来解决上述问题:

首先,要明确,内敛样式只是 CSS 三种加载方式之一;

其次,浏览器解析分为两个分支,HTML Parser 和 CSS Parser,两个 Parser 各司其职,各尽其责;

最后,不同的 CSS 加载方式产生的 Style rule ,通过权重来确定谁覆盖谁;

到这里就不难理解了,对浏览器来说,内联样式与其他的加载样式方式唯一的区别就是权重不同。

深入了解,请阅读Webkit CSS 引擎分析

六、何谓 computedStyle ?

到这里,你以为完了?Too young too simple, sometimes naive!

浏览器还有一个非常棒的策略,在特定情况下,浏览器会共享 computedStyle,网页中能共享的标签非常多,所以能极大的提升执行效率!如果能共享,那就不需要执行匹配算法了,执行效率自然非常高。

也就是说:如果两个或多个 element 的 computedStyle 不通过计算可以确认他们相等,那么这些 computedStyle 相等的 elements 只会计算一次样式,其余的仅仅共享该 computedStyle 。

那么有哪些规则会共享 computedStyle 呢?

该共享的 element 不能有 id 属性且 CSS 中还有该 id 的 StyleRule,哪怕该 StyleRule 与 Element 不匹配。

tagName 和 class 属性必须一样

mappedAttribute 必须相等

不能使用 sibling selector,譬如:first-child, :last-selector, + selector

不能有 style 属性。哪怕 style 属性相等,他们也不共享

当然,知道了共享 computedStyle 的规则,那么反面我们也就了解了:不会共享 computedStyle 的规则,这里就不展开讨论了。

深入了解,请参考:Webkit CSS 引擎分析 - 高效执行的 CSS 脚本

七、眼见为实

如上图,我们可以看到不同的 CSS 选择器的组合,解析速度也会受到不同的影响,你还会轻视 CSS 解析原理吗?

感兴趣的同学可以参考这里:speed/validity selectors test for frameworks

八、有何收获?

1.使用 id selector 非常的高效。在使用 id selector 的时候需要注意一点:因为 id 是唯一的,所以不需要既指定 id 又指定 tagName:

Badp#id1 {color:red} Good #id1 {color:red}

当然,你非要这么写也没有什么问题,但这会增加 CSS 编译与解析时间,实在是不值当。

2.避免深层次的 node ,譬如:

Bad div >div >div >p {color:red} Good p-class{color:red}

3.慎用 ChildSelector ;

4.不到万不得已,不要使用 attribute selector,如:p[att1=”val1”]。这样的匹配非常慢。更不要这样写:p[id=”id1”]。这样将 id selector 退化成 attribute selector。

Bad p[id="id1"]{color:red} p[class="class1"]{color:red} Good #id1{color:red} .class1{color:red}

5.理解依赖继承,如果某些属性可以继承,那么自然没有必要在写一遍;

6.规范真的很重要,不仅仅是可读性,也许会影响你的页面性能。这里推荐一个CSS 规范,可以参考一下。

更多资源

CSS 解析顺序优先级详细探索简单剖析 CSS 的解析规则

24个金币已到账

金币可兑换现金

立即提现

子宫肌瘤怎么办?告诉你一个调理方法!直达病灶!

到电驴上面下载吧: http://www.verycd.com/topics/2741979/“CSS设计彻底研究”随书光盘视频教程+实例源码+教学PPT。

“CSS设计彻底研究”随书光盘视频教程目录

CSS核心基础

第0课《CSS设计彻底研究》简介

第1课 CSS与(X)HTML核心基础(上)

第1课 CSS与(X)HTML核心基础(中)

第1课 CSS与(X)HTML核心基础(下)

第2课 CSS禅意花园介绍

深入CSS盒子模型

第3课 深入理解盒子模型(上)

第3课 深入理解盒子模型(下)

第4课 浮动与定位(上)

第4课 浮动与定位(下)

第5课 文字与图像(上)

第5课 文字与图像(下)

CSS导航设计

第6课 链接与导航

第7课 竖直菜单(上)

第7课 竖直菜单(下)

第8课 水平菜单

第9课 下拉菜单

CSS高级样式设计

第10课 表格也精彩

第11课 高级网页元素样式

第12课 圆角设计

CSS整体布局详解

第13课 固定宽度布局

第14课 不固定宽度布局(上)

第14课 不固定宽度布局(下)

第15课 综合布局实践

在线观看地址: http://learning.artech.cn/20070430.css-reserch-content-table.html 前沿视频教室的,上面还有很多教程

1.从一名小白到前端大神需要掌握哪些知识点

要想被称为前端大神要掌握的知识点还是有点多的,以我在源码时代培训过的经验来看,要想成为顶尖的前端大神,以下知识点你至少是应该要掌握的:“JavaScript基础、HTML入门基本内容,CSS+DIV的基础知识,选择器,盒子模型,网页布局,Photoshop,JavaScript高级编程,jQuery插件开发,模块化组件开,AJAX,HTML5,CSS3,响应式原理及布局,Bootstrap,前端依赖管理,CSS预处理语言(Less+Sass),Grunt/Gulp自动化构建工具Express(Node.js),MongoDB,ElementUIl,MVC、MVVM架构模式,VUE2,Webpack模块加载器&打包工具,React,Angular4,React Native”是不是感觉很多?觉得多就对了,只有对上述内容做到系数掌握,你才有资格被称之为“前端大神”。

2.学习前端HTML5需要了解哪些知识点

Stylus/Less实现CSS预编译

Express实现服务器端搭建

Nginx实现服务器反向代理

ngrok实现内网穿透

sha1、MD5实现加密隐私数据

Monggose实现mongoDB数据库操作

Echarts实现数据可视化

Mock、json-server实现模拟数据

Nodejs实现前后端完全分离

WebSocket实现实时通信

企业级UI设计图实现页面布局

BootStrap实现响应式页面

原生JavaScript实现小游戏开发

原生Ajax实现前后端通信

JSONP,CORS实现解决跨域

Animation实现动画

Canvas实现气泡, 钟表功能

jQuery实现备忘录项目

ArtTemplate实现模板页面复用

Viewport + Rem实现移动端适配

ViewPort实现1物理像素问题

原生JavaScript实现无缝滑屏

zepto实现移动端滑屏

Stylus/Less实现CSS预编译

Express实现服务器端搭建

Nginx实现服务器反向代理

ngrok实现内网穿透

3.网站前端开发都需要掌握哪些知识

CSS和HTML、JavaScript这是前端学习的三个语言,其中HTML是自简单,设计到代码多的就是CSS、JavaScript,入,门简单,达到初级前端水平很容易。

但是精通各种框架需要一定学习实践1、CSS和HTML刚入门的朋友,应该把重点放在 CSS和HTML基础知识的学习上。关于 CSS(3) 你需要了解以下一些知识点:web标准、HTML相关概念、HTML标签、路径相关概念、锚点及其他、表格标签、表单标签、综合案例,注册页面、CSS选择、CSS字体样、CSS外观属性、调式、CSS复合选择器、标签显示模式、CSS背景、CSS三大特性等等。

总的来讲,CSS和HTML的学习还是比较简单的。2、JavaScriptJavaScript一直都是前端工程师进步的基石, JavaScript 的理解深度决定了前端开发者的职业发展。

关于JavaScript的学习内容包括了浏览器执行JS过程、JS变量、数据类型、运算符、流程控制语句(if else 、三元表达式、switch)、循环(for、while、do while)、数组、冒泡排序、函数、作用域、预解析、对象、内置对象、简单类型和复杂类型等。只有在熟悉了JavaScript基础语法的基础上,我们才能继续深入学习前端技术。

前端需要掌握这些基本技能精通html,能够书写语意合理,结构清晰,易维护的html结构;精通css,能够还原视觉设计,并兼容业界承认的主浏览器;熟悉javascript,了解ECMAscript基础内容,掌握至少两种js框架随着web前端技术不断发展,web前端的岗位越来越多了,技术方向也有好多种,。web前端有广阔的发展空间,app、小程序、移动端、pc端等都是需要前端技术的开发支持才能够完成,技术门槛相对较低、需求量较大,薪资待遇良好。

只要是互联网端的客户界面,就需要前端来制作完成,前端开发的编程量不大,但是需要部分编程,入门简单,但是要学的深入需要一个过程。Web前端招聘岗位• 前端开发工程师、Web开发工程师、网页开发工程师、HTML开发工程师。

• H5开发工程师、移动应用开发工程师、App开发工程师、小程序开发工程师。• JS开发工程师、Vue.js开发工程师、Node.js开发工程师、前端架构师。

• 小游戏开发工程师、数据可视化开发工程师、WebGL开发工程师、WebVR开 发工程师、Web安全工程师。在互联网行业,前端有WEB前端、HTML前端等,随着互联网技术发展,就业方向也有很多。

web前端的就业方向有web架构师、web前端工程师、HTML前端开发工程师、网页设计师等等。HTML前端开发与Web前端开发不同的是,使用HTML5不仅仅可以开发前端,还有网页游戏,手机APP,使用浏览器进行3D渲染等一系列建立在HTML5标准与搭载其标准浏览器上的开发,而未来可能会有更多的功能分支并入HTML5标准。

web前端工程师这个方向是目前从事Web前端开发的主要就业方向Web架构师薪资普遍比较高,技术要求高,掌握多种技能,包括:后端技术、DBA、Platform等等,甚至包括网站优化SEO技术。数据方向数据研发这个是在Web开发的基础上用数据附能,懂可视化的一定是有前端能力的,懂hadoop的一定java要熟悉,属于Web开发的拓展方向。

大前端方向比如阿里,在大量实践rn和weex;由于公司内部安卓/ios式微,一定程度上,前端把ios和安卓收编了,统称大前端。图形学方向前端自然是与图形学有千丝万缕的联系,除了上面提到了可视化,还有相关3d引擎的开发工作。

做这一行要求也非常高了,图形学相关的算法,3d引擎的开发,这都需要图形学相关知识。

4.学HTML5,你需要掌握这几个知识点

Html5开发可谓是这几年来特别“受宠”的软件开发了,html5不仅入行门槛低、薪资高,发展前景更是可观,所以得到大家的追捧和青睐也是实至名归的,那么想要从事html5开发学习要掌握哪些必备的知识呢?

那么想要学好html5开发,那么需要掌握的专业技术有:

第1阶段:前端页面重构:PC端网站布局、HTML5+CSS3基础项目、WebAPP页面布局;

第2阶段:JavaScript高级程序设计:原生JavaScript交互功能开发、面向对象开发与ES5/ES6、JavaScript工具库自主研发;

第3阶段:PC端全栈项目开发:jQuery经典特效交互开发、HTTP协议,Ajxa进阶与后端开发、前端工程化与模块化应用、PC端网站开发、PC端管理信息系统前端开发;

第4阶段:移动端webAPP开发:Touch端项目、微信场景项目、应用Vue.js开发WebApp项目、应用Ionic开发WebApp项目、应用React.js开发WebApp

第5阶段:混合(Hybrid)开发:各类混合应用开发;

第6阶段:NodeJS全栈开发:WebApp后端系统开发;

第7阶段:大数据可视化:数据可视化入门、D3.jS详解及项目实战。

如今移动互联网发展迅速,技术不断的更新迭代,所学知识也需与时俱进。现在市场上的主流互联网网站,需要打造的是一流用户交互体验。对于前端开发者的要求,不再是简单的页面展示,而是需要全栈式的前端开发工程师。

5.web前端开发需要用到哪些知识

1. HTML5 + CSS3 + JavaScript Web开发基础中的基础,HTML是负责网页结构,CSS负责网页样式,JS则负责逻辑交互。

前两者更像是标记语言,没有什么逻辑,JS才是前端的重中之重。 HTML5 新增的技术大部分需要结合JS学习。

每个人学习进度可能不同,这个阶段主要是多仿站,熟悉基础,试试用CSS写响应式页面,了解JS深入性的知识,比如原型链、闭包、设计模式 等需要更多的积累,逐渐理解并实践掌握。 2. JQuery + BootStrap + Ajax + Json jQuery是JS的一个应用库,能够提升原生JS开发效率。

Bootstrap则是响应式框架,更简单的实现手机/平板/PC多个设备的页面支持。Ajax技术用于异步交互,不刷新页面就能更新数据,比如 地图 应用等。

Json是一种数据格式,被广泛应用在各大编程语言中。 jQuery 和 bootstrap 会简化很多编写的代码量,用着不亦乐乎,但对于基础还不是很扎实的人建议还是少用。

Ajax 和 json 通常用于和后端交互,在实际业务中也经常用到。 3. Git/SVN 版本管理工具,主要用于团队开发时避免文件冲突,也可回档。

前端推荐学习Git。 4. Nodejs + Mysql /MongoDB(可选) 运行在服务器端的JavaScript。

Express是其拓展MVC框架。其中nodejs最常用到的就是npm包管理器,不用到各个网站去下载资源包。

数据库 的学习可以选择MongoDB或者MySQL,前者与Nodejs的契合度更好,不过现在大多数网站都是 PHP +Mysql的组合,如果有学PHP的打算的话,可以先学习 Mysql 。 5. ECMAScript 6 JavaScript 的语言标准。

ES6中加入了很多新的概念,也弥补了之前版本中JS的很多缺陷,越来越多的项目开始运用ES6进行开发。学之前最好把ES5先搞懂了,目前实际项目中考虑到兼容性,ES6是需要通过Babel将其编译为ES5来部署的。

6. Angular/React/Vue 前端三大框架,各自也有着各自的生态系统,根据需求自行选择学习。目前企业需求量最大的仍然是Angular,但近期趋势来看react和vue则更受欢迎。

因为现在前端技术发展太过于突飞猛进,工具和框架的更新比翻书还快,建议学习还是看文档比较好。学习过程中也会遇到很多用到各种构建工具的时候。

7. 其他常用工具 这个一样是根据需求自行选择学习。比较常用的现在有 Web pack,可以将多个不同编程风格的文件打包,比如ES6/AMD/CMD之类的模块化都能识别并编译成 浏览器 能运行的文件。

Sass/Less,CSS预编译框架,可以用带有逻辑性的方式编写CSS代码。Gulp/Grunt构建工具,可以自动化对代码进行压缩合并等工作。

8. 其他后端编程语言 目前市场对前端基本都要求会一门后端语言, PHP / JAVA / Nodejs / Python 等。

6.前端这么多知识点该怎么记忆

前端涉及到的知识确实是比较广的,先要理清一定的框架,然后有条理的进行学习才能事位功半,这里我有一份知识体系给你了解一下

如果你有毅力可以坚持下去就自己好好的自学,但如果觉得效率不是很好条件允许的话也可以考虑参加系统的培训,虽然要花钱但可以省不少的时间,自己权衡。