css 预处理器选择_CSS预处理器的选择器特异性
阅读原文时间:2021年04月20日阅读:1

css 预处理器选择

Selector specificity is a real problem for most medium and large-sized projects, and as any other frequently recurring coding problem it needs to be addressed carefully. Even CSS-Tricks recently had an article on how to keep your CSS specificity low.

对于大多数中型和大型项目来说,选择器的特殊性是一个实际的问题,与其他任何经常重复出现的编码问题一样,它也需要仔细解决。 甚至CSS-Tricks最近也有一篇文章介绍了如何降低CSS特异性

And before you even try to say !important let me remind you that:

!important让我提醒您:

CSS/everyday tip: if everything is !important, nothing is !important.

CSS /日常技巧:如果一切都很重要,那么什么都不重要。

– Tony Nelson (@tonynelson19) November 18, 2010

–托尼·尼尔森(@ tonynelson19) 2010年11月18日

CSS specificity isn’t that complex, but the community has done a lot to make it as easy to comprehend as possible, writing guides by using analogies with fish and Star Wars, or by using poker terminology. There are interactive calculators available online, and even a specificity mixin for Sass, allowing you to check and output the exact specificity value of a selector.

CSS的特殊性并不那么复杂,但是社区已经做了很多工作,以使其尽可能容易理解,使用与鱼类《星球大战》的类比或使用扑克术语编写指南。 在线提供了交互式 计算器 ,甚至还有Sass特异性mixin ,您可以检查并输出选择器的确切特异性值。

Simpler is better when in comes to a CSS specificity strategy, the specificity workarounds in this article (which may feel a bit hacky) are suited for cases where the architecture doesn’t allow for a simple fix. Use your judgment when deciding which approach suits your project best and ultimately try to hit the perfect balance between clean and maintainable CSS.

当涉及到CSS专用性策略时,越简单越好,本文中的专用性变通办法(可能会让人觉得有些棘手)适用于架构不允许简单修复的情况。 在决定哪种方法最适合您的项目时,请使用您的判断力,并最终尝试在干净和可维护CSS之间达到完美的平衡。

方法#0 – BEM (Approach #0 – BEM)

BEM is more than a naming convention, it is a front-end toolkit invented by Yandex, the philosophy of which is to get closer to object-oriented programming. In practice, this means using a class name for every single thing that you style. Although “no cascading in Cascading Style Sheets” may sound preposterous to some, the idea to never use type selectors and to avoid nesting is extremely helpful when creating modules that should be maintainable, portable, self-sufficient, easy-to-modify, and scalable.

BEM不仅仅是一个命名约定,它还是Yandex发明的一种前端工具包,其理念是更接近于面向对象的编程。 实际上,这意味着您要为样式设置的每件事使用一个类名。 尽管“级联样式表中没有级联”听起来有些荒谬,但是在创建应维护,可移植,自给自足,易于修改和可修改的模块时,永远不要使用类型选择器并避免嵌套的想法非常有用。可扩展的。

One of the main benefits of the BEM methodology though is that it keeps specificity the same for every selector, so there should be practically zero issues caused by overly specific selectors, this is why this approach is #0 – if you adopt it you are essentially eliminating any future problems with selector specificity in a project.

BEM方法的主要优点之一是,它对每个选择器都保持相同的特异性,因此,过分具体的选择器实际上应该存在零问题,这就是为什么这种方法是#0的原因 –如果采用它,则本质上是消除项目中选择器特定性的任何未来问题。

规则的特殊性 (Specificity of Rules)

Since you’ll be using only single classes for everything you write, every single selector will have a specificity of 0,1,0

由于您将只使用单个类来编写所有内容,因此每个选择器的特异性为0,1,0

当BEM不能解决问题时 (When BEM isn’t the answer)

There are countless success stories of front-end architectures that use BEM, however, as popular as BEM may be, it is not suited for a specific type of projects. It seems to work great for projects where front end developers are the only people that write the HTML. If you do however write for a CMS where content editors without any HTML skills write at least some of the content then BEM will be severely limiting.

使用BEM的前端体系结构有无数成功的故事,但是,尽管BEM可能很流行,但它并不适合特定类型的项目。 对于前端开发人员是唯一编写HTML的人的项目,这似乎非常有用。 但是,如果您确实为CMS编写内容,而没有任何HTML技能的内容编辑者至少写了一些内容,那么BEM将会受到严重限制。

BEM at its pure form does not allow for nesting and type selectors such as .Section--dark > a (to give it a light color for example), instead it requires you to invent a class for the anchor tag. This leads to a problem – a content editor will insert a default link through a graphic interface which may result in hardly-visible links. This may also apply to all paragraphs, lists, or images within a specific section. Sometimes being able to write pure HTML content without classes is needed, in such cases the solution is having it all style itself by a parent with descendant selectors. This use of cascading allows for contextual flexibility – the presence of custom styles for something when it’s in a different context.

BEM的纯格式不允许嵌套和类型选择器,例如.Section--dark > a (例如, .Section--dark > a赋予浅色),相反,它需要您为锚标签创建一个类。 这就导致了一个问题–内容编辑器将通过图形界面插入默认链接,这可能会导致难以看见的链接。 这也可能适用于特定部分中的所有段落,列表或图像。 有时需要能够编写不带类的纯HTML内容,在这种情况下,解决方案是由具有后代选择器的父项自行设置所有样式。 级联的这种使用可实现上下文灵活性-在不同上下文中某些对象的自定义样式。

So we need an actual solution for when we can’t use pure BEM, which is quite often. CSS preprocessors can help us here, and all 3 of the popular ones – LESS, Sass, and Stylus are able to ease our job when we need to override a selector with a more specific one.

因此,当我们不能使用纯BEM时(这很常见),我们需要一个实际的解决方案。 CSS预处理器可以在这里为我们提供帮助,当需要用更具体的选择器覆盖选择器时,所有3种流行的预处理器(LESS,Sass和Stylus)都可以简化我们的工作。

方法1 –前面有一个选择器 (Approach #1 – Prepend with a selector)

When you encounter a specificity problem and want to make a certain selector heavier you can prepend the existing selector with a class, attribute, id, or a type selector. In this way you can bump the specificity just a bit. While this feature has mostly been used to target IE with a conditional html tag, it has a lot more power that awaits to be harnessed.

当您遇到特定性问题并希望增加某个选择器的重量时,可以在现有选择器之前添加类,属性,ID或类型选择器。 通过这种方式,您可以稍微提高特异性。 尽管此功能主要用于通过条件html标签定位IE,但它具有更多功能可供使用。

The parent reference selector (&) in CSS preprocessors easily allows us to prepend a selector to make it heavier, thus we can do the following:

CSS预处理器中的父引用选择器 ( & )可以轻松地使我们在选择器前添加使其更重,因此我们可以执行以下操作:

.class {
  body & {
    foo: bar;
  }
}

Resulting in this CSS

产生此CSS

body .class {
  foo: bar;
}

You might want to prepend it with the html or body tag, but you can just as well use something more specific that is present on all your pages such as .page, #wrapper, html[lang], etc.

你可能想用加前缀htmlbody标记,但你可以如用更具体的东西是存在的所有网页,例如.page#wrapperhtml[lang]等。

Sass allows you to put the prepending selector within a variable in case of future changes, additionally, for larger projects it might be worth creating a set of prepending selectors with different weights:

Sass允许您在将来进行更改时将前置选择器放入变量中,此外,对于较大的项目,可能值得创建一组权重不同的前置选择器:

$prepend1: "html &";
$prepend2: "#wrapper &";

.selector {
  #{$prepend1} {
    background: #cacaca;
  }
  #{$prepend2} {
    background: #fefefe;
  }
}

Which will result in:

这将导致:

html .selector {
  background: #cacaca;
}
#wrapper .selector {
  background: #fefefe;
}

Other popular preprocessors such as LESS and Stylus also offer this functionality.

其他流行的预处理器(如LESSStylus)也提供此功能。

规则的特殊性 (Specificity of Rules)

Prepending our initial class selector 0,1,0 with a type selector will result in 0,1,1, prepending with an id – 1,1,0. The drawback here is that once you prepend something with your heaviest selector (i.e. #wrapper) you can no longer override it until you invent a new, heavier selector, which isn’t always possible.

在我们的初始类选择器0,1,0加上类型选择器,将得到0,1,1 ,在其ID之前加上– 1,1,0 。 这里的缺点是,一旦您在最重的选择器( #wrapper )之前添加了某些内容,就无法覆盖它,除非您发明了一个新的更重的选择器,但这并不总是可能的。

方法2 –自链选择器 (Approach #2 – Self-chained selectors)

Prepending a selector is useful but it is not an infinitely scalable solution – you may have limited number of ways to target a parent. Also, once you prepend more than one selector with the heaviest option in your code you limit your options to resolve a specificity problem later on (especially if you’ve used an id).

在选择器前添加一个选择器很有用,但它不是无限扩展的解决方案–您定位父对象的方式可能有限。 同样,一旦在代码中使用最重的选项为多个选择器添加了前缀,就限制了以后解决特定性问题的选项(特别是如果使用id的话)。

The front-end community has recently been reminded of one very useful CSS feature – self-chaining a selector to increase its specificity. Self-chained selectors work with ids, classes, attribute selectors, but not type selectors. Still, if you use predominantly classes to style your content self-chaining offers you an infinitely scalable way to override any selector.

最近提醒前端社区一个非常有用CSS功能– 自动链接选择器以增加其特异性 。 自链接选择器可用于ID,类,属性选择器,但不能与类型选择器一起使用。 但是,如果您主要使用类来设置内容样式,则自链接将为您提供无限扩展的方式来覆盖任何选择器。

With the help of the parent reference selector you can easily chain the same selector to itself multiple times (this applies to ids, classes, and attribute selectors, but not type selectors). You will need to interpolate every & after the first though and the minimum requirement is Sass 3.4:

借助父级引用选择器,您可以轻松地多次将同一选择器链接到自身(这适用于id,类和属性选择器,但不适用于类型选择器)。 您需要在第一个之后插入& ,最低要求是Sass 3.4:

.selector {
  &#{&} {
    background: #cacaca;
  }
  &#{&}#{&} {
    background: #fefefe;
  }
}

.selector.selector {
  background: #cacaca;
}
.selector.selector.selector {
  background: #fefefe;
}

Once again, you can also do this with LESS and Stylus.

同样,您也可以使用LESSStylus进行此操作。

If this is too ugly for your taste you can always create a mixin that can iteratively increase the specificity of any single selector. This mixin uses some advanced features and also requires Sass 3.4:

如果这对于您的口味来说太难看了,您可以随时创建一个mixin,它可以迭代地提高任何单个选择器的特异性。 此mixin使用一些高级功能,并且还需要Sass 3.4:

@mixin specificity($num: 1) {
  $selector: &;
  @if $num > 1 {
    @for $i from 1 to $num {
      $selector: $selector + &;
    }
    @at-root #{$selector} {
      @content;
    }
  }
  @else {
    @content;
  }
}

.selector {
  @include specificity(2) {
    background: #cacaca;
  }
  @include specificity(3) {
    background: #fefefe;
  }
}

Resulting in the following CSS:

产生以下CSS:

.selector.selector {
  background: #cacaca;
}
.selector.selector.selector {
  background: #fefefe;
}

You can create an identical mixin in Stylus, unfortunately there are no easy ways to create such a mixin in LESS.

您可以在Stylus中创建相同的mixin,但是不幸的是,没有简单的方法可以在LESS中创建这样的mixin。

规则的特殊性 (Specificity of Rules)

Self-chaining will increase the specificity of a selector from 0,1,0 to 0,2,0 to 0,3,0 and so on, making it almost infinitely scalable.

自链接将选择器的特异性从0,1,0增加到0,2,00,3,0 ,依此类推,使其几乎可以无限扩展。

最后的想法 (Final Thoughts)

The natural next step in dealing with specificity problems in our smarter-than-ever CSS would be creating a way to identify conflicting declarations, calculate the specificity of each of the entities with something like David Khourshid’s Sass mixin and then automatically using one of the approaches above to bump up the specificity. Maybe my dreams for self-aware stylesheets are too optimistic, but I think that as CSS preprocessors evolve, the sophisticated logic in our code will increase.

处理比以往任何时候都聪明CSS中的特异性问题的自然下一步就是创建一种方法来识别冲突的声明,使用David Khourshid的Sass mixin之类的方法计算每个实体的特异性,然后自动使用其中一种方法以上来提高特异性。 也许我对自我意识样式表的梦想太乐观了,但是我认为随着CSS预处理程序的发展,我们代码中复杂的逻辑将会增加。

Which of the approached above would you use next time you need to battle with specificity issues? What other strategies do you use to solve your specificity problems?

下次您需要与特异性问题作斗争时,将使用上面哪种方法处理? 您还使用其他哪些策略来解决您的特异性问题?

翻译自: https://www.sitepoint.com/selector-specificity-css-preprocessors/

css 预处理器选择