首页 >web前端 >html教程 >CSS秘密花园: 相邻元素样式_html/css_WEB-ITnose

CSS秘密花园: 相邻元素样式_html/css_WEB-ITnose

WBOY
WBOY原创
2016-06-21 08:51:05949浏览

《 CSS Secrets 》是 @Lea Verou 最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北和@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

问题

在很多情况下,我们需要给元素的兄弟元素以不同的样式风格呈现。主要的用例是提高用户体验和在大屏幕中不断增加列表荐。下面是一些使用场景:

邮件列表或类似基于文的列表展示。如果我们只有为数不多的列表项,我们可以单独展示。随着列表项的增加,我们可以减少列表的预览项。当列表的高度大于视窗高时,我们可能会选择隐藏一些列表项,或者在尾添加一个查看更多的按钮,让用户在不滚动滚动条也能浏览列表。

App中的待办事项列表(to do list),可以给几个列表项设置大的文本样式,但随着列表项数目增加,列表项目的设置较小的字号。

用来显示颜色的调色板APP。有人可能想随着颜色数量增加,利用好空间让颜色控制面板变得更紧凑些,如下图所示:

随着颜色的数量增加,逐步缩小控制颜色的埠和减少可用空间。注意,在特殊情况之下,当只有一个颜色时,会隐藏删除按钮。

具有多个

然而,针对元素相邻兄弟元素来选择目标元素不是简单的CSS选择器。例如,当列表总数是 4 个时给列表不同样式。我们可以使用 :nth-child(4) 来选择列表的第四个列表项,但这并不是我们所需要的,我们要的是当列表总数为 4 的时候,选择列表的每一个列表项。

有一个想法就是使用通用选择符( ~ )和 :nth-child() 选择器配合使用,例如 li:nth-child(4),li:nth-child(4)~li 。不管列表项总数有多少,只选择了第四个项和其之后的所有列表项,如下图所示:

因为没有“向后选择器”和选择元素之前的兄弟元素的选择器,那么CSS就注定不能选择到需要的目标元素吗?我们不应该失去信心,一切皆有可能。

解决方案

有一个特殊案例就是只有一个单独的列项项目,有一个明显的解决方案: :only-child 选择器,这个选择器就是为这种情况而生的。他是非常有用的,这也是为什么会将其添加到规范中。例如前面提到的颜色调控板APP,当只有一个颜色时,会隐藏删除按钮,那么就可以使用 :only-child 选择器来实现。

li:only-child {    /* 当只有一个列表项时的样式 */}

我们在这一节讨论的是 :nth-child() 选择器,但这一切的讨论都同样适用于 :nth-of-type() 选择器。往往这种类型选择器更适用,通常情况之下,容器中会有不同类型的兄弟元素,使用这种类型选择器,我们只要关心一种类型。这里将使用列表元素做为示例讨论,但讨论中的一切都适用于任何类型元素。

然而, :only-child 相当于 :first-child:last-child ,他是第一项也是最后一项,从逻辑上可以得出结论,他就是唯一的项目。其实, :last-child 就是 :nth-last-child(1) 简写。

li:first-child:nth-last-child(1) {    /* 和li:only-child等同 */}

当然,现在 1 就是一个参数,我们可以根据自己的喜好调整这个参数。你能猜出 li:first-child:nth-last-child(4) 选到的目标是什么?如果你回答,当列表的总数是四个的时候,选择到 :only-child 的目标元素,你可能太过于乐观了一点。其实事实并不是这样,但是离我们正确的选择目标越来越接近。分别考虑两个选择器: :first-child 和 :nth-last-child(4) 。因此,在相同时间从元素第一个子元素开始计数和倒数第四个子元素计数。那么哪些元素满足这个范围呢?

正确答案是,只个四个元素的列表的第一个元素被选中,如下图所示:

这并不是我们想要的结果,但已非常接近我们需要的效果。因为我们在一个列表中选择到了第一个子元素,我们可以使用通用选择符( ~ )来选择第一个子元素后的相邻兄弟元素。这样一来,如果列表只有四个列表项时,所有列表项都将被选中。这正是我们试图要实现的效果:

li:first-child:nth-last-child(4),li:first-child:nth-last-child(4) ~ li {    /* 目标选择了仅有四个列表项的列表所有列表项 */}

为了避免代码的冗长和重复的解决方案,可以使用预处理器,例如SCSS。尽管现有的预处理器语法比图笨拙:

/* 定义mixin */@mixin n-items($n) {    &:first-child:nth-last-child(#{$n}),    &:first-child:nth-last-child(#{$n}) ~ & {@content; }}/* 像这样使用 */li {    @include n-items(4) {        /* 这里写样式 */    }}

选择兄弟元素范围

在大多数实际运用中,我们并不希望瞄准特定数量的列表,而是希望在一个范围内。有一个小技巧,我们可以使用 :nth-child() 选择器来指定一个选择范围。例如选择第四个之后的列表项。除了使用简单的数字作为参数之外,还可以使用 an+b 表达式作为参数(例如: :nth-child(2n+1) ),其中 n 是一个变量,范围是从 0 到 +∞ (实际上,值在某点不会选择任何东西,因为我们元素的数量是有限的)。如果我们使用一个表达式 n+b ( a 默认下是 1 ),那么,如果 n 不是一个正整数时可以给我们一个小于 b 值的范围。因此,表达式 n+b 可以用来第 b 个值为第一个子元素所有子元素。例如: :nth-child(n+4) 选择除了第一、第二、第三的所有子元素。如下图所示:

如果你不想为 :nth-* 选择器做过多的思考,你可以使用一个测试工具,我写了一个 在线的工具 ,足够你做测试。

我们可以利用这个功能来选择列表项是四个或更多的列表子元素,如下图所示:

在这种情况下,我们可以在 :nth-last-child() 使用 n+4 这个表达式:

li:first-child:nth-last-child(n+4),li:first-child:nth-last-child(n+4) ~ li {    /* 目标列表选择最少包含四个列表项 */}

同样,表达式 -n+b 可以用来选择第 b 个元素。因此,选择仅有四个或更少的列表项的列表的所有子元素时,就可以使用这种表达式。

如上图所示,我们代码可以这样写:

li:first-child:nth-last-child(-n+4),li:first-child:nth-last-child(-n+4) ~ li {    /* 选择列表项最多只有四个的列表所有子元素 */}

当然,我们可以结合这两个,但现在的代码变得更加笨拙。假设我们列表包含 2~6 项的列表所有子元素:

li:first-child:nth-last-child(n+2):nth-last-child(-n+6),li:first-child:nth-last-child(n+2):nth-last-child(-n+6) ~ li{    /*选择包含2-6个列表项的列表所有子元素*/}
声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn