19

我有一个 .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 个嵌套选择器!”的讨论。但它真的有害吗?它对页面加载有任何明显的影响吗?我所做的基准测试说不,但我有什么遗漏吗?

4

6 回答 6

32

这取决于页面加载后将对 DOM 和样式进行多少动态操作。问题不是页面加载(大部分)或初始布局上的慢速选择器,而是重绘/重排。

现在,Steve Souders 说,在一般网站上,这根本不是一个真正的问题。但是,在 Web 应用程序或高度交互的网站上,性能不佳的 CSS 规则会使您的重绘速度比必须的慢。如果你有很多重绘...

Nicole SullivanPaul IrishSteve Souders等专家介绍了 CSS 与 JavaScript 交互的方式以及如何编写高性能的 CSS 选择器。这不仅仅是深度(不同的选择器有不同的性能),但一个好的经验法则是限制深度和复杂性,以免自己陷入困境——但不是那么多的性能问题,请继续阅读。

然而,正如jankfree.org 所指出的,与其说是后代或特定选择器,不如说是某些上下文(html5rocks.com) 中的某些属性使绘制变得昂贵。我认为长或复杂的选择器更像是一个可维护性问题(Nicolas Gallagher)而不是性能问题——请记住,可维护性与性能相互作用。高度可维护的代码可以更快地迭代并且更容易调试(帮助您发现和修复性能问题)。

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

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

于 2012-12-11T15:07:12.553 回答
10

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

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

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

于 2012-12-13T09:31:13.307 回答
6

Don't nest CSS. We feel comfortable nesting css because that closely mirrors what we do in HTML. Nesting gives us context that .some-child is inside .some-parent. It gives us some control over the cascading. But not much else.

As SMACSS suggests, I would nest in class names instead. i.e, use .child-of-parent instead of .parent .child or .parent > .child

Nesting badly in practice can lead to extremely slow pages. See how github speeded up their diff pages.The least you should do is follow the inception rule which states that you shouldn't be nesting beyond 4 levels.

However, I would go one step further and say that we shouldn't nest CSS at all. I wrote a blog post with my opinions. Hope this is useful.

于 2013-09-10T17:56:26.217 回答
4

只是为了插话并执行其他人所说的话。从性能的角度来看,这不一定是一种不好的做法(与优化选择器相比,移除模糊/阴影和圆角可能会增加绘制时间),而是从可维护性的角度来看。

选择器嵌套的越多,生成的 CSS 规则就越具体(您已经知道了)。因此,当您想在某个时候“胜过”该规则时,您必须在级联的下方编写一个具有相同(或更高)特异性的规则以推翻第一个规则。如果你在那里有一个 ID,那也会使它更具体(所以避免,除非你需要它们并且知道你不需要覆盖下一行)。

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

.selector .another .yeah-another {}

当这将做同样的工作时:

.yeah-another {}

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

于 2013-02-11T22:26:48.127 回答
4

我的意见:

你告诉哪个更伤你的眼睛

从操作

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

或如建议的那样

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

所以...

问题是“在 SCSS 中过度嵌套是不好的做法吗?” (或者是 SASS?)我说不。但这是一个辅助论点。

更糟糕的做法在于将 SASS(或者它是 SCSS?)输出以机器驱动的状态用于生产。

S*SS 只是你的技巧包中的一个工具,与 Notepad++ 或 Git 或 Chrome 没有什么不同。它的作用是通过将一些非常通用的编程概念带到构建一些 css 的点上,让你的生活更轻松一些。它的作用不是构建你的 CSS。您不能指望它为您完成工作并创建完全可用、可读、执行的输出。

尽可能多和尽可能深地嵌套,然后遵循良好实践......

...之后将通过您的CSS并进行手动调整。使用您的超嵌套输出进行测试、构建等。当 S*SS 在上面创建我的第一个示例时,给该锚一个类并使用nav .class.

于 2013-09-24T19:13:15.897 回答
1

尽管不能直接回答您的问题,但您可以为自己的目的保留高度嵌套的 sass,但仍使用@at-root. 在这里查看。

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

// compiles to ... 

.child1 { ... }
.child2 { ... }
于 2014-05-10T10:32:39.857 回答