Главная » Css live » Удар откуда не ждали: псевдокласс :has() ломает сайты на jQuery

Удар откуда не ждали: псевдокласс :has() ломает сайты на jQuery

:has() в виде астероида несет угрозу jQuery в виде динозавров

Псевдокласс :has(), он же «родительский селектор» и «селектор предыдущего соседа» — пожалуй, одно из самых революционных новшеств CSS 2022 года (наряду с выражениями от контейнера). Его штатно поддерживают уже два стабильных браузера — Safari 15.4+ и Chrome 105+. Но кроме всеобщей радости, его внедрение принесло и неожиданные проблемы: пользователи стали жаловаться, что с новым обновлением перестали работать некоторые сайты на jQuery.

В jQuery давно есть как своя реализация :has(), так и множество нестандартных (пока) селекторов, вроде :contains(). Работают они так: сначала jQuery пытается подставить селектор в нативный querySelectorAll(), и если тот не может его распарсить и выдает ошибку, переключается на собственный алгоритм разбора. Но так как у :has() «прощающий» синтаксис, т.е. невалидные селекторы внутри него не делают весь селектор невалидным, селектор наподобие :has(:contains('упс')) или вложенного :has() не вызовет ошибки, и скрипт не переключится на другой алгоритм, а просто вернет пустой набор элементов.

Правка самого jQuery проблему не решит, так как многие сайты работают на старых его версиях и вряд ли обновятся. В обсуждении ишью Таб Аткинс указал три возможных решения — переименовать нативный :has(), отказаться от «прощающего» синтаксиса селекторов, либо ничего не делать и смириться с багами в сайтах. Ни одно из них нельзя назвать хорошим, поэтому, пока CSSWG собирает статистику, насколько проблема серьезна, обсуждение продолжается. Если у вас есть идеи, как решить проблему с наименьшими издержками — подключайтесь к нему!

P.S. Это тоже может быть интересно: