前端开发

 首页 > 前端开发 > css教程 > CSS规则树和HTML的DOM树合成渲染树时渲染结点与选

CSS规则树和HTML的DOM树合成渲染树时渲染结点与选

分享到:
【字体:
导读:
          在浏览器内核(排版引擎)CSS规则树和HTML的DOM树合成渲染树的时候,会涉及到渲染树的位置属性的问题,因为其位置属性将通过CSS选择器链的优先级来决定,而渲染树的某个结点可能会...

在浏览器内核(排版引擎)CSS规则树和HTML的DOM树合成渲染树的时候,会涉及到渲染树的位置属性的问题,因为其位置属性将通过CSS选择器链的优先级来决定,而渲染树的某个结点可能会同时满足多个选择器链,这时候就要通过选择器的优先级来完成属性的赋值。

在这个地方,我仅仅处理了几个简单的选择器情况:{(.class) (#id) (element) (#id,.class,elememt) (#id>.class) (#id element) (#id.class)}。

这时候,将渲染结点同时满足的几个选择器链通过其优先级加权算值,从小到大依次覆盖渲染结点;而如何确定此渲染结点是否满足某个选择器链呢?

我的实现过程大致如下:

首先给定选择器的结构体如下:

struct CSSParserSelector {
     enum TYPE {ID,CLASS,ELEMENT};
     enum RELATION {NONE,DESCENDANT,CHILD,AND};
     TYPE m_Type;
     std::string m_Name;
     RELATION m_Relation;
     struct CSSParserSelector *ptr;
     CSSParserSelector():m_Relation(NONE),ptr(NULL) {}
};

从本渲染结点开始,判断此结点是否与选择器链表的当前选择器相匹配。如果匹配,判断此选择器与下一个选择器的关系:如果为NONE,表示本选择器是选择器链的最后一个,返回成功;如果关系为AND (比如:#id.class),选择下一个选择器与本渲染结点继续比较;如果关系为CHILD,表示本选择器是下一个选择器的子结点,返回下一个选择器与下一个渲染结点的匹配结果;否则,关系为DESCENDANT,选择器和渲染结点各指向下一个结点,然后将渲染结点继续回溯,直到第一个满足回溯后的选择器的结点,此时将继续判断回溯后的选择器和回溯后的渲染结点是否匹配。这个过程大致如下:

/**
*选择器是否与渲染结点匹配
*/
bool RenderTree::IsSelectorsMatchRenderTree(CSSParserSelector *selector,RenderNode *renderNode)
{
     if(IsSelectorMatchRenderNode(selector,renderNode)) {
          if(selector->m_Relation == CSSParserSelector::NONE) {
               return true;
          } else if(selector->m_Relation == CSSParserSelector::AND) {
               return IsSelectorsMatchRenderTree(selector->ptr,renderNode);
          } else if(selector->m_Relation == CSSParserSelector::CHILD) {
               return IsSelectorsMatchRenderTree(selector->ptr,renderNode->parentNode);
          } else {
               return IsMatchDescendantRelation(selector->ptr,renderNode->parentNode);
          }
     } else {
          return false;
     }
}

/**
* 判断与祖父关系是否匹配
*/
bool RenderTree::IsMatchDescendantRelation(CSSParserSelector *selector,RenderNode *renderNode)
{
     while(renderNode->getTypeOfRenderNode() != "html"
               && (!IsSelectorMatchRenderNode(selector,renderNode))) {
          renderNode = renderNode->parentNode;
     }
     if(renderNode->getTypeOfRenderNode() != "html") {
          return IsSelectorsMatchRenderTree(selector,renderNode);
     } else {
          return false;
     }
}
最终便得到了匹配结果。而后通过公式便可以计算选择器链表的优先级。
分享到:
CSS基本功先生——选择器 - html/css语言...
  导入CSS(导入命名空间) 我们就一点一点的说,首先他是为了修饰网页的,也就是修饰HTML中的元素的,之所以说他方便,主要是他能对HTML中的每个元素集中处理,就好像我们的函数一样,但是我们要使用某个函数的话是不是就首先要导入他的命名空间呢,在HTML中也是一样的,当然方法稍微有点差异,但是思路还是一样的。下边...
[HTML5+CSS3]Transform详解 - html/css语...
Transform字面上就是变形,改变的意思。在CSS3中transform主要包括以下几种:旋转rotate、扭曲skew、缩放scale和移动translate以及矩阵变形matrix。下面我们一起来看看CSS3中transform的旋转rotate、扭曲skew、缩放scale和移动translate具体如何实现,老样子,我们就从transform的语法开始吧。 语法: transform : none...
  •         php迷,一个php技术的分享社区,专属您自己的技术摘抄本、收藏夹。
  • 在这里……