在SASS / SCSS中过度嵌套选择器在实践中有多糟糕?

时间:2012-12-10 16:46:53

标签: css performance css-selectors sass

我有一个.scss文件,其中包含:

nav {
  font-size: 0;
  ul {
    margin: $padding/3;
  }
  li {
    z-index: 10;
    position: relative;
    display: inline-block;
    font-size: $fontSize;
    /**
     * If we want separated, Uncomment!

    margin: $padding/3;
    @include border-radius(5px);

    */
    &:first-child {
      @include border-radius(0 5px 5px 0);
    }
    &:last-child {
      @include border-radius(5px 0 0 5px);
    }
    padding: $padding/3 0;
    @include background(linear-gradient(lighten($textColor, 10%), $textColor));
    border: 1px solid lighten($textColor, 20%);
    a {
      color: $brightColor;
      padding: $padding/3 $padding;
      font-weight: bold;
      text-decoration: none;
      @include transition(.2s all);

    }
    //Nested menues
    ul {
      opacity: 0;
      //display: none;
      position: absolute;
      margin: 0;
      top: 0;
      left: 0;
      right: 0;
      z-index: 5;
      pointer-events: none;
      @include transition(.2s all);
      li {
        @include background(linear-gradient(darken($brightColor, 10%), darken($brightColor, 30%)));
        display: block;
        border: 1px solid lighten($textColor, 20%);
        &:first-child {
          @include border-radius(0);
        }
        &:last-child {
          @include border-radius(0 0 5px 5px);
        }
        a {
          color: $textColor;
        }
      }
    }
    &:hover ul {
      pointer-events: all;
      top: 100%;
      opacity: 1;
      //display: block;
    }
  }
}

在实践中有多糟糕/有害?我听过很多关于“不要超过3个嵌套选择器!”的讨论。但它真的有害吗?它是否对页面加载有明显影响?我所做的基准说不,但有什么我想念的吗?

6 个答案:

答案 0 :(得分:29)

这取决于页面加载后DOM和样式的动态操作量。初始布局上的页面加载(主要是)或slow selectors不是问题,而是重新绘制/回流。

现在,Steve Souders说on the average site it's simply not a real concern。但是,在Web应用程序或高度交互的网站上,CSS规则can make your repaints slower执行效果不佳。如果你有很多重绘......

Nicole SullivanPaul IrishSteve Souders等知名专家介绍了CSS与JavaScript交互的方式以及如何编写高性能的CSS选择器。它比深度更复杂,但一个好的经验法则是限制深度以避免麻烦 - 但不要那么多性能问题,请继续阅读。

然而,正如jankfree.org所指出的那样,后代选择器并不是因为它是certain properties in certain contexts(html5rocks.com)而使油漆变得昂贵。我认为长选择器更多为a maintainability issue(Nicolas Gallagher)而不是性能问题 - 请记住可维护性与性能相互作用。高度可维护的代码可以更快地迭代并且更容易调试(帮助您查找和修复性能问题)。

现在,关于Sass优化。是的,Sass可以优化您的CSS。但它无法优化您的 选择器 。 4级嵌套块将作为4级嵌套选择器输出。 Sass无法在不使CSS无效的情况下改变它。作为作者,您必须优化编写Sass的方式以优化输出。我个人来说,只能以有限的方式使用嵌套(Sass中的杀手级功能是@extend和占位符。但是,如果你真的喜欢嵌套,你可以使用Sass parent selector reference(或更新的@at-root)在一定程度上调整输出。

据我所知,Sass和Compass都没有内置工具来分析选择器并警告它们。使用AST创建一个工具(设置最大深度并让预处理器发出警告)可能是可能的。更直接地,Google Page Speed does具有提供某些信息的现有功能。 SCSS Lint有一个嵌套选项。还有CSS Lint。 (如果您还没有使用像Grunt或Gulp这样的东西,理论上可以在Compass配置的on_stylesheet_saved中添加这些。)

答案 1 :(得分:9)

想想你将如何编写实际的css选择器。不要仅仅因为它是元素的子元素而嵌套所有内容。

nav li ul li a { 
    /* over specific, confusing */
}
.sub-menu a {
    /* add a class to nested menus */
}

一旦你开始链接那么多选择器,覆盖就会变得很痛苦,并且会导致特异性问题。

答案 2 :(得分:5)

不要嵌套CSS。我们觉得嵌套css很舒服,因为这与我们在HTML中所做的非常相似。嵌套为我们提供.some-child位于.some-parent内的上下文。它让我们可以控制级联。但其他并不多。

正如SMACSS建议的那样,我会在类名中嵌套。即,使用.child-of-parent代替.parent .child.parent > .child

在实践中严重嵌套会导致页面速度极慢。看看github如何加速他们的差异页面。你应该做的最少的就是遵循inception rule,它指出你不应该嵌套超过4个级别。

但是,我会更进一步说我们不应该嵌套CSS。我用我的意见写了一篇blog post。希望这很有用。

答案 3 :(得分:4)

只是为了加入并强制执行别人所说的话。这不是一个糟糕的做法,不一定是从性能的角度来看(从可移动性的角度来看,可能会因为去除模糊/阴影和圆角而不是优化选择器而获得更好的绘制时间增加)。

嵌套的选择器越多,生成的CSS规则(您已经知道)就越具体。因此,当你想在某个时刻“胜过”这条规则时,你必须在级联中进一步写出一个相等(或更高)特异性的规则来否决第一个规则。如果你有一个ID,那么它也会更加具体(所以除非你需要它们并且知道你不需要重写这一行)。

要遵循这个逻辑结论,除非你需要,否则不要嵌套。没有这样的规则:

.selector .another .yeah-another {}

当这会做同样的工作时:

.yeah-another {}

它让每个人(包括你)的生活变得更轻松。

答案 4 :(得分:4)

我的意见:

你告诉 哪个更糟糕

来自op

nav li ul li a {color: $textColor;}

或按照建议

.nav-menuitem-menu-menuitem-link {color: $textColor;}

因此...

问题是“在SCSS中是否是最严重的做法?” (或者是SASS?)我说不。 但这是一个辅助论点。

WORSE 的做法在于将SASS(或SCSS?)输出留在机器驱动状态下进行生产。

S * SS只是你技巧包中的一个工具,与Notepad ++或Git或Chrome没什么区别。它的作用是通过引入一些非常通用的编程概念来构建一些css,从而使您的生活更轻松。 它的作用不是构建你的CSS。你不能指望它为你完成你的工作并创建完全可用,可读,性能的输出。

尽可能多地嵌套,然后按照良好实践......

......之后会通过你的css和手调整。使用高性能输出进行测试,构建等。当S * SS在上面创建我的第一个例子时,给该锚点一个类并用nav .class调用它。

答案 5 :(得分:1)

虽然不能直接回答您的问题,但您可以为自己的目的保留高度嵌套的sass,但仍使用@at-root。请查看here

.parent {
  @at-root {
   .child1 { ... }
   .child2 { ... }
  }
} 

// compiles to ... 

.child1 { ... }
.child2 { ... }