CSS-селектор «(A или B) и C»?

176

Это должно быть просто, но у меня возникли проблемы с поиском поисковых запросов.
Допустим, у меня есть это:

<div class="a c">Foo</div>
<div class="b c">Bar</div>

В CSS, как я могу создать селектор, который соответствует чему-то, что соответствует "(.a или .b) и .c"?

Я знаю, что мог сделать это:

.a.c,.b.c {
  /* CSS stuff */
}

Но, если предположить, что мне придется много заниматься такой логикой с различными логическими комбинациями, есть ли лучший синтаксис?

мистифицировать
источник
Будьте осторожны, если вам нужно поддерживать Internet Explorer 6, потому что он просто игнорирует более одного имени класса в селекторе CSS.
fforw
24
К счастью, для этого проекта я могу сказать пользователям IE6, что нужно самим обновляться.
Джош
12
Для ясности я стараюсь всегда ставить новую строку после запятых или, по крайней мере, пробел.
Ноябрь
2
@ ANeves +1 для новой строки. На мой взгляд, это лучшее приложение, особенно при использовании системы контроля версий.
Курт

Ответы:

149

есть ли лучший синтаксис?

Нет. CSS ' oroperator ( ,) не разрешает группировки. По сути, это логический оператор самого низкого приоритета в селекторах, поэтому вы должны его использовать .a.c,.b.c.

Мэтт Болл
источник
25

Пока нет, но есть экспериментальная :matches()функция псевдокласса, которая делает именно это:

:matches(.a .b) .c {
  /* stuff goes here */
}

Вы можете найти больше информации об этом здесь и здесь . В настоящее время большинство браузеров поддерживают его первоначальную версию :any(), которая работает аналогичным образом, но будет заменена на :matches(). Нам просто нужно немного подождать, прежде чем использовать это везде (я, конечно, буду).

Metalcoder
источник
Неразумно обвинять IE в том, что он не реализовал то, о чем они просто никогда не думали и о котором изначально не говорилось. :-moz-any()и :-webkit-any()появился задолго до того, как Mozilla предложила его для Селекторов 4 (что привело к его нынешнему воплощению как :matches()).
BoltClock
1
В равной степени неразумно ожидать, что какой-либо поставщик реализует функцию из нестабильного черновика, независимо от того, как долго этот черновик был доступен (это связано с тем, что селекторы 4 остаются нестабильными и в основном не реализуются более трех лет после его FPWD) ,
BoltClock
@BoltClock, они целое десятилетие обвиняли IE6 в том, чего не было в 2001 году. Люди просто хотят кого-то обвинять.
GetFree
Одним словом об экспериментальных является то, что вы не хотите полагаться на них, если это официально не реализовано. Хотя это может показаться отличным решением - возможность его исчезновения, что лично мешает мне реализовать его в своих проектах. Даже отслеживание одного экспериментального псевдокласса не заставляет меня чувствовать себя в безопасности. Скорее всего, он будет использоваться более чем в одном месте в проекте, и в случае, если у вас есть более одного места, где вы его используете - вам каким-то образом нужно отслеживать все это. Вы, конечно, можете иметь запасные варианты и все же справиться с этим, но это не звучит чисто
Алексей Шевелев
я единственный, кто получает Uncaught DOMException: Failed to execute 'querySelector' on 'Document': ':any(.a .b)' is not a valid selector.ошибку? 🤔
томас
12

Если у вас есть это:

<div class="a x">Foo</div>
<div class="b x">Bar</div>
<div class="c x">Baz</div>

И вы хотите только выбрать элементы, которые имеют .xи ( .aили .b), вы можете написать:

.x:not(.c) { ... }

но это удобно только тогда, когда у вас есть три «подкласса» и вы хотите выбрать два из них.

Выбор только одного подкласса (например .a):.a.x

Выбор двух подклассов (например .aи .b):.x:not(.c)

Выбор всех трех подклассов: .x

Шиме Видас
источник
6
Любое логическое предложение формы a or b or c or dтакое же, как not(not(a) and not(b) and not(c) and not(d))«или», на самом деле это просто вспомогательная функция. Теоретически, во всех случаях можно обойтись без него . В случае ОП (.a or .b) and .c->:not(:not(.a):not(.b)).c
Макс Мерфи
2
@MaxMurphy Вы проверяли это?
Шиме Видас
4
По состоянию на пять часов утра, да! У меня есть JS, который выплевывает логику первого порядка, с селекторами на листьях, давая результаты, такие как :not(:not([data-status="ACT"]):not([data-status="ISS"]):not([data-status="COR"]))[data-month="08"]. Код недостаточно чистый для публичного ознакомления, в противном случае я бы его опубликовал. Я тестировал на Chrome, Safari и Android-телефоне низкого уровня.
Макс Мерфи
2
@MaxMurphy У вас есть замечательное замечание, но я думаю, что вы использовали довольно замученное определение «удобной функции». Все, что может сделать цифровой компьютер, может быть разложено на шлюзы NAND, но я бы не назвал остальную часть разработки программного обеспечения «набором удобных функций». Различия в степени быстро становятся фактическими, когда конструкции могут быть объединены.
Сара Г
1
@MaxMurphy Мне было трудно понять, что ты просто шутишь. :( Псевдокласс CSS отрицания,: not (X), является функциональной нотацией, принимающей простой селектор X в качестве аргумента. Он соответствует элементу, который не представлен аргументом. X не должен содержать другой селектор отрицания . (Из Mozilla docs , выделение мое)
törzsmókus
5

Нет. Стандартный CSS не обеспечивает то, что вы ищете.

Тем не менее, вы можете захотеть посмотреть на LESS и SASS .

Это два проекта, целью которых является расширение синтаксиса CSS по умолчанию путем введения дополнительных функций, включая переменные, вложенные правила и другие улучшения.

Они позволяют вам писать гораздо более структурированный код CSS, и любой из них почти наверняка решит ваш конкретный вариант использования.

Конечно, ни один из браузеров не поддерживает их расширенный синтаксис (тем более, что оба проекта имеют разный синтаксис и функции), но они предоставляют «компилятор», который преобразует ваш код LESS или SASS в стандартный CSS, который вы затем можете развернуть на своем сайте.

Spudley
источник
В этот момент я мог бы просто использовать печать PHP "Content-type: text / css"
Josh