Почему комбайнер general-sibling позволяет переключать псевдоэлементный контент, но не соседний брат?
В этом вопросе "Селектор CSS3, который работает как .click()?" I отправил ответ используя :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;
}
JS Fiddle demo.
Как только я отправил ответ, мне пришло в голову, что мы могли бы также переключить текст 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 ';
}
JS Fiddle demo.
Скорее всего, это сработало (изменилось content
label
в ответ на измененное состояние input
).
Итак, вопрос: почему комбайнер general-sibling допускает обновление более позднего брата, в то время как цепные комбонатчики следующего поколения (которые соответствуют элементам и структуре DOM) не?
Кроме того, похоже, что это работает в Firefox (21, на Windows XP); поэтому я предполагаю, что вопрос слегка изменен, чтобы включить: это ошибка в Chrome/Webkit или ожидаемое поведение?
И еще больше кажется, что, хотя это ошибка в Chrome (спасибо @Boltclock), есть несколько смехотворная 'do-nothing' анимация, который фиксирует нерабочую демонстрацию (хотя существуют другие, возможно, лучшие альтернативы, как показывает ответ Скотта):
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 ';
}
JS Fiddle demo.
Примечание. причина, по которой я обновляю этот вопрос с помощью этого исправления, а не размещать его как ответ, просто потому, что вопрос был не "как я могу это исправить?" но (в основном) "почему он не работает?"
Ответы
Ответ 1
Это давняя ошибка в браузерах WebKit, связанная с использованием некоторых динамических псевдоклассов с комбинаторами следующего поколения. Это происходит независимо от того, применяете ли вы стили к самому элементу-брату или псевдоэлементу этого элемента-брата.
Я не знаю, зарегистрировал ли кто-нибудь отчет об ошибке, но это было довольно часто встречается на сайте:
Странно также сообщалось, что у Chrome возникли проблемы с общим комбинированным сборщиком, но, как вы заметили, он работает в вашем сценарии:
Итак, либо это было исправлено, либо что-то еще запускает/запускает его.
Ответ 2
Работа с ошибками
По-видимому, некоторые действительные псевдоклассы, соединенные вместе, позволяют ему работать.
Эти работы (см. Fiddle # 1, Fiddle # 2, Fiddle # 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