Подтвердить что ты не робот

Какова логика выбора селекторов для сиблинга * + * и * ~ *?

Для этого вопроса я использую следующую разметку:

<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.

4b9b3361

Ответ 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. Это объясняет, почему все параграфы подчеркнуты и выделены курсивом.