当前位置: 首页 > Web前端 > CSS

编写高效的CSS选择器–CSS魔法

时间:2023-03-30 19:12:18 CSS

高效的CSS不是一个新话题,也不是我必须重温的话题,但它是我工作时感兴趣的东西,并且一直在关注这是很久的话题了。很多人忘记了,或者根本没有意识到,我们手中的CSS可能非常有效,也可能非常无效。这很容易忘记,尤其是当您意识到您的CSS代码非常少且效率低下时。以下规则只应真正应用于速度至关重要且页面上绘制成百上千个DOM元素的大型站点。不过,实践真理,多了解一点总是好的。CSS选择器CSS选择器对我们大多数人来说都很熟悉。最基本的选择器是元素选择器(例如div)、ID选择器(例如#header)和类选择器(例如.tweet)。一些不常见的选择器包括伪类选择器(:hover)、许多复杂的CSS3和常规选择器,例如:first-child、class^="grid-"。CSS选择器具有高效的继承性,CSS选择器的效率从高到低排序如下:ID选择器如#header类选择器如.promo元素选择器如div兄弟选择器如h2+p子选择器如ul>li后代选择器如ula通用选择器如*属性选择器如type="text"伪类/伪元素选择器如a:hover我们不得不提的是,尽管ID选择器快速高效,但是仅此而已。从CSSTest我们可以看出ID选择器和类选择器在速度上的差别很小。在Windows上的Firefox6上,我测得一个简单类选择器的回流图为10.9ms,ID选择器为12.5ms,所以实际上ID比回流图慢一点。ID选择器和类选择器之间的速度差异基本上是无关紧要的。对标签选择器(a)的测试表明它比类或ID选择器慢得多。在一个深度嵌套的后代选择器的测试中,显示的数据是440左右!从这里我们可以看出,ID/class选择器和element/descendant选择器之间有很大的区别,但是彼此之间的区别很小。组合选择器您可以使用标准选择器(例如#nav)来选择ID为“nav”的任何元素,或者您可以使用复合选择器(例如#nava)来选择ID为“nav”的任何元素目前在链接元素中,我们以从左到右的方式阅读这些内容。我们先找到#nav,再从中找到其他元素。但这不是浏览器解析这些的方式:浏览器以从右到左的方式解析选择器。在我们看来,#nav中有一个a,但浏览器在#nav中看到了一个。这些细微的差别对选择器的效率有很大的影响,值得学习。浏览器从最右边的元素(它要呈现的元素)开始,然后沿着DOM树向上移动,而不是从DOM树的顶部开始向下看。这些对CSS选择器的效率有很大的影响。键选择器如前所述,键选择器是复杂CSS选择器最右边的部分。这是浏览器首先寻找的内容。现在我们回到讨论开始的地方,哪种类型的选择器最有效?选择器的关键是哪个,会影响选择器的效率;在编写CSS代码时,关键选择器是效率的决定性因素。像这样的关键CSS选择器:#content.intro{}像类选择器这样的高效选择器是否天生就高效?浏览器会寻找一个.intro的实例(可能有很多),然后查找DOM树以确定刚刚找到的实例是否在ID为“content”的容器中。但是,下面这个选择器的表现并不是那么好:#content*{}这个选择器所做的是选择页面上所有的个体元素(也就是每个个体元素),然后看它们是否有#content的父元素.这是一个非常低效的选择器,因为它的键选择器执行起来太昂贵了。利用这些知识,我们可以在分类和选择元素时做出更好的选择。假设您有一个非常庞大的复杂页面,并且位于您的一个非常非常大的网站上。该页面上有数百、数千甚至数万个a标签。它还在Ul中有一个小的社交链接区域,ID为#social。假设它们是指向Twitter、Facebook、Dribbble和Google+的链接。在这个页面上,我们有四个社交链接和数百个其他链接。下面的选择器自然就没那么高效合理了:#sociala{}这里发生的事情是,浏览器在定位到#socialarea下的四个链接之前,会获取页面上所有的数千个链接。我们的键选择器匹配了太多我们不感兴趣的其他元素。为了弥补这一点,我们可以在社交链接区域为每个a添加一个更具体明确的选择器.social-link,但这似乎有点违背我们的认知:当我们可以使用组合选择器时,我们不应该letitgo必要的类都标在了元素上。这就是我对选择器性能如此感兴趣的原因:必须在Web标准最佳实践和速度之间取得平衡。通常我们有:

  • Twitter
  • Facebook
  • 运球
  • Google+
  • CSS:#sociala{}我们现在最好有:
  • Twitter
  • Facebook
  • Dribble
  • Google+
  • /ul>加上CSS:#social.social-link{}这个新的键选择器将匹配更少的元素,这意味着浏览器可以快速找到它们并呈现特定的样式,然后专注于下一件事。另外,我们实际上可以使用.social-link{}来使选项更清晰,而不会对其进行过多限制。阅读下一部分,您就会知道为什么……回顾一下,您的键选择器将决定浏览器的工作量,因此我们应该注意键选择器。过度约束选择器现在我们知道了键选择器是什么以及它是如何工作的,我们可以稍微乐观一些。拥有显式键选择器的最大好处是您可以避免过度限制的选择器。一个过度限制的选择器可能看起来像:htmlbody.wrapper#contenta{}在这里写太多了,至少3个选择器是完全没有必要的。它最多看起来像这样:#contenta{}那么会发生什么?首先,第一个意味着浏览器必须找到所有a元素,然后检查它们是否在ID为“content”的元素中,依此类推,直到HTML标记。这会产生我们并不真正想要的太多费用。知道了这一点,我们得到一些更现实的例子:#navlia{}变成这样:#nava{}我们知道,如果a在li里面,它也一定在#nav里面,所以我们可以立即将li从中移除选择器组。那么,由于我们知道页面中只有一个id为nav的元素,所以它所依附的元素是完全无关的,我们也可以去掉ul。过度限制选择器会使浏览器比实际需要更努力地工作,从而花费更多时间。我们可以删除不必要的约束,使我们的选择器更简单、更高效。这些真的需要吗?最简短的回答是:可能不会。最长的答案是:这取决于您正在构建的站点。如果您正在做宣传,请编写简单、高效的CSS,因为您可能感觉不到其中的不同。如果您正在构建下一个站点,其中每个页面都以毫秒计,有时它会很快,但有时却不是。浏览器将更好地解析CSS,即使在移动设备上也是如此。您不太可能会在网站上注意到低效的CSS选择器,但是......但它确实会发生,并且浏览器仍然必须完成我们讨论过的所有工作,无论它们变得多快。即使您不需要甚至不想练习其中任何一个,也值得学习。请记住,选择器可能会让你付出很多代价,你应该避免盯着一个。这意味着如果你发现自己写了类似这样的东西:div:nth-of-type(3)ul:last-childli:nth-of-type(odd)*{font-weight:bold}那么你可能只是在做错误的。