Какова логика выбора селекторов для сиблинга * + * и * ~ *?
Для этого вопроса я использую следующую разметку:
<body>
<p>1</p> <!-- Paragraph 1 -->
<p>2</p> <!-- Paragraph 2 -->
<p>3</p> <!-- Paragraph 3 -->
</body>
В Спецификации выбора 3-го уровня применяются следующие правила выбора:
* any element
E + F an F element immediately preceded by an E element
E ~ F an F element preceded by an E element
На основании этого должно произойти следующее:
body + * { } /* Selects nothing as no elements precede body */
body ~ * { } /* As above. */
p + * { } /* Selects Paragraph 2 and Paragraph 3 as these are preceded by p */
p ~ * { } /* As above. */
* + * { } /* As above. */
* ~ * { } /* As above. */
False
* + *
и * ~ *
каким-то образом могут выбрать пункт 1 вместе с 2 и 3! Параграфу 1 ничего не предшествует, поэтому доступ к нему невозможен:
body + * { background: #000; }
body ~ * { background: #000; }
p ~ * { color: #f00; }
p + * { font-weight: bold; }
* + * { text-decoration: underline; }
* ~ * { font-style: italic; }
Результат:
![Result example; paragraph 2 and 3 are red and all paragraphs are italic and underlined]()
Как вы можете видеть, параграф 1 не предшествует body
или phantom p
, но ему, очевидно, предшествует что-то. Он не должен иметь никакого специального стиля, применяемого к нему вообще, но каким-то образом затрагиваются эти последние два селектора. Какова логика этого?
Пример JSFiddle.
Ответы
Ответ 1
* + *
Стили любого элемента, который является непосредственным родственником любого элемента, начиная с корня документа. Поскольку <head>
на самом деле является непосредственным предшественником брата (несмотря на то, что он не отображается в вашем коде), этот селектор нацеливается на тело и два последних абзаца, поскольку первый абзац не сразу следует за другим элементом брата. Все три абзаца были подчеркнуты из-за характера text-decoration
на потомках блочного уровня в нормальном потоке.
* ~ *
Это в основном то же самое, что и выше, за исключением использования общего сиблингового комбинатора.. он стилирует нисходящий элемент которые появляются после <head>
независимо от того, являются ли они непосредственными братьями или сестрами или нет. Поскольку <body>
является единственным родственным братом, это имеет тот же эффект, что и вышеприведенный селектор. Первый абзац выделен курсивом из-за наследования.
p ~ *
выбирает элемент sibling, следующий за <p>
, который в вашем примере является двумя последними абзацами. p + *
стилирует любой элемент, который является непосредственным родственником абзаца, который также был бы двумя последними элементами <p>
.
Ответ 2
Они фактически не применяются к первому абзацу. Чтобы продемонстрировать это, немного измените таблицу стилей:
* + * { border-right: solid red }
* ~ * { border-left: solid black; }
![demo]()
fiddle
Они оба применяются к элементу "тело", которому на самом деле предшествует "голова".
Ответ 3
Это ошибка в вашем тестовом примере. Как и следовало ожидать, ни один из селекторов не соответствует первому абзацу, но стиль от каскадов body
до абзацев!
Оба * + *
и * ~ *
соответствуют body
, поскольку ему предшествует тег head
. Таким образом, он получает text-decoration:underline
и font-style:italic
. Это объясняет, почему все параграфы подчеркнуты и выделены курсивом.