我有一些列表项,我需要在列表元素之间显示行,而不是第一个和最后一个元素。
根据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的“兄弟选择器”相关的问题?
答案 0 :(得分:1)
在讨论可能出现的“错误”之前,我想指出,我不同意nmkol的回答,:first-child
在你的情况下完全没问题。 His example showing a potential issue是无效的html,因为ul
的唯一有效子项是li
,所以永远不应该有任何其他“类型”的孩子是{{1}的兄弟}}
现在关于“错误”。
<强>第一强>
first code根据您的意愿提供您的行,并且还允许后来的CSS(也许是您的同事在项目中的其他css)to override it like so:
li
但是,上面的覆盖不起作用if you use the second code,因为覆盖不够具体,无法克服原始选择器代码的特殊性。所以这可能被视为一个“错误”,因为它需要某种方式来提高覆盖它的特异性,其中可能没有“优雅”的方式去做,而只是通过一些“多余的”增加{{ 3}}(冗余,因为.list-item {
border: none;
}
匹配所有元素):
:nth-child(n)
或like this(仅列出两次课程):
.list-item:nth-child(n) {
border: none;
}
然而,还有其他增加特异性的方法可能不会多余,但可能是你的同事不希望增加特异性。
<强>第二强>
这两个版本对旧版浏览器都有一些“bugginess”,只是区别对待。因此,可能取决于所需的浏览器支持,您的同事可能会认为this redundancy比:first-child
pseudo-class更少错误。
就个人而言,我会要求他们更具体地说明您的第二个代码引入的“错误”。这将有助于您更清楚地了解他们认为问题的原因(这可能是我在这里没有给出的一些“第三”想法)。
由于您的预期支持是IE9 +,因此此选择器可能是您的the general sibling selector ~
:
.list-item.list-item {
border: none;
}
我说“最好”因为:
.list-item:not(:first-child) {
border-top: 1px solid black;
}
,除非它是第一个。显而易见的是.list-item ~ .list-item
也跳过第一项而只跳过第一项(尽管当人们考虑它时,他/她会得出这个结论)。如果.list-item
元素上没有使用这些元素(例如,.list-item ~ .list-item
元素的“列表”),那么li
可能需要替换为div
(这假设没有其他非“list-item”元素属于同一类型;实际上这个想法是为与:first-child
元素一起使用而设计的。)
答案 1 :(得分:1)
正如其他两个答案中所述,我不明白为什么你的方法应该是“越野车”。但是你的一般概念还有其他一些问题。
我认为你的标记看起来像这样:
<ul>
<li class="list-item">...</li>
<li class="list-item">...</li>
<li class="list-item">...</li>
<li class="list-item">...</li>
</ul>
如果它是有序或无序列表并不重要。
因此,关于您的方法的第一点是使用class属性。如果你只有三个或四个列表项,那么也许没关系,但想想如果你有一百个或更多的元素,这是多么无效。
因此,通常应避免在每个列表项上使用class属性,而不是在父元素上使用它。
<ul class="my-list">
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
其次,class和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 principle并不是一个坏主意! ; - )
答案 2 :(得分:1)
1)由于您提到您的目标是IE9 +,因此浏览器支持与此无关,因为这两种方法都受支持。
2)虽然方法#2似乎更简洁,但您已成功将顶部边框放在除一个规则中的第一个元素之外的所有元素和不覆盖边界 -
i)在这些情况下覆盖规则似乎是一个更好的主意,因为它们清楚地显示了代码正在做什么
和
ii)如果列表项除了border-top之外还需要进一步的样式(通常情况下是这样) - 那么在方法#2中你需要一个额外的规则来定位所有列表项目。
所以我会坚持使用方法#1,因为代码清晰度略微优于方法#2。
答案 3 :(得分:1)
我不会像其他答案那样大而详细,因为我觉得实际上不需要详细阐述这个......
我们在这里支持IE9 + ..您能否就此发表意见 我应该采取什么方法? (我上面提到的两个appraches) (Here)功能
如果您使用~
或使用first-child
,则答案是没有问题,因为两者完全兼容..
这里唯一的问题是,如果你在~
first-child
内有其他一些属性,可能会导致问题,就好像你使用~
一样它不会,检查this ...
我的同事说它会在项目后期导致错误。 - 首先请问他们一般兄弟选择器真正产生了什么样的错误。
所以,我的问题是,是否真的存在与CSS的“兄弟选择器”相关的问题? - 答案是否
就兼容性而言,您可以参考下表..
所以,现在我已经和你分享了兼容性表,如果你使用普通兄弟选择器class
,那绝对没有问题,如果你的同事有多余的话可以使用它...我会为你提供一些替代解决方案..
解决方案1 - 复古
在li
元素的第一个孩子
ul li {
border-top: 1px solid #eee;
}
ul li.first {
border-top: 0;
}
ul li {
border-top: 1px solid #eee;
}
ul li:first-child {
border-top: 0;
}
解决方案2 - 使用Demo [1] (您已经拥有此项目)
first-of-type
1。 Demo 2
最后但至少你也可以使用first-child
而不是first-child
,但同样,兼容性也是一个问题,因为与first-of-type
相比,last-of-type
更兼容您可以使用last-child
和border-top
,但同样,兼容性也会导致问题,而不是使用border-bottom: 0;
如果您要去,则必须使用last-child
last-of-type
或{{1}}
答案 4 :(得分:0)
嗯,我不确定为什么你的选择器可能会在以后导致错误。
我所知道的是你的选择器并不完全相同。
首先,:first-child
选择器将选择第一个元素。使用元素<li>
指定它只有在它是第一个元素时才会被选中。
正如您所见Here,第一个选择器无效。
但是:first-of-type
与第二个选择器的选择器相同。 然而,这不适用于课程!
我自己会选择你的选择器,因为它更具体你想要的。
如果您使用:first-of-type
,我仍然会使用您的选择器,因为它更加“智能”编码,您不需要任何重叠代码来禁用边框。 您也可以将选择器与类结合使用。
我建议你问你的同事他们为什么会这么说,因为我不会看到这是一个问题的任何情况。
但是对于较旧的浏览器存在一个错误,其中动态伪类无法与一般兄弟或相邻的兄弟选择器结合使用。
bug:https://bugs.webkit.org/show_bug.cgi?id=32695
这似乎在以后的版本中得到修复。