简体   繁体   English

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

[英]How bad is it in practice to over-nest selectors in SASS/SCSS?

I have a .scss file that, among other things contains this:我有一个 .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;
    }
  }
}

How bad/harmful it is in practice?它在实践中有多糟糕/有害? I've heard many talks about "Don't go over 3 nested selectors!"我听过很多关于“不要超过 3 个嵌套选择器!”的讨论。 But how harmful is it really?但它到底有多大危害呢? Does it have any visible impact on page loads?它对页面加载有任何明显的影响吗? The benchmarks I've done say no, but is there anything I'm missing?我所做的基准测试说不,但有什么我遗漏的吗?

It depends on how much dynamic manipulation of the DOM and styles will go on after page load.这取决于页面加载后将进行多少 DOM 和样式的动态操作。 It's not page loads (mostly) or slow selectors on initial layout that are at issue, it's repaints/reflows.有问题的不是页面加载(主要是)或初始布局上的慢速选择器,而是重绘/回流。

Now, Steve Souders says that on the average site it's simply not a real concern .现在,Steve Souders 说, 在一般网站上,这根本不是一个真正的问题 However, on a web app or highly interactive site, poorly performing CSS rules can make your repaints slower than they have to be.但是,在 Web 应用程序或高度交互的站点上,性能不佳的 CSS 规则会使您的重绘速度比它们必须的要 If you have a lot of repaints...如果你有很多重绘...

Experts such as Nicole Sullivan , Paul Irish , and Steve Souders have covered the way CSS interacts with with JavaScript and how to write highly performant CSS selectors. Nicole SullivanPaul IrishSteve Souders等专家介绍了 CSS 与 JavaScript 交互的方式以及如何编写高性能的 CSS 选择器。 It's more than depth (different selectors have different performance), but a good rule of thumb is to limit both depth and complexity to keep yourself out of trouble--but not so much performance trouble, read on.这不仅仅是深度(不同的选择器具有不同的性能),但一个好的经验法则是限制深度和复杂性,以免自己遇到麻烦——但不是那么多的性能问题,请继续阅读。

However, as jankfree.org notes, it's not so much descendant or specific selectors as it is certain properties in certain contexts (html5rocks.com) that make paints expensive.然而,正如jankfree.org 所指出的,与其说是后代选择器或特定选择器,不如说是 某些上下文(html5rocks.com) 中的 某些属性使绘画变得昂贵。 I see long or complicated selectors more as a maintainability issue (Nicolas Gallagher) than a performance issue--keeping in mind that maintainability interacts with performance.我认为长的或复杂的选择器更像是一个可维护性问题(Nicolas Gallagher),而不是性能问题——请记住,可维护性与性能相互作用。 Highly maintainable code can iterate faster and is easier to debug (helping you find and fix performance issues).高度可维护的代码可以更快地迭代并且更容易调试(帮助您发现和修复性能问题)。

Now, as to Sass optimization.现在,至于 Sass 优化。 Yes, Sass can optimize your CSS.是的,Sass 可以优化你的 CSS。 But it cannot optimize your selectors .但它无法优化您的选择器 A 4 level nested block will be output as a 4 level nested selector. 4 级嵌套块将作为 4 级嵌套选择器输出。 Sass cannot change it without possibly making your CSS not work. Sass 无法更改它,而不会使您的 CSS 无法正常工作。 You, as the author, have to optimize the way you write Sass to optimize your output.作为作者,您必须优化编写 Sass 的方式以优化输出。 I, personally, use nesting only in a limited way (a killer feature in Sass for me is composing styles with @extend and placeholders).我个人仅以有限的方式使用嵌套(对我来说,Sass 中的一个杀手级功能是使用@extend和占位符组合样式)。 However, if you really love nesting you might be able to tweak your output to some degree using the Sass parent selector reference (or the newer @at-root ).然而,如果你真的喜欢嵌套,你可以使用Sass 父选择器引用(或更新的@at-root某种程度上调整你的输出。

So far as I know, neither Sass nor Compass has a built-in tool to analyze selectors and warn about them.据我所知,Sass 和 Compass 都没有内置工具来分析选择器并对其发出警告。 It's probably possible to create a tool to do that (set a max depth and have your pre-processor warn you) utilizing an AST .可能可以使用AST创建一个工具来做到这一点(设置最大深度并让您的预处理器警告您)。 More directly, Google Page Speed does have an existing feature that provides some information.更直接的是, Google Page Speed 确实有一个现有的功能可以提供一些信息。 SCSS Lint has a nesting option. SCSS Lint有一个嵌套选项。 There's also CSS Lint .还有CSS Lint (These can theoretically be added to run in your Compass config's on_stylesheet_saved if you're not already using something like Grunt or Gulp). (如果您还没有使用 Grunt 或 Gulp 之类的东西,理论上可以将这些添加到您的 Compass 配置的on_stylesheet_saved运行)。

Just think about how you would want to write the actual css selector.想想你想如何编写实际的 css 选择器。 Don't nest everything just because it is a child of the element.不要仅仅因为它是元素的子元素而嵌套所有内容。

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

Once you start chaining that many selectors, it becomes a pain to override and can lead to specificity issues.一旦你开始链接这么多选择器,覆盖就变得很痛苦,并可能导致特异性问题。

Don't nest CSS.不要嵌套 CSS。 We feel comfortable nesting css because that closely mirrors what we do in HTML.我们觉得嵌套 css 很舒服,因为这与我们在 HTML 中所做的非常相似。 Nesting gives us context that .some-child is inside .some-parent .嵌套为我们提供了.some-child位于.some-parent内部的.some-parent It gives us some control over the cascading.它让我们可以控制级联。 But not much else.但没有太多其他的。

As SMACSS suggests, I would nest in class names instead.正如 SMACSS 所建议的,我会嵌套在类名中。 ie, use .child-of-parent instead of .parent .child or .parent > .child即,使用.child-of-parent而不是.parent .child.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.看看 github 如何加速他们的差异页面。至少你应该遵循初始规则,该规则指出你不应该嵌套超过 4 个级别。

However, I would go one step further and say that we shouldn't nest CSS at all.但是,我会更进一步说,我们根本不应该嵌套 CSS。 I wrote a blog post with my opinions.我写了一篇博客文章,表达了我的看法。 Hope this is useful.希望这是有用的。

Just to chime in and enforce what others have said.只是为了加入并强制执行其他人所说的话。 It's a bad practice not necessarily from a performance point of view (It's probable you'll get better paint time increases from removing blurs/shadows and rounded corners than optimising selectors) but from a maintainability point of view.从性能的角度来看,这不一定是一种糟糕的做法(与优化选择器相比,通过消除模糊/阴影和圆角,您可能会获得更好的绘画时间增加),但从可维护性的角度来看。

The more heavily nested a selector, the more specific the resultant CSS rule (which you know already).选择器嵌套越多,生成的 CSS 规则就越具体(您已经知道了)。 Therefore, when you want to 'trump' that rule at some point you'll have to write a rule of equal (or greater) specificity further down the cascade to overrule the first.因此,当您想在某个时候“胜过”该规则时,您必须在级联的更下方编写一条具有相同(或更高)特异性的规则以否决第一个规则。 If you have an ID in there, that's going to make it FAR more specific too (so avoid unless you need them and know you won't need to override down the line).如果你在那里有一个 ID,那也会使它更具体(所以避免,除非你需要它们并且知道你不需要覆盖)。

To follow this to its logical conclusion, don't nest unless you need to.为了遵循这个逻辑结论,除非你需要,否则不要嵌套。 Don't have a rule like this:不要有这样的规则:

.selector .another .yeah-another {}

When this would do the same job:当这会做同样的工作时:

.yeah-another {}

It just makes life easier for everyone (including you) down the line.它只是让每个人(包括你)的生活更轻松。

My opinion:我的意见:

You tell me which is worse on your eyes你告诉你的眼睛哪个更糟

from the op从操作

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

or as has been suggested或按照建议

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

So...所以...

The question is "Is it bad practice to hypernest in SCSS?"问题是“在 SCSS 中超嵌套是不好的做法吗?” (or is it SASS?) I say no. (或者是 SASS?)我说不。 But it's an ancillary argument.但这是一个辅助参数。

The WORSE practice lies in leaving the SASS (or is it SCSS?) output, in it's machine-driven state, for production.糟糕的做法在于将 SASS(或者是 SCSS?)输出留在机器驱动状态,用于生产。

S*SS is a only a tool in your bag of tricks, no different than Notepad++ or Git or Chrome. S*SS 只是你的工具包中的一个工具,与 Notepad++ 或 Git 或 Chrome 没有什么不同。 It's role is to make your life a little easier by bringing some very general programming concepts to the point of building some css.它的作用是通过引入一些非常通用的编程概念来构建一些 css,从而使您的生活更轻松一些。 It's role is NOT building your css.它的作用不是构建您的 css。 You can't expect it to do your job for you and create completely usable, readable, performing output.您不能指望它为您完成工作并创建完全可用、可读、执行的输出。

Nest as much and as deep as you want, then follow Good Practice...嵌套尽可能多和深,然后遵循良好实践...

...which would be going thru your css afterwards and hand tweaking. ...之后将通过您的 css 并手动调整。 Test, build, etc with your hypernested output.使用您的超嵌套输出进行测试、构建等。 And when S*SS creates my first example above, give that anchor a class and call it with nav .class .当 S*SS 创建我上面的第一个示例时,给该锚点一个类并使用nav .class调用它。

Although not directly an answer to your question, you can keep highly nested sass for your own purposes but still use @at-root .虽然不是直接回答您的问题,但您可以为自己的目的保留高度嵌套的 sass,但仍使用@at-root Check it out here . 在这里查看

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

// compiles to ... 

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM