1

我有一些列表项,我需要在列表元素之间显示行,而不是在第一个和最后一个元素上。

根据这里关于 SO 的许多帖子,这可以使用

第一种方法

.list-item { 
    border-top: 1px solid black;
}

.list-item:first-child{
    border: none;
}

但我自己才意识到它也可以这样完成

第二种方法

.list-item ~ .list-item {
    border-top: 1px solid black;
}

我正在我的办公室项目中实施第二种方法,但我的同事禁止我使用它。

我一直在使用它,因为它很简单,做同样的事情,而且它也通过了浏览器兼容性。那为什么我不应该使用第二种方法呢?(我在这里问是因为我在 SO 上找不到这种方法

我的同事说这会导致项目后期出现错误。所以,我的问题是,真的存在与 CSS 的“兄弟选择器”相关的问题吗?

4

5 回答 5

1

这可能就是他们所说的“错误”

在讨论可能的“错误”之前,我想指出我不同意 nmkol 的回答,因为:first-child在你的情况下这完全没问题。他显示潜在问题的示例是无效的 html,因为 a 的唯一有效子级ul是 an li,因此不应有任何其他“类型”的子级是 an 的兄弟姐妹li

现在关于“错误”。

第一的

一个代码根据您的需要提供您的行,并且还允许以后的 css(可能是您同事制作的项目中的其他 css)像这样覆盖它

.list-item {
   border: none;
}

但是,如果您使用第二个代码,上述覆盖将不起作用,因为覆盖不够具体,无法克服原始选择器代码的特殊性。所以这可以被视为一个“错误”,因为它需要某种方式来增加特异性来覆盖它,其中可能没有一种“优雅”的方式来做到这一点,而只能通过像这样的一些“冗余”增加(冗余,因为:nth-child(n)匹配所有元素):

.list-item:nth-child(n) {
    border: none;
}

或者这种冗余(仅说明该类两次):

.list-item.list-item {
    border: none;
}

但是,还有其他增加特异性的方法可能不是多余的,但您的同事可能不希望必须增加特异性。

第二

两个版本都与旧浏览器有一些“错误”,只是不同。:first-child因此,您的同事可能会认为伪类比一般的同级选择器~错误更少,这可能取决于需要什么浏览器支持。

就个人而言,我会要求他们更具体地说明您的第二个代码引入的“错误”。这将帮助您更清楚地确定他们认为问题是什么(这可能是我在这里没有给出的一些“第三个”想法)。

更好的是?

由于您的预期支持是 IE9+,那么这个选择器可能是您最好的解决方案

.list-item:not(:first-child) { 
    border-top: 1px solid black;
}

我说“最好”是因为:

  1. 它将其保持为单个(非级联)选择器
  2. 它将其保留为仅评估相关项目的选择器(换句话说,浏览器不需要检查任何先前元素的状态,这是 的一般兄弟组合的情况.list-item ~ .list-item),因此提高了性能。
  3. 在做什么比较清楚一点,就是选择.list-item除非是第一个。也不是很明显.list-item ~ .list-item也跳过第一项并且只跳过第一项(尽管当人们考虑它时,他/她会得出那个结论)。

如果这些没有用于li元素(例如,元素的“列表” div),那么:first-child可能需要替换为:first-of-type(假设没有其他非“列表项”元素属于同一类型; 实际上,这个想法是为与li元素一起使用而设计的)。

于 2013-11-16T15:32:41.143 回答
1

正如其他两个答案中已经说明的那样,我看不出为什么您的方法应该是“错误的”。但是您的一般概念还有其他一些问题。

我假设您的标记看起来像这样:

<ul>
   <li class="list-item">...</li>
   <li class="list-item">...</li>
   <li class="list-item">...</li>
   <li class="list-item">...</li>
</ul>

无论是有序列表还是无序列表都无关紧要。

因此,关于您的方法的第一点是使用 class 属性。如果您只有三个或四个列表项,那么可能没关系,但想想如果您有一百个或更多元素,这将是多么无效。

因此,通常应避免在每个列表项上使用类属性,而不是在父元素上使用它。

<ul class="my-list">
   <li>...</li>
   <li>...</li>
   <li>...</li>
   <li>...</li>
</ul>

其次,类和 id 名称应始终与各自元素的内容相关,而不是与它们的呈现相关,因为它们的呈现可能会改变!
(所以“my-list”不是一个好的选择,应该用与内容相关的名称替换。或者使用 ID 而不是类属性甚至可能更好。)

你还写道:

...但不是第一个和最后一个元素。

我看不出你将如何用你的方法来实现这一点,无论是第一个还是第二个,因为你只将第一个li元素与它们两个匹配。

将有另一种解决方案(取决于所需的浏览器支持)与第一个元素不匹配:

.my-list li:not(:first-child) {
   border-top: 1px solid black;
}

如果您还想排除最后一个元素:

.my-list li:not(:first-child):not(:last-child) {
   border-top: 1px solid black;
}

如果它是一个嵌套列表,您可以像这样使用子选择器

.my-list > li:not(:first-child):not(:last-child) {
   border-top: 1px solid black;
}

与往常一样,有许多不同的方法可以用 CSS 实现相同的目标。哪一个可能是最好的取决于各自项目的具体情况。一般来说,牢记KISS 原则并不是一个坏主意!;-)

于 2013-11-17T22:31:04.347 回答
1

不像其他答案那样大而详细,因为我觉得实际上不需要详细说明这个......

tl;博士

我们在这里支持 IE9+。你能就我应该采用哪种方法发表意见吗?(我上面提到的两种方法) 这里

答案是,如果你使用或使用任何东西都没有问题,因为两者都是完全兼容的..~first-child

这里唯一的问题是,如果您在~like this中有其他一些属性,那么它可能会给您带来问题,如果您使用first-child它而不是,请检查一下...


我的同事说这会导致项目后期出现错误。- 首先请询问他们一般同级选择器确实会产生什么样的错误。

所以,我的问题是,真的存在与 CSS 的“兄弟选择器”相关的问题吗?- 答案是否定的

就兼容性而言,您可以参考下表。

在此处输入图像描述


所以,现在我已经给你分享了兼容性表,如果你使用通用的兄弟选择器绝对没有问题~,如果你的同事有多余的使用它..我会为你提供一些替代解决方案..

解决方案 1 - 年份

class在元素的第一个子li元素上使用

ul li {
    border-top: 1px solid #eee;
}

ul li.first {
    border-top: 0;
}

演示


解决方案 2 - 使用[1]first-child(你已经有了这个)

ul li {

    border-top: 1px solid #eee;
}

ul li:first-child {
    border-top: 0;
}

演示 2

1.兼容性


最后但同样重要的是,您也可以使用first-of-type,而不是first-child再次,兼容性将是一个问题,因为first-child与 相比,兼容性要好得多first-of-type,或者您可以使用last-of-typelast-child但同样,兼容性也会导致问题,而不是使用border-top您将border-bottom: 0;如果你要去last-child或必须使用last-of-type

于 2013-11-18T11:43:57.290 回答
1

1)既然您提到您的目标是 IE9+ - 浏览器支持在这里无关紧要,因为这两种方法都受支持。

2)虽然方法#2似乎更简洁,因为您已成功将顶部边框放置在一个规则中除第一个元素之外的所有元素上并且没有覆盖边框-

i)在这些情况下覆盖规则似乎是一个更好的主意,因为它们清楚地显示了代码在做什么

ii)如果列表项除了边框顶部(通常是这种情况)之外还需要进一步的样式,那么无论如何您都需要在方法#2 中使用额外的规则来定位所有列表项的样式。

因此,我会坚持使用方法 #1,因为代码清晰度优于方法 #2。

于 2013-11-18T11:09:29.943 回答
0

好吧,我不确定为什么您的选择器以后会导致错误。

我所知道的是您的选择器并不完全相同。

首先:first-child选择器将选择第一个元素。用元素指定它,<li>只有当它是第一个元素时才会被选中。

如您所见,这里的第一个选择器不起作用。

但是,:first-of-type它与您的第二个选择器相同。但是,这不适用于课程!

我自己会选择您的选择器,因为它更具体您想要什么。如果您要使用,:first-of-type我仍然会使用您的选择器,因为它的编码更加“智能”,并且您不需要任何覆盖代码来禁用边框。您也可以将选择器与类结合起来。

我建议你问问你的同事他们为什么会这么说,因为我看不出任何这种情况会成为问题。


然而,对于较旧的浏览器存在一个错误,其中动态伪类将无法与通用同级或相邻同级选择器结合使用。

错误:https ://bugs.webkit.org/show_bug.cgi?id=32695

这似乎在以后的版本中得到修复。

于 2013-11-13T12:32:05.610 回答