Selektor CSS „(A lub B) i C”?

176

To powinno być proste, ale mam problem ze znalezieniem odpowiednich terminów.
Powiedzmy, że mam to:

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

W CSS, jak mogę utworzyć selektor, który pasuje do czegoś, co pasuje do „(.a lub .b) i .c”?

Wiem, że mógłbym to zrobić:

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

Ale zakładając, że będę musiał dużo wykonywać tego rodzaju logiki, z różnymi kombinacjami logicznymi, czy istnieje lepsza składnia?

Josh
źródło
Uważaj, jeśli musisz obsługiwać przeglądarkę Internet Explorer 6, ponieważ po prostu zignoruje on więcej niż jedną nazwę klasy w selektorze CSS.
fforw
24
Na szczęście w przypadku tego projektu mogę powiedzieć użytkownikom IE6, aby sami przeszli na aktualizację.
Josh
12
Ze względu na przejrzystość staram się zawsze umieszczać znak nowej linii po przecinkach lub przynajmniej spację.
ANeves,
2
@ANeves +1 dla nowej linii. Moim zdaniem jest to najlepsze rozwiązanie, szczególnie w przypadku korzystania z kontroli źródła.
Curt

Odpowiedzi:

149

czy jest lepsza składnia?

Nie. orOperator CSS ( ,) nie zezwala na grupowanie. Jest to zasadniczo operator logiczny o najniższym priorytecie w selektorach, więc musisz użyć .a.c,.b.c.

Matt Ball
źródło
25

Jeszcze nie, ale istnieje eksperymentalna :matches()funkcja pseudoklasy, która właśnie to robi:

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

Więcej informacji na ten temat można znaleźć tutaj i tutaj . Obecnie większość przeglądarek obsługuje jego początkową wersję :any(), która działa w ten sam sposób, ale zostanie zastąpiona przez :matches(). Musimy tylko trochę poczekać, zanim użyjemy tego wszędzie (na pewno będę).

Metalcoder
źródło
Nierozsądne jest obwinianie IE za to, że nie zaimplementował czegoś, o czym po prostu nigdy nie pomyśleli i nie było go w żadnym projekcie. :-moz-any()i :-webkit-any()pojawił się na długo przed tym, jak Mozilla zasugerował ją dla Selectors 4 (prowadząc do obecnego wcielenia jako :matches()).
BoltClock
1
Równie nierozsądne jest oczekiwanie, że jakikolwiek dostawca zaimplementuje funkcję z niestabilnej wersji roboczej, niezależnie od tego, jak długo wersja robocza została udostępniona (ma to na celu uwzględnienie faktu, że Selectors 4 pozostaje niestabilny i w dużej mierze nie został wdrożony przez ponad trzy lata po jego FPWD) .
BoltClock
@BoltClock, przez całą dekadę winili IE6 za rzeczy, które nie istniały w 2001 roku. Ludzie po prostu chcą kogoś winić.
GetFree
Jednym słowem o eksperymentalnych jest to, że nie chcesz na nich polegać, chyba że zostaną oficjalnie zaimplementowane. Choć mogłoby się to wydawać świetnym rozwiązaniem - możliwość zniknięcia, co osobiście uniemożliwia mi wdrażanie go w moich projektach. Nawet śledzenie jednej eksperymentalnej pseudoklasy nie daje mi poczucia bezpieczeństwa. Najprawdopodobniej będzie używany w więcej niż jednym miejscu w projekcie i na wypadek, gdybyś miał więcej niż jedno miejsce, w którym go używasz - musisz jakoś to wszystko śledzić. Z pewnością możesz mieć awarie i nadal to robić, ale to nie brzmi czysto
Alexey Shevelyov
czy tylko ja otrzymuję Uncaught DOMException: Failed to execute 'querySelector' on 'Document': ':any(.a .b)' is not a valid selector.błąd? 🤔
thomas
12

Jeśli masz to:

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

I chcesz tylko wybrać elementy, które mają .xi ( .alub .b), możesz napisać:

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

ale jest to wygodne tylko wtedy, gdy masz trzy „podklasy” i chcesz wybrać dwie z nich.

Wybór tylko jednej podklasy (na przykład .a):.a.x

Wybór dwóch podklas (na przykład .ai .b):.x:not(.c)

Wybór wszystkich trzech podklas: .x

Šime Vidas
źródło
6
Każda logiczna klauzula formularza a or b or c or djest taka sama, jak not(not(a) and not(b) and not(c) and not(d))tak „lub” jest w rzeczywistości tylko funkcją wygodną. Teoretycznie we wszystkich przypadkach powinno być możliwe obejście się bez niego . W przypadku OP (.a or .b) and .c->:not(:not(.a):not(.b)).c
Max Murphy,
2
@MaxMurphy Czy przetestowałeś to?
Šime Vidas
4
Od piątej rano, tak! Mam js, który wypluwa logikę pierwszego rzędu, z selektorami na liściach, dając wyniki takie jak :not(:not([data-status="ACT"]):not([data-status="ISS"]):not([data-status="COR"]))[data-month="08"]. Kod nie jest jeszcze wystarczająco czysty, aby można go było zobaczyć publicznie, w przeciwnym razie opublikowałbym go. Testowałem na Chrome, Safari i low-endowym telefonie z Androidem.
Max Murphy
2
@MaxMurphy Masz świetną rację, ale myślę, że przywołałeś dość męczącą definicję „funkcji wygody”. Wszystko, co może zrobić komputer cyfrowy, można rozłożyć na bramki NAND, ale reszty inżynierii oprogramowania nie nazwałbym „zestawem wygodnych funkcji”. Różnice stopni szybko stają się de facto różnicami w rodzaju, gdy konstrukty można łączyć.
Sarah G
1
@MaxMurphy Trudno mi było zrozumieć, że tylko żartujesz. :( Pseudoklasa negacji CSS,: not (X), jest notacją funkcjonalną przyjmującą prosty selektor X jako argument. Dopasowuje element, który nie jest reprezentowany przez argument. X nie może zawierać innego selektora negacji . (Z Mozilla docs ,
wyróżnienie
5

Nie. Standardowy CSS nie zapewnia tego, czego szukasz.

Możesz jednak zajrzeć do LESS i SASS .

Są to dwa projekty, których celem jest rozszerzenie domyślnej składni CSS poprzez wprowadzenie dodatkowych funkcji, w tym zmiennych, zagnieżdżonych reguł i innych ulepszeń.

Pozwalają napisać znacznie bardziej ustrukturyzowany kod CSS i prawie na pewno każdy z nich rozwiąże Twój konkretny przypadek użycia.

Oczywiście żadna z przeglądarek nie obsługuje swojej rozszerzonej składni (zwłaszcza, że ​​oba projekty mają inną składnię i funkcje), ale dostarczają "kompilator", który konwertuje twój kod LESS lub SASS na standardowy CSS, który możesz następnie wdrożyć w swojej witrynie.

Spudley
źródło
W tym momencie równie dobrze mógłbym po prostu użyć drukowania PHP „Content-type: text / css”
Josh