Почему комбинатор общего брата позволяет переключать содержимое псевдоэлемента, но не смежного брата?
В этом вопросе " Селектор CSS3, который работает как jcuery's.click ()? ", Я опубликовал ответ, используя :checked
состояние input
из type="checkbox"
переключить отображение элемента.
Это HTML-код демонстрации, которую я разместил в этом ответе:
<input type="checkbox" id="switch" />
<nav>
<h2>This would be the 'navigation' element.</h2>
</nav>
<label for="switch">Toggle navigation</label>
И CSS (с переходами для краткости):
#switch {
display: none;
}
#switch + nav {
height: 0;
overflow: hidden;
/* transitions followed */
}
#switch:checked + nav {
height: 4em;
color: #000;
background-color: #ffa;
/* transitions followed */
}
label {
cursor: pointer;
}
Как только я опубликовал ответ, мне пришло в голову, что мы также можем переключать текст label
используется для запуска изменения состояния этого флажка, используя следующие селекторы (изменив label
текст к 'навигации'):
label {
display: inline-block;
cursor: pointer;
}
#switch + nav + label::before {
content: 'Show ';
}
#switch:checked + nav + label::before {
content: 'Hide ';
}
Упрощенная / базовая демонстрация JS Fiddle.
Это не сработало, в то время как селектор соответствовал, в то время как input
был в своем непроверенном состоянии (а label
показал Show navigation
), селектор не соответствует, когда состояние input
изменилось. Обратите внимание, что переходы по-прежнему были nav
элемент, а исходный селектор сопоставления указывает, что комбинатор соседнего брата совпал изначально. Приведенная выше ссылка показывает упрощенную демонстрацию нерабочих (в Chrome 27/Windows XP) селекторов.
Затем мне пришло в голову попробовать комбинатор общего брата, чтобы уменьшить селекторную цепь. что привело к следующему CSS (с переходами, снова сокращенными для краткости):
#switch:checked + nav {
background-color: #ffa;
}
label {
display: inline-block;
cursor: pointer;
}
#switch ~ label::before {
content: 'Show ';
}
#switch:checked ~ label::before {
content: 'Hide ';
}
К моему удивлению, это сработало (content
из label
изменилось в ответ на измененное состояние input
).
Итак, вопрос: почему комбинатор общего родственного брата допускает обновление позднего родственного брата, в то время как комбинаторы цепных соседей (которые соответствуют элементам и структуре DOM) не позволяют?
Кроме того, похоже, что это работает в Firefox (21, в Windows XP); поэтому я думаю, что вопрос немного изменен, чтобы включить: это ошибка в Chrome/Webkit или ожидаемое поведение?
И, более того, кажется, что, хотя это ошибка в Chrome (спасибо @Boltclock), есть несколько нелепая анимация "ничего не делать", которая исправляет неработающую демонстрацию (хотя существуют и другие, возможно, лучшие, альтернативы, как у Скотта). ответ показывает)
body {
-webkit-animation: bugfix infinite 1s;
}
@-webkit-keyframes bugfix {
from {
padding: 0;
}
to {
padding: 0;
}
}
#switch {
}
#switch + nav {
-moz-transition: all 1s linear;
-ms-transition: all 1s linear;
-o-transition: all 1s linear;
-webkit-transition: all 1s linear;
transition: all 1s linear;
}
#switch:checked + nav {
background-color: #ffa;
-moz-transition: all 1s linear;
-ms-transition: all 1s linear;
-o-transition: all 1s linear;
-webkit-transition: all 1s linear;
transition: all 1s linear;
}
label {
display: inline-block;
cursor: pointer;
}
#switch + nav + label::before {
content:'Show ';
}
#switch:checked + nav + label::before {
content:'Hide ';
}
Примечание: причина, по которой я обновляю вопрос с помощью этого "исправления" вместо того, чтобы публиковать его как ответ, заключается просто в том, что вопрос был не "как я могу это исправить?" но (в основном) "почему это не работает?"
2 ответа
Это давняя ошибка в браузерах WebKit, связанная с использованием определенных динамических псевдоклассов с комбинаторами следующего уровня. Это происходит независимо от того, применяете ли вы стили к самому элементу брата или к псевдоэлементу этого элемента брата.
Я не знаю, подавал ли кто-нибудь еще отчет об ошибке, но это довольно часто встречается на сайте:
- Ошибка Webkit с `:hover` и множеством селекторов смежных братьев и сестер
- CSS-смежные селекторы, элементы Safari и ;
Как ни странно, также сообщалось, что в Chrome были проблемы с общим комбинатором, но, как вы заметили, он работает в данном сценарии:
Так что или это было исправлено, или что-то еще запускает / запускает это.
Bug Work Around
По-видимому, некоторые действительные псевдоклассы, объединенные в цепочку, позволяют ему работать.
Эти работы (см. Скрипка № 1, Скрипка № 2, Скрипка № 3):
#switch:checked + nav:only-of-type + label::before
#switch:checked + nav:nth-of-type(1) + label::before
#switch:checked + nav:nth-child(2) + label::before
Это не так (см. Fiddle # 4):
#switch:checked + nav:not([class]) + label::before
Я попробовал другой :not()
комбинации, ни одна из которых не позволила ему работать.
** Лучший выбор **
#switch:checked + nav:nth-child(n) + label::before