2015-02-03 36 views
7

W spec członkowskie, dotyczące obliczania CSS swoistość: (wytłuszczenie moje)Czy selektory typu można powtarzać w celu zwiększenia specyficzności?

UWAGA: powtórzeń tego samego prostego selektora są dozwolone i zrobić zwiększenie swoistości.

Tak na przykład .class.class {} ma dwukrotnie większą specyficzność niż .class {} - DEMO

jednak, w odniesieniu do terminu 'prosty selektor' the spec ma do powiedzenia: (pogrubienie kopalni)

selektor prosty to wybierak typu typu lub uniwersalny selektor , po którym następuje natychmiast zero lub więcej selektorów atrybutu , ID selektory lub pseudoklasy, w dowolnej kolejności.

Więc skoro spec mówi, że powtórzeń tego samego prostego selektora są dozwolone - to oznaczałoby, że można powtórzyć type selectors również.

Cóż najwyraźniej coś jak to nie zadziała: h1h1 { },

więc próbowałem to: h1[]h1[] {} - co nie działa albo,

więc zastanawiam się, czy istnieje sposób, aby Zrób to?

+0

mam wrażenie, jest to faktycznie wina w drodze spec został napisany w górę .. – SW4

+0

musiałbym się zgodzić, nie sądzę, jakie kiedykolwiek widziałem czegoś takiego. Być może będę musiał się z tym pogodzić i przetestować, ale nie wydaje się prawdopodobne, aby to było poprawne. – Ruddy

Odpowiedz

11

Możliwe jest zwiększenie specyficzności selektora za pomocą selektorów typu, ale niekonwencjonalnie. Powód tego jest wyjaśniony poniżej, ale dla tych, którzy szukają alternatywy, są dwa z nich. Można łańcuch :not() Pseudoklasy zawierające typu selektorów w jednym selektorem związku:

h1      {} /* 1 type -> specificity = 0-0-1 */ 
h1:not(_)    {} /* 2 types -> specificity = 0-0-2 */ 
h1:not(_):not(_)  {} /* 3 types -> specificity = 0-0-3 */ 
h1:not(_):not(_):not(_) {} /* 4 types -> specificity = 0-0-4 */ 

lub, jeśli trzeba wspierać starszych przeglądarek, które nie obsługują :not(), można dodać nadmiarowe selektorów typu, takie jak html i body do początku złożonego selektora, chociaż są znacznie bardziej ograniczone w tym przypadku może nie być w stanie wyjaśnić wszystkich elementów:

h1    {} /* 1 type -> specificity = 0-0-1 */ 
body h1   {} /* 2 types -> specificity = 0-0-2 */ 
html body h1  {} /* 3 types -> specificity = 0-0-3 */ 
html body tr > td {} /* 4 types -> specificity = 0-0-4, assumes every td is a child of tr */ 

rzecz jasna, są one uważane za hacki specyfikę; tak jak w przypadku wszystkich innych hacków CSS, używaj ich oszczędnie, jeśli w ogóle.


Selektor związek może mieć co najwyżej tylko dokładnie jeden selektor typu poprzedzającym wszystkie inne proste selektorów. Z Selectors 3 (który nazywa to sekwencja prostych selektorów)

sekwencja prostych selektorów jest łańcuchem prostym selektory, które nie są oddzielone combinator. Zawsze zaczyna się od selektora typu lub uniwersalnego selektora. Żaden inny selektor typu lub selektor uniwersalny nie jest dozwolony w sekwencji.

I Selectors 4:

Selektor związek jest sekwencją prostych selektory, które nie są oddzielone combinator. Jeśli zawiera selektor typu lub uniwersalny selektor, selektor ten pojawia się jako pierwszy w sekwencji. W sekwencji dozwolony jest tylko jeden selektor typu lub selektor uniwersalny.

Tylko selektory typu i uniwersalne podlegają tej zasadzie; możesz łączyć i powtarzać inne proste selektory, aby zwiększyć swoistość. Być może specyfikacja mogła przypomnieć czytelnikowi o tym w sekcji dotyczącej obliczania specyfiki, ale nie sądzę, że jest to absolutnie konieczne.

Powodem tej reguły nie jest powiedziane wprost, ale jest to dość łatwo wywnioskować:

  • Pamiętaj, że selektor typu polega po prostu identyfikator, na przykład h1. W przeciwieństwie do innych prostych selektorów, które mają swoje własne symbole odróżniające w gramatyce, takie jak ID (#), klasa (.), pseudoklasa (:) lub selektor atrybutu ([]). Nie można mieć wielu kolejnych selektorów typów bez możliwości oddzielnego analizowania ich.

  • I nawet jeśli mógłby typu selektorów łańcuchowe, na przykład jeśli miał innego prostego wyboru między nimi, jedyne możliwe zastosowanie dla tego byłoby jak hack specyficzności, jak opisano w pytaniu, co oznacza, że ​​będzie mogą go używać tylko wtedy, gdy wszystkie selektory typu są takie same; żadna inna kombinacja selektorów typu nie może działać.

    Dzieje się tak, ponieważ selektorzy zakładają, że język dokumentu definiuje każdy element, aby mieć dokładnie jeden typ elementu. Na przykład w HTML, h1 jest zawsze h1; nigdy nie może być innego rodzaju elementu. Selektor złożonych zapytań o element, który jest zarówno h1, jak i p, nigdy nie może się równać z tym samym powodem, dla którego coś takiego jak [type=text][type=password] nigdy nie będzie pasować do niczego w języku dokumentu, który nie obsługuje zduplikowanych atrybutów.

Jednak z powyższych punktów na uwadze, że nadal możliwe jest utworzenie selektora związku, który zawiera selektor więcej niż jeden typ do specyfiki - za pomocą :not() pseudo-klasa:

  • Specyfika pseudo-klasy :not() jest równa jej argumentowi. Sama pseudoklasa nie jest liczona. Jest to wspomniane w pierwszym linku. Oznacza to, że specyfika :not(h1) jest odpowiednikiem h1 - jednego selektora typów.

  • Ponieważ element może być dokładnie tego samego typu, oznacza to, że :not() z dowolnym innym selektorem typów będzie gwarantowanym dopasowaniem.

  • Ponieważ selektor złożony może zawierać dowolną liczbę pseudoklas, można powtórzyć negację tyle razy, ile to konieczne, nawet jeśli wszystkie negacje używają tego samego selektora typów.

  • A ponieważ selektory nie dbają o to, czy selektor ma sens w kontekście określonego języka dokumentu, można użyć selektora typów, który gwarantuje, że nigdy nie będzie pasował do żadnego elementu zgodnego dokumentu HTML, o ile spełnia gramatyka selektorów dla selektora typów. Selektor typów składa się tylko z identyfikatora CSS, więc dowolny identyfikator CSS to uczciwa gra. W tym _.

+0

Dzięki za tę bardzo szczegółową odpowiedź! Ciekawe jednak: dlaczego uważasz, że selektor 'body h1 {}' hack? Pomyślałem także o innym możliwym sposobie dodania specyfiki: coś w rodzaju 'h1: nth-child (n) {}' - ale to wygląda na znacznie bardziej odrażające – Danield

+1

@Danield: Ponieważ nie ma * prawdziwego * powodu, powinieneś mieć 'ciało 'selektor tam, ponieważ możesz ogólnie założyć, że' h1' będzie zawsze w 'ciele'. Czuję się trochę brudny za każdym razem, gdy dodaję selektory wyłącznie w celu dodania specyfiki :) – BoltClock