不存在一劳永逸的样式。 三张图片的图片库可能需要与十二张图片的图片库采用不同的样式。 您可以在 CSS 中使用一些巧妙的技巧来添加一些基于数字的逻辑! 使用 :nth-child
和 :nth-last-child
,您可以在不离开样式表的情况下获得一些令人惊讶的复杂信息。
本文假设您基本了解 :nth-child
伪选择器的工作原理。 如果您需要快速复习,Chris 有一篇关于该主题的 精彩文章。
编写复杂的 `:nth-child()` 选择器
您可能已经知道,除了 :nth-child
之外,还有一个相关的 :nth-last-child
。 它与 :nth-child
的工作原理完全相同,只是它从父元素的 末尾 开始。 例如,您可以使用选择器 :nth-child(-n + 3)
来选择父元素的 前三个子元素。 您可以使用 :nth-last-child(-n + 3)
来选择 最后 三个子元素。 让我们来看一个无序列表作为示例。
查看 CodePen 上 Adam Giese 的 1. 选择最后三个。
同样,您可以使用 :nth-last-child(n + 4)
来选择 除 最后三个以外的所有子元素。
查看 CodePen 上 Adam Giese 的 2. 选择除最后三个以外的所有子元素。
当您开始将 :nth-last-child
与 :first-child
结合使用时,真正的魔力就出现了。 通过使用这两个选择器来查看某个元素是否既是父元素的第一个子元素,又是最后三个元素之一,您可以仅在父元素最多包含三个元素时为第一个元素设置样式。
li:nth-last-child(-n + 3):first-child {
/* your styling here */
}
继续我们的列表示例,以下是一种可视化此工作原理的方法
查看 CodePen 上 Adam Giese 的 3. 将 “first-child” 和 “last three” 链接在一起。
相反,您可以使用 li:nth-last-child(n + 4):first-child
来选择具有四个或 更多 项的列表的第一个项
查看 CodePen 上 Adam Giese 的 4. 至少三个选择器。
很酷吧? 但是很有可能,您想设置的样式不仅仅是列表中的第一个项。 通过使用普通兄弟选择器,您可以为紧随此第一个元素的任何列表项设置样式。 将这两个选择器用逗号隔开添加,您就可以选择所有元素。
li:nth-last-child(n + 4):first-child,
li:nth-last-child(n + 4):first-child ~ li {
/* your styling here */
}
查看 CodePen 上 Adam Giese 的 5. 至少四个选择器。
这带来了很多有趣的机会! 您也不必仅仅将自己限制在计算元素的总数。 通过将 :first-child
和 :nth-last child
链接在一起,您可以检查任何有效的 :nth-child
表达式是否适用于元素的总数。 您可以编写样式,例如,如果子元素总数为奇数,如果子元素正好为七个,或者如果子元素为 3n + 2
个。
此技术的一个实际用例是为由 CMS 自动生成的下拉菜单设置样式。 例如,让我们来看一下由 WordPress wp_nav_menu()
函数生成的代码,为便于阅读已清理过
查看 CodePen 上 Adam Giese 的 WordPress 菜单 nth-child 示例。
这看起来很标准。 将鼠标悬停在 Members 菜单项上,并注意子菜单项。
现在,让我们看看添加了更多成员的同一菜单
查看 CodePen 上 Adam Giese 的 WordPress 菜单 nth-child 示例,更多子元素。
哇! 适用于四个项的样式无法很好地扩展到十二个项。 通过应用前面的示例,您可以纯粹在样式表中为 WordPress 默认菜单设置样式:无需编写自定义过滤器来更改根据菜单项数量而变化的类:您可以在样式表中保留样式。
查看 CodePen 上 Adam Giese 的 WordPress 菜单 nth-child 示例,紧凑版。
以下是一些其他可能的用例。
- 默认情况下打开的手风琴,如果手风琴的数量低于指定数量。 例如,这对于自动生成的 “常见问题解答” 很有用。
- 有序说明的样式。 如果列表项更少,可以为较大的数字设置样式。
- 颜色样式指南。
- 如果表格行数量足够多,则添加斑马条纹。
局限性
您可以使用 :nth-child
做很多很酷的事情。 但是,也存在一些局限性。 例如,您无法为父元素设置样式,只能为子元素设置样式。 您无法根据 li
元素的数量为 ul
添加任何样式。
另一个需要考虑的问题是,是否使用 :nth-child
或 :nth-of-type
。 使用 :nth-child
将选择所有元素,这可能符合您的要求,也可能不符合您的要求。 例如,如果您想根据段落的数量为 .post-content
添加样式,则需要使用 p:nth-of-type
。 不幸的是,使用这种方法,您只能为第一个段落标签之后(包括第一个段落标签)的子元素设置样式。 如果内容开头有一个 h2
标签,则您将无法根据 p
标签的数量为标题设置样式。 此外,nth-of-type
仅适用于元素:您将无法检查特定类的数量。
我发现,当应用于具有可预测兄弟元素的元素时,此技巧效果最佳。 li
是一个完美的候选元素,因为它们是 ul
和 ol
的唯一有效子元素。 自动生成的内容也可能效果很好。
抽象
这是一个很酷的技巧,但不幸的是语法有点繁琐。 但是,如果您使用 Sass,则可以轻松地添加一层抽象来使其更易于使用! 这将使使用这些复杂的选择器变得更易读、更直观。
由于所有这些选择器都基于一个模式,因此您可以从一个通用混合宏开始
@mixin has-nth($expression, $element: '*') {
&:nth-last-child(#{$expression}):first-child,
&:nth-last-child(#{$expression}):first-child ~ #{$element} {
@content;
}
}
将在 SCSS 中使用类似以下内容调用该混合宏
li {
@include has-nth('n + 4', 'li') { //four or more
/* your styling here */
}
}
虽然这比编写纯 CSS 肯定要简洁得多,但您可以通过定义更多混合宏来添加另一层抽象。 以下是如何编写 at-least
混合宏的示例
@mixin at-least($quantity, $element: '*') {
@include has-nth('n + #{$quantity}', $element) {
@content;
}
}
将在代码中像这样调用它们
li {
@include at-least(4, 'li') { // four or more
// styling goes here...
}
}
可读性肯定有所提高! 您甚至可以通过嵌套混合宏来将它们链接在一起。
这里是使用一些复杂的 nth-child 逻辑的 Sass 混合宏的集合。
未来选择器
目前在 W3C 编辑器草案中有一些附加功能,这些功能可以极大地提高此技术的灵活性。 其中之一是 nth-child
的 选择器列表
参数。 它的工作原理是在 nth-child
选择器中添加一个可选的附加参数。 它的工作原理类似于 nth-of-type
的工作原理,只是它适用于 任何 选择器,而不仅仅是元素。 例如,您可以使用选择器 li:nth-child(odd of .active)
为带有类 active
的所有其他列表项设置样式。 使用此功能,我们可以检测特定类的数量:例如
li.active:nth-last-child(n + 5 of .active).first-child,
li:nth-last-child(n + 5 of .active).first-child ~ li.active {
/* styling goes here... */
}
如果至少有五个活动列表项,这将为它们设置样式。 您可以在 此处了解有关选择器列表的更多信息。 然而,目前浏览器支持非常有限; 它仅在 Safari(iOS 和 OSX)上可用。
另一个功能是 关系伪类选择器。 此建议的选择器接受一个 选择器列表
参数,并在选择器相对于基本选择器存在时匹配。 例如,您可以为 ul:has(li)
设置样式,以对至少包含一个 li
的任何列表添加样式。 您还可以添加更复杂的选择器:.post-content:has(h1, h2, h3, h4, h5, h6)
可以为至少包含一个标题元素的任何 .post-content
设置样式。 将此功能与我们学到的某些高级 nth-child 配方结合使用,我们可以编写 ul:has(li:nth-last-child(n + 5):first-child)
来为至少包含五个 li
的任何 ul
设置样式。
截至目前,按数量设置样式主要适用于为具有可预测兄弟元素的元素设置样式,例如列表或表格。 如果这两个功能得到支持,那么此技术将更加灵活。
哇。很酷的微妙技巧。谢谢你了 :)
很棒的文章!
:nth-child
是我最喜欢的 CSS 部分之一。我用它做了一些有趣的事情,并把它包含在我最近关于 RWD 的演讲中。真的希望选择器列表
和关系伪选择器能得到支持!谢谢!
我喜欢你使用
:nth-child
来创建内容感知 CTA。高效利用空间!很棒的技巧。
has-nth mixin 有个错字:
~ #{$expression}
->~ #{$element}
。好眼力!已修正。
这项技术最近被称为“数量查询”。
这个小应用程序可能也会有帮助 -http://quantityqueries.com/
那是一个很酷的应用程序!它提出了另一个很好的观点——你可以查询子元素数量是否在某个范围内,方法是使用两个
nth-last-child
以及first-child
。很酷,但仅仅因为你可以做到,并不一定意味着你应该在每种情况下都使用它。根据子元素数量对父元素进行样式设置很酷,但在其他场景中,额外的修饰符会使代码更易于预测,更容易理解,我认为 :)
如果你有能力为父元素添加额外的修饰符(比如类),那绝对是一个好方法。不幸的是,有时这不可能:例如,使用 CMS 生成的代码。
我实际上认为这种技术在用 Sass 编写并在 mixin 中抽象时相当易读。以下是上面菜单示例的“Sass 化”样式。
CodePen 链接
很棒的文章!原始 CSS 本身会很混乱,但 SASS mixin 非常棒(而且现在,难道不是每个人都在使用 SASS 吗)。
哇。那是一个很酷的技巧。感谢分享 :)