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



我有一个.scs文件,其中包含以下内容:

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个嵌套选择器!"的言论,但它到底有多有害?它对页面加载有明显的影响吗?我做过的基准测试都说没有,但我还缺少什么吗?

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

现在,Steve Souders说,在普通网站上,这根本不是一个真正的问题。然而,在一个web应用程序或高度交互式的网站上,表现不佳的CSS规则会使你的重新绘制速度比必须的慢。如果你有很多重新绘制。。。

Nicole Sullivan、Paul Irish和Steve Souders等专家已经介绍了CSS与JavaScript交互的方式,以及如何编写高性能的CSS选择器。这不仅仅是深度(不同的选择器有不同的性能),但一个好的经验法则是限制深度和复杂性,以避免麻烦——但不是太多的性能问题,请继续阅读

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

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

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

只需想想如何编写实际的css选择器。不要因为它是元素的子元素就嵌套所有对象。

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

一旦你开始链接这么多选择器,就会很难覆盖,并可能导致特定性问题。

不要嵌套CSS。我们觉得嵌套css很舒服,因为它与我们在HTML中所做的非常相似。嵌套为我们提供了.some-child位于.some-parent内部的上下文。它使我们能够控制级联。但没有其他太多。

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

在实践中嵌套不好会导致页面速度极慢。看看github如何加速他们的差异页面。你至少应该遵循初始规则,该规则规定你不应该嵌套超过4个级别。

然而,我更进一步说,我们根本不应该嵌套CSS。我写了一篇博客,表达了我的观点。希望这是有用的。

只是为了插话并强化他人的言论。这是一种糟糕的做法,不一定从性能的角度来看(去除模糊/阴影和圆角可能会比优化选择器获得更好的绘制时间增加),但从可维护性的角度来看。

选择器嵌套越多,生成的CSS规则就越具体(您已经知道了)。因此,当你想在某个时候"推翻"这条规则时,你必须写一条具有同等(或更大)特异性的规则来推翻第一条规则。如果你有一个ID,这也会让它变得更加具体(所以除非你需要它们,并且知道你不需要重写,否则就要避免)。

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

.selector .another .yeah-another {}

当这将做同样的工作:

.yeah-another {}

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

我的观点:

你告诉哪一个对你的眼睛更糟

从操作

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调用它。

虽然不能直接回答您的问题,但您可以出于自己的目的保留高度嵌套的sas,但仍然使用@at-root。在这里查看。

.parent {
@at-root {
.child1 { ... }
.child2 { ... }
}
} 
// compiles to ... 
.child1 { ... }
.child2 { ... }

最新更新