Удар откуда не ждали: псевдокласс :has() ломает сайты на jQuery
Псевдокласс :has()
, он же «родительский селектор» и «селектор предыдущего соседа» — пожалуй, одно из самых революционных новшеств CSS 2022 года (наряду с выражениями от контейнера). Его штатно поддерживают уже два стабильных браузера — Safari 15.4+ и Chrome 105+. Но кроме всеобщей радости, его внедрение принесло и неожиданные проблемы: пользователи стали жаловаться, что с новым обновлением перестали работать некоторые сайты на jQuery.
В jQuery давно есть как своя реализация :has()
, так и множество нестандартных (пока) селекторов, вроде :contains()
. Работают они так: сначала jQuery пытается подставить селектор в нативный querySelectorAll()
, и если тот не может его распарсить и выдает ошибку, переключается на собственный алгоритм разбора. Но так как у :has()
«прощающий» синтаксис, т.е. невалидные селекторы внутри него не делают весь селектор невалидным, селектор наподобие :has(:contains('упс'))
или вложенного :has()
не вызовет ошибки, и скрипт не переключится на другой алгоритм, а просто вернет пустой набор элементов.
Правка самого jQuery проблему не решит, так как многие сайты работают на старых его версиях и вряд ли обновятся. В обсуждении ишью Таб Аткинс указал три возможных решения — переименовать нативный :has()
, отказаться от «прощающего» синтаксиса селекторов, либо ничего не делать и смириться с багами в сайтах. Ни одно из них нельзя назвать хорошим, поэтому, пока CSSWG собирает статистику, насколько проблема серьезна, обсуждение продолжается. Если у вас есть идеи, как решить проблему с наименьшими издержками — подключайтесь к нему!
Добавлено 21.12.2022. В рабочей группе по CSS нашли четвертое решение: отказаться от «прощающего» синтаксиса для :has()
, но сохранить его для :is()
и :where()
(и только для них). Спецификация уже обновлена, дело за браузерами.
P.S. Это тоже может быть интересно: