
С появлением множества нововведений в технологиях вёрстки веб страниц, у разработчиков появилась возможность отчасти заменить JavaScript, применяя HTML/CSS для большей производительности и расширяемости интерфейса своих порталов.
Помимо проблем с кроссбраузерностью и разной реализаций новых свойств CSS, часто приходится встречаться с другими проблемами в местах, где казалось бы, давно всё устаканилось и везде работает одинаково. Именно с такой проблемой мне пришлось столкнутся, применяя CSS transitions вместе с псевдоклассом :active. Видимо из-за того, что в документации отсутствует описание поведения родителей элемента в состоянии :active, в разных браузерных движках это поведение реализовано по-разному.
Задача
Кроссбраузерно декорировать потомка активного элемента (родителя), с возможностью активировать родителя кликом на любого потомка (мой пример на jsfiddle, и на dabblet).
Прототип
Учитывая потенциальные сложности и несостыковки поведения в разных браузерах, делаем рабочий прототип, для кроссбраузерной проверки.
span {
display: block;
position: relative;
width: 60px;
height: 60px;
background: red;
}
b {
position: absolute;
left: 10px;
top: 10px;
width: 40px;
height: 40px;
background: blue;
}
i {
position: absolute;
left: 10px;
top: 10px;
width: 20px;
height: 20px;
background: green;
}
<span><b><i></i></b></span>
В сферическом вакууме
В спецификации указано, что активным элементом (прим. div:active), является тот, на который производится клик, но ничего не сказано как наследуется активное состояние. Делаем эксперимент, и смотрим, как же в реальном мире, ведут себя активные элементы, ссылка на страницу с экспериментом на Jsfiddle (на dabblet).
Первые проблемы
В первом случае, в webkit, FF 3.6+ и opera мы видим, что активное состояние наследуется всеми родителями, вплоть до <html>, но когда требуется отследить более 1ого активного элемента, опера уже не справляется, и активное состояние наследует только первый родитель в DOM, декорированный псевдоклассом :active (span:active)
html:active { background: #ededed; } /* Light gray */
.test1-2 span:active { background: yellow; }
<div class="test1-2"><span><b><i></i></b></span></div>

В Interner Explorer активное состояние вообще не наследуется, и работает только при клике на элемент декорированный :active псевдокласом (в эксперименте это <span>), а в версиях до 7ого, включительно, :active работает только на ссылки.

Это еще не всё
Во втором случае я использовал каскад от активного элемента (span:active b), как видим в примере, webkit и ff, всё работает как и предполагалось, кликая на любой элемент вниз по DOM от декорированного псевдоклассом стиля, подсвечивается нужный элемент, определённый через каскад. Опера в этом случае начинает вести себя как IE, переставая наследовать активное состояние и работая только с элементом, на которые непосредственно происходит клик.
html:active { background: #ededed; } /* Light gray */
.test2 span:active b { background: yellow; }
<div class="test2"><span><b><i></i></b></span></div>


Оружие к бою
В третьем примере удалось заставить оперу наследовать активное состояние от потомка для использования в каскаде, используя абсолютно позиционированный элемент (<em class=«pseudo»>), опирающийся от элемента декорированного псевдоклассом :active. FF и webkit тут по прежнему работают предсказуемо, но IE8+ до сих пор не при делах.
html:active { background: #ededed; } /* Light gray */
.test3 span:active b { background: yellow; }
em.pseudo {
content:"";
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}
<div class="test3"><span><b><i></i></b><em class="pseudo"></em></span></div>
Что бы заставить работать IE как нам требуется, и улучшить немного код, заменяем абсолютный элемент псевдоэлементом. Как выяснилось, в IE активное состояние всё таки наследуется, но только на псевдоэлементы ::before, ::after. К сожалению, в IE8 псевдоэлементы игнорируют z-index, что может не подойти в большинстве случаев (как и в моём), но в IE9+ всё в порядке.
html:active { background: #ededed; } /* Light gray */
.test4 span:active b { background: yellow; }
.test4 span:after {
content:"";
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}
<div class="test4"><span><b><i></i></b></span></div>

Миссия закончена, возвращаемся домой
В итоге, мы заставили все элементы одинакого наследовать активное состояние кроссбраузерно (IE9+, FF 3.6+, Opera 9.64+, Chrome, Safari и другие вебкиты) и теперь спокойно можем реализовать функционал на портале.
Так как функционал несёт чисто декоративную роль, мы решил отказаться от IE6-8, оставив им мягкий fallback, а остальное сделать на CSS.
Постскриптум.
Без каскада
Можно проще решить проблему в IE8 и Опере, отказавшись от каскада, что в моём случае не подходило, и снижало расширяемость функционала, поэтому решил отказаться от реализуемой красивости в IE8.
Пояснение к задаче
Единственный нормальный способ отслеживать клик на CSS, в моём примере, без использования Java Script, оказался псевдокласс :active. Можно было использовать :focus, подставляя элементы формы под существующие блоки, но такое решение много тяжелее по нагрузке, и в итоге всё равно требовало Java Script напильника.
Тачпад
При клике с тачпэда элемент заметно меньше времени находится в активном состоянии, в отличии от клика с мыши.