minimal主题的样式文件中发现了下面的代码, 对”+”号有点不理解, 于是在《CSS权威指南》里查了一下, 发现这是相邻兄弟结合符Adjacent Sibling Combinator, 也叫 相邻兄弟选择器.

1
2
3
4
header ul li + li + li {
border-right:none;
width:89px;
}

语法

因为之前在看这本书时就发现中文版有挺多错误, 而且很多解释都十分费解, 所以中英版的内容都看了, 果然发现中文版的翻译有一部分是错误的, 书中说明该结合符的功能时用了下面的例子:

选择紧接着, 具有共同父元素的元素

1
2
3
h1 + p {
margin-top: 0;
}

中文版对其的解释是: “选择紧接在h1元素后出现的所有段落, h1与p有共同的父元素. “

英文原版是这样的: “selects any paragraph that immediately follows an h1 element that shares a parent with the p element.”

any在这里并不是所有的意思, 我认为这句话的意思应该是: 紧接在h1元素之后的一个p元素, 同时h1和p有共同的父元素. 经过测试, 也证实了我的想法.

不作用于第一个’+’前的元素

然后又给出了另一个例子, 看到这个例子之后我发现, 有可能是因为这个例子对译者造成了影响, 这个例子是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
<div>
<ol>
<li>List item 1</li>
<li>List item 1</li>
<li>List item 1</li>
</ol>
<ul>
<li>A list item</li>
<li>Another list item</li>
<li>Yet another list item</li>
</ul>
</div>
1
2
3
li + li {
font-weight: bold;
}

看到上述的样式, 我下意识地认为只有第二个li应该加粗, 因为我把li + li中的前一个当做第一个li了, 但实际上并没有这样指明, 因此li可以指任意li. 书上举出这个例子, 想要指明的概念是: 第一个li元素, 不会被这个选择器影响, 因此, 除了第一个以外的li, 其他li元素均加粗.

没有标签的纯文本不算是兄弟元素

接下来书上举出了第三个例子, 在上述ul与ol之间插入一段文本, 说明了不使用任何标签的文本不能被当做兄弟元素, 相邻兄弟结合符会自动忽略文本.

可以结合其他选择器使用

同时该结合符可以和其他选择器结合使用:

1
2
3
html > body table + ul{
margin-top: 1.5em;
}

该选择器选择的是: html的子元素body下含有的table元素下紧接着的具有共同父元素的ul元素

理解了该选择器的功能之后, 就可以知道header ul li + li + li选择的是header元素下的ul元素下的第3个li元素.

应用

现在有这样一种情况: 我手头上有一个公司的列表, 列表中的几乎每一个公司都有这样的这样的信息: 表示该公司的一幅图片以及描述图片的文本. 但是并不是所有公司都有图片, 而文本是全部都有的.

现在需要在页面上呈现这些内容, 有图片的公司只显示图片不显示文本, 对于没有图片的公司, 就显示文本.

这时, 就可以利用”+”选择器来达到隐藏某些文本的目的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="page-wrap">
<img src="images/image-110.png" alt="image">
<span>Text</span>
<br><br>
<img src="images/image-110.png" alt="image">
<span>Text</span>
<br><br>
<span>Text</span>
<br><br>
<img src="images/image-110.png" alt="image">
<span>Text</span>
<br><br>
<span>Text</span>
</div>
1
2
3
4
5
6
7
8
9
10
11
img {
vertical-align: middle;
z-index: 9999;
position: relative;
}
span {
z-index: 1;
}
img+span {
margin-left: -110px;
}

设置负值外边距将紧接在img元素之后具有共同父元素的span元素”踢”到图片下方将其隐藏, 而对于不与img相邻的span元素, 不执行这样的操作.

仅设置外边距难以确保span被隐藏, 因此还需要再设置两者的z-index值保证span在img下方, 在img下设置position: relative;以确保z-index正常作用.

这个方法的好处在于即使图片出现问题, 我们还是能够获取文本信息. 但也有一些坏处: 被隐藏的文本如果过长就无法被图片覆盖, 如果图片是透明的, 也会出现问题. 这时就要考虑用visibility: hidden;或者display: none的方法了, 缺点是易用性没有设置负值外边距强.


参考