具有后代选择器特异性的通用选择器

时间:2019-03-28 10:51:53

标签: css css-selectors css-specificity

我有一个通用的布局组件,该组件需要对其子级进行布局,并在它们之间设置垂直空间:

.container > * + * {
  margin-top: 1rem;
}

出于我不愿讨论的原因,我不能保证组件样式的加载顺序。

如果子组件已重置为应用其边距,例如……

.child {
  margin: 0
}

…并且它在.container CSS之后加载,其样式将获胜,因为通配符选择器没有特异性,这意味着两个声明的权重相等(因此最后一个声明将获胜)。

我不想让容器知道或关心它的子代是什么(并且我不想为所有子代添加特定的类)。

有什么方法可以提高第一个选择器的特异性,同时保持其通用性(因此适用于所有子代)。

2 个答案:

答案 0 :(得分:2)

一种更优雅的替代方法(即,无需特定的hack即可带来所需的附加特异性)

.container > :not(:first-child)

在功能上等同于原始选择器,与原始选择器的(0,1,0)相比具有(0,2,0)的特异性。

.container {
  margin: 1rem 0;
  border-style: solid;
}

/* 1 class, 1 pseudo-class -> specificity = (0, 2, 0) */
.container > :not(:first-child) {
  margin-top: 1rem;
}

/* 1 class                 -> specificity = (0, 1, 0) */
.child {
  margin: 0;
}
<div class="container">
  <div class="child">Child</div>
  <div class="child">Child</div>
  <div class="child">Child</div>
</div>
<div class="container">
  <div class="child">Child</div>
  <div class="child">Child</div>
  <div class="child">Child</div>
</div>

答案 1 :(得分:1)

通过添加选择器

.container > * + [class] 

您可以为边距规则找到一个更具体的选择器。

您还可以按照Temani Afif

的建议使用:not()规则。

.container, .container2, .container3 {
   background-color: goldenrod;
   border: 1px solid black;
   display: block;
   margin-bottom:50px;
}

.container > * + * {
  margin-top: 1rem;
}

.container2 > * + *,
.container2 > * + [class] {
  margin-top: 1rem;
}

.container3:not(#doyoudreamofelectricsheep) > * + * {
  margin-top: 1rem;
}


.child {
  margin: 0;
  height: 20px;
  background-color:red;
  color: black;
  
}

.foobar {
  height: 20px;
  background-color:black;
  color: white;
}
Without the "fix"
<section class="container2">
   <div class="foobar">
       foobar
   </div>
   <div class="child">
       child
   </div>
   <div class="foobar">
       foobar
   </div>
   <div class="child">
       child
   </div>
   <div class="foobar">
       foobar
   </div>
   <div class>
       just class
   </div>
</section>

With the [class] "fix"
<section class="container2">
   <div class="foobar">
       foobar
   </div>
   <div class="child">
       child
   </div>
   <div class="foobar">
       foobar
   </div>
   <div class="child">
       child
   </div>
   <div class="foobar">
       foobar
   </div>
   <div class>
       just class
   </div>
</section>

With the :not(#doyoudreamofelectricsheep) "fix"
<section class="container3">
   <div class="foobar">
       foobar
   </div>
   <div class="child">
       child
   </div>
   <div class="foobar">
       foobar
   </div>
   <div class="child">
       child
   </div>
   <div class="foobar">
       foobar
   </div>
   <div class>
       just class
   </div>
</section>