CSS 基于文档结构的选择器
1. 元素关系
基于文档结构的选择器主要依赖于几个基本的概念: 父子关系, 祖先后代的关系, 兄弟关系。
HTML 文档是一个结构化的, 所有定义在HTML文档中的元素构成一棵"树".
比如,我们有如下一个 HTML 文档:
<!DOCTYPE html><html lang="en-us"><head>  <meta charset="utf-8">  <meta name="viewport" content="width=device-width">  <title>Meerkat Central</title></head><body>  <h1>Meerkat <em>Central</em></h1>  <p>  Welcome to Meerkat <em>Central</em>, the <strong>best meerkat web site  on <a href="inet.html">the <em>entire</em> Internet</a></strong>!</p>  <ul>    <li>We offer:      <ul>        <li><strong>Detailed information</strong> on how to adopt a meerkat</li>        <li>Tips for living with a meerkat</li>        <li><em>Fun</em> things to do with a meerkat, including:          <ol>            <li>Playing fetch</li>            <li>Digging for food</li>            <li>Hide and seek</li>          </ol>        </li>      </ul>    </li>    <li>...and so much more!</li>  </ul>  <p>  Questions? <a href="mailto:suricate@meerkat.web">Contact us!</a>  </p></body></html>

1.1 父子关系
在 HTML 这颗树中,如果一个元素恰好位于另一个元素的上一级或下一级,则这些元素具有父子关系。
比如:
- 左起第一个 p 就是 em 和 strong 的父, 而 em 和 strong 便是 p 的子。 它们之间是父子关系。
 - 这里的 strong 又是 a 的父, a 是 strong 的子。 它们之间是父子关系。
 
1.2 祖先后代的关系
如果从一个元素到另一个元素的路径经过两层或多层级,则这些元素之间存在祖先后代关系,但不具有父子关系。
但是: 子元素也是后代,父元素也是祖先。
比如:
- 最右上侧的 ul 元素是两个 li 元素的父,同时他也是所有它的子元素 li 的子或者后裔的祖先。
 - html 元素是所有元素的祖先。
 
1.2 兄弟关系
同一个父元素的同级子元素之间是兄弟关系。
比如:
- 最下方的 ol 元素有 三个子元素 li, 这三个 li 元素之间就是兄弟关系。
 
2. 后代选择器
比如, 你想匹配所有嵌套在 h1 元素中的 em 元素, 你可以这样写:
h1 em {color: gray;}
这个规则只会将嵌套在 h1 元素中的 em 元素的文字编程灰色,对于其他的 em 元素,比如嵌套在 p 中的 em 都不会起作用。
<!DOCTYPE html><html><head>  <meta http-equiv="content-type" content="text/html; charset=utf-8" />  <title>Simple styling of a simple document</title>  <style type="text/css">    html { background-color: white; }    h1 em {color: gray;}  </style></head><body><h1>Hello <em>World!</em></h1><h2>My css <em>example</em></h2></body></html>
这里的语法规则是: 使用多个空格将一个或多个选择器组合起来。
比如:
ul ol ul em {color: gray;}
<!DOCTYPE html><html><head>  <meta http-equiv="content-type" content="text/html; charset=utf-8" />  <title>Simple styling of a simple document</title>  <style type="text/css">    html { background-color: white; }    ul ol ul em {color: gray;}  </style></head><body><ul>  <li>It's a list</li>  <li>A right smart list    <ol>      <li>Within, another list        <ul>          <li>This is <em>deep</em></li>          <li>So <em>very</em> deep</li>        </ul>      </li>      <li>A list of lists to see</li>    </ol>  </li>  <li>And all the lists for me!</li></ul></body></html>
3. 孩子选择器
有些时候,你不想匹配到任意的后代的节点,而是想精确一点, 仅仅只匹配某个元素的孩子节点。
比如, 你想选中是 h1 元素的孩子节点的 strong 元素,而不选中其他后代 strong 元素,可以这样写:
h1 > strong {color: red;}
这里的 > 符号叫做 "child combinator"。
<!DOCTYPE html><html><head>  <meta http-equiv="content-type" content="text/html; charset=utf-8" />  <title>Simple styling of a simple document</title>  <style type="text/css">    html { background-color: white; }    h1 > strong {color: red;}  </style></head><body><h1>This is <strong>very</strong> important.</h1><h1>This is <em>really <strong>very</strong></em> important.</h1></body></html>
4. 选择相邻兄弟元素
要选择紧跟同一父元素的另一个元素的元素,可以使用相邻兄弟组合器(adjacent-sibling combinator),表示为加号 (+)。
比如,
当你要删除紧跟 <h1> 元素的段落的上边距, 可以这样写:
h1 + p {margin-top: 0;}
这里看一个 li + li 的例子:
<!DOCTYPE html><html><head>  <meta http-equiv="content-type" content="text/html; charset=utf-8" />  <title>Simple styling of a simple document</title>  <style type="text/css">    html { background-color: white; }    li + li {font-weight: bold;}  </style></head><body><div>  <ol>    <li>List item 1</li>    <li>List item 1</li>    <li>List item 1</li>  </ol>  This is some text that is part of the 'div'.  <ul>    <li>A list item</li>    <li>Another list item</li>    <li>Yet another list item</li>  </ul> </div></body></html>
5. 选择后续兄弟元素
通用兄弟组合器(general sibling combinator)允许你选择任何位于另一个元素之后的元素,当两个元素共享同一个父元素时,使用波浪号 (~) 组合器表示。
<!DOCTYPE html><html><head>  <meta http-equiv="content-type" content="text/html; charset=utf-8" />  <title>Simple styling of a simple document</title>  <style type="text/css">    html { background-color: white; }    h2 ~ ol {font-style: italic;}  </style></head><body><div><h2>Subheadings</h2><p>It is the case that not every heading can be a main heading.  Some headings must besubheadings.  Examples include:</p><ol>  <li>Headings that are less important</li>  <li>Headings that are subsidiary to more important headlines</li>  <li>Headings that like to be dominated</li></ol><p>Let’s restate that for the record:<ol>  <li>Headings that are less important</li>  <li>Headings that are subsidiary to more important headlines</li>  <li>Headings that like to be dominated</li></ol></div></body></html>
这里的两个 ol 都处于 h2之后,并和 h2 有相同的父元素, 因此该条规则匹配这两个 ol.