Czy mogę używać nieistniejących klas CSS?

260

Mam tabelę, w której pokazuję / ukryję pełną kolumnę według jQuery za pośrednictwem klasy CSS, która nie istnieje:

<table>
   <thead>
      <tr>
         <th></th>
         <th class="target"></th>
         <th></th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td></td>
         <td class="target"></td>
         <td></td>
      </tr>
      <tr>
         <td></td>
         <td class="target"></td>
         <td></td>
      </tr>
   </tbody>
</table>

Za pomocą tego DOMa mogę to zrobić w jednym wierszu za pomocą jQuery: $('.target').css('display','none');

Działa to doskonale, ale czy można używać klas CSS, które nie są zdefiniowane? Czy powinienem utworzyć dla niego pustą klasę?

<style>.target{}</style>

Czy są jakieś skutki uboczne lub czy istnieje lepszy sposób, aby to zrobić?

totymedli
źródło
9
Nie widzę w tym nic złego, chociaż uczyniłbym to częścią arkusza stylów, jeśli w ogóle byłoby możliwe, zamiast używać .css, stylów ustawionych w .css bardzo trudno jest zastąpić bez powodowania innych problemów, więc staram się ich unikać.
Kevin B
8
uwaga dodatkowa, której możesz użyć .toggle(), jest nieco krótsza w kodzie.
Agregat matematyczny
4
W Visual Studio + ReSharper, jeśli użyjesz klasy, która nie jest zdefiniowana, wyświetli ostrzeżenie, które jest pomocne, jeśli mam tylko literówkę, ale jest denerwujące w takich sytuacjach. W takim przypadku masz do wyboru dodanie pustego stylu lub wyłączenie ostrzeżenia (lub po prostu zignorowanie go) - osobiście po prostu dodaję pusty styl. Nie wiem, czy inne IDE zachowują się podobnie.
Joe Enos,
8
Jest to nie tylko możliwe, ale przez niektórych wyraźnie zalecane. Ponieważ twój targetjest do celów javascript, wiele osób używa prefiksu js-dla takich klas, tj js-target. BTW: Target to rodzaj złej nazwy;) Więcej informacji można znaleźć na stronie: philipwalton.com/articles/decoupling-html-css-and-javascript
k0pernikus 10.09.13
1
stackoverflow.com/questions/2832117/... jest mniej więcej duplikatem tego, bez nieporozumień.
naught101 11.09.13

Odpowiedzi:

491

„Klasa CSS” jest mylącą nazwą; classto atrybut (lub właściwość pod względem skryptów) przypisywany do elementów HTML. Innymi słowy, można zadeklarować klas w HTML, CSS nie, więc w przypadku klasy „target” robi w rzeczywistości istnieje na tych konkretnych elementów i znaczniki są całkowicie poprawny, jak to jest.

Nie musi to koniecznie oznaczać, że musisz mieć zadeklarowaną klasę w kodzie HTML, zanim będziesz mógł użyć jej w CSS. Zobacz komentarz ruakh. To, czy selektor jest prawidłowy, zależy całkowicie od jego składni , a CSS ma swój własny zestaw reguł obsługi błędów parsowania , z których żaden nie dotyczy w ogóle znaczników. Zasadniczo oznacza to, że HTML i CSS są całkowicie niezależne od siebie pod względem ważności. 1

Kiedy to zrozumiesz, staje się jasne, że nie ma efektu ubocznego braku zdefiniowania .targetreguły w arkuszu stylów. 2 Kiedy przypisujesz klasy do swoich elementów, możesz odwoływać się do tych elementów przez te klasy albo w arkuszu stylów, albo w skrypcie, albo w obu. Żadna z nich nie jest zależna od drugiej. Zamiast tego oba odnoszą się do znaczników (a ściślej do jego reprezentacji DOM). Zasada ta obowiązuje nawet wtedy, gdy używasz JavaScript do stosowania stylów, tak jak robisz to w swojej jednowierszowej wersji jQuery.

Kiedy piszesz regułę CSS za pomocą selektora klasy, mówisz tylko: „Chcę zastosować style do elementów należących do tej klasy”. Podobnie, kiedy piszesz skrypt do pobierania elementów o określonej nazwie klasy, mówisz: „Chcę robić rzeczy z elementami należącymi do tej klasy”. Czy tam elementy, które należą do danej klasy jest zupełnie odrębna kwestia.


1 Z tego powodu selektor identyfikatora CSS dopasowuje wszystkie elementy o podanym identyfikatorze, niezależnie od tego, czy identyfikator pojawia się dokładnie raz, czy wielokrotnie (w wyniku czego dokument HTML jest niezgodny).

2 Jedyną sytuacją, w której zdaję sobie sprawę z tego, gdzie taka pusta reguła CSS jest konieczna, jest sytuacja, gdy niektóre przeglądarki odmawiają prawidłowego zastosowania niektórych innych reguł w wyniku błędu; utworzenie pustej reguły spowoduje zastosowanie innych reguł z jakiegoś powodu. Zobacz tę odpowiedź, aby zobaczyć przykład takiego błędu. Jest to jednak po stronie CSS i dlatego nie powinno mieć nic wspólnego ze znacznikami.

BoltClock
źródło
5
Wieki zajęło mi uświadomienie sobie, że klasy nie mają nic wspólnego z CSS. Ale mniej więcej w tym samym czasie wszyscy się zorientowali i pojawiły się mikroformaty.
Konrad Rudolph,
13
+1, choć odpowiedź ta może być błędnie sugerowana, że ​​CSS może odnosić się tylko do klas, które faktycznie występują w HTML. W rzeczywistości w witrynie dość często stosuje się CSS na całej stronie, nawet jeśli niektóre klasy, do których się odnosi, nie pojawiają się na każdej stronie. (Na przykład witryna może mieć niestandardową stylizację zewnętrznych linków a.extlinklub nie, nawet jeśli niektóre strony nie zawierają żadnych zewnętrznych linków).
ruakh 10.10.2013
1
@ruakh: Doskonały punkt, dzięki. Nie mogłem znaleźć sposobu, aby dopasować ją do mojej oryginalnej, krótkiej odpowiedzi, nie zmieniając tematu, ale widzę, jak użycie terminu zależność mogło wywrzeć na tym wrażenie, więc trochę go zmieniłem. To powiedziawszy dodałem przypis odnoszący się do twojego komentarza, a także dopracowujący go dalej.
BoltClock
66

Nie ma żadnych złych efektów, aby używać klas, które nie mają stylów. Rzeczywiście, jest to część użyteczności CSS polegającej na tym, że jest on odłączony od znaczników i może stylizować elementy / klasy / itp. w razie potrzeby.

Nie myśl o nich jako o „klasach CSS”. Pomyśl o nich jak o „klasach”, których CSS używa także w razie potrzeby.

David
źródło
11
+1 za „Nie myśl o nich jako o„ klasach CSS ”. Pomyśl o nich jako o „klasach”, których CSS używa także w razie potrzeby ”
laike9m
48

Zgodnie ze specyfikacją HTML5 :

Atrybut klasy musi mieć wartość będącą zbiorem tokenów oddzielonych spacjami reprezentujących różne klasy, do których należy element. ... Nie ma żadnych dodatkowych ograniczeń dotyczących tokenów, których autorzy mogą używać w atrybucie klasy, ale autorzy są zachęcani do używania wartości opisujących naturę treści, a nie wartości opisujących pożądaną prezentację treści.

Ponadto w wersji 4 :

Atrybut klasy ma kilka ról w HTML:

  • Jako selektor arkuszy stylów (gdy autor chce przypisać informacje o stylu do zestawu elementów).
  • Do przetwarzania ogólnego przeznaczenia przez aplikacje klienckie.

Twój przypadek użycia mieści się w drugim scenariuszu, co czyni go uzasadnionym przykładem użycia atrybutu klasy.

Vitalii Fedorenko
źródło
13
+1 za cytowanie odpowiednich specyfikacji. Często zapominałem o tym.
BoltClock
40

Możesz użyć klasy, która nie ma stylów, jest to całkowicie poprawny HTML.

Klasa, do której odwołuje się plik CSS, nie jest definicją klasy, służy jako reguła selektora do celów stylizacji.

Lakoniczny
źródło
25

Kiedy używasz nazwy klasy w JavaScript, nie patrzy na CSS, aby znaleźć tę klasę. Wygląda bezpośrednio w kodzie HTML.

Wymagane jest jedynie, aby nazwa klasy była w kodzie HTML. Nie musi być w CSS.

W rzeczywistości wiele osób uważa, że dobrym pomysłem jest używanie oddzielnych klas w CSS i JavaScript , ponieważ pozwala to projektantom i programistom pracować niezależnie, nie wchodząc sobie nawzajem w siebie nawzajem.

(uwaga, powyższy akapit jest oczywiście bardziej odpowiedni dla większych projektów, więc nie myśl, że musisz przejść do tego ekstremum, jeśli pracujesz na własną rękę; wspomniałem o tym, aby podkreślić, że oba mogą być całkowicie oddzielne )

Spudley
źródło
13

Możesz używać klas CSS bez korzystania z nich, ale sugeruję, że jeśli dodajesz klasy CSS tylko dla kodu JavaScript / jQuery, przedrostek z nim, js-YourClassNameaby programiści front-end nigdy nie używali tych klas do stylowania elementów. Powinni zrozumieć, że klasy te można usunąć w dowolnym momencie.

Aamir Afridi
źródło
10

W momencie dodania klasy do kodu HTML klasa zostanie zdefiniowana, więc Twoje rozwiązanie będzie w porządku

koningdavid
źródło
7
Używanie klasy w HTML nie definiuje jej. Powiedziałbym raczej, że definicja jest nieistotna: nie ma kary za używanie niezdefiniowanych klas.
JAL
10

Definiowanie klas CSS w arkuszu stylów nie jest konieczne . Powinno działać dobrze. Jednak dodanie go nie zaszkodzi.

Rameez
źródło
Nie mówię, aby dodać te style, to zależy od niego, jeśli chce, jeśli planuje wspierać te style, to dlaczego nie? w każdym razie dzięki za niepotrzebne głosowanie w dół :)
Rameez,
Powiedziałeś „to ... nie zaszkodzi”, ale w końcu to zrobi.
Pavlo
tak, to nie zaszkodzi. jeśli ma zmysły, aby dodać te puste style, to oczywiście będzie miał zmysły, aby nimi zarządzać. Oczywiście nie dodam. Nigdzie nie polecam dodawać.
Rameez,
8

Jedną z rzeczy, o których nikt tu nie wspomniał w pełni, jest to, że JavaScript (w tym przypadku wspierany przez jQuery) nie jest w stanie bezpośrednio modyfikować kaskadowego arkusza stylów dokumentu. css()Metoda jQuery zmienia jedynie dopasowany zestaw właściwości elementów style. CSS i JavaScript są całkowicie niezwiązane w tym aspekcie.

$('.target').css('display','none');w ogóle nie zmienia .target { }deklaracji CSS. Zamiast tego dzieje się tutaj, że dowolny element z class„celem” wygląda teraz mniej więcej tak:

<element class="target" style="display:none;"></element>

Czy są jakieś skutki uboczne spowodowane brakiem wstępnego zdefiniowania reguły stylu CSS? Absolutnie nic.

Czy jest na to lepszy sposób? Pod względem wydajności, tak, jest!

Jak można poprawić wydajność?

Zamiast bezpośrednio modyfikować stylekażdy element, zamiast tego możesz wstępnie zdefiniować nową klasę i dodać ją do dopasowanych elementów za pomocąaddClass() (innej metody jQuery).

Na podstawie tej wcześniej istniejącej JSPerf który porównuje css()ze addClass()widzimy, że addClass()jest o wiele szybciej:

css () vs addClass ()

Jak sami możemy to zrealizować?

Po pierwsze możemy dodać w naszej nowej deklaracji CSS:

.hidden {
    display: none;
}

Twój HTML pozostanie taki sam, ta wstępnie zdefiniowana klasa jest po prostu gotowa do późniejszego wykorzystania.

Możemy teraz zmodyfikować JavaScript, aby addClass()zamiast tego używał :

$('.target').addClass('hidden');

Podczas uruchamiania tego kodu, zamiast bezpośrednio modyfikować stylewłaściwość każdego dopasowanego elementu „docelowego”, nowa klasa zostanie teraz dodana:

<element class="target hidden"></element>

Dzięki nowej „ukrytej” klasie element ten odziedziczy styl deklarowany w twoim CSS, a twój element nie będzie już wyświetlany.

James Donnelly
źródło
Dobra rada. Rzadko jest dobry powód, aby używać .css()zamiast przełączać klasy IMO.
BoltClock
6

Jak wspomina wiele innych osób, tak, używanie klas bez przypisanego CSS jest całkowicie poprawne i zamiast myśleć o nich jako o „klasach CSS”, powinieneś po prostu rozpoznać semantykę klasy i identyfikatora odpowiednio jako grupy i poszczególne elementy.

Chciałem się przyłączyć, ponieważ czułem, że podany przykład nie podniósł ważnej kwestii. Jeśli kiedykolwiek będziesz potrzebować wizualnych manipulacji na elementach o zmiennej długości (w tym przypadku używasz wierszy tabeli), zawsze warto rozpoznać, że koszt zrobienia tego za pomocą Javascript może być bardzo drogi (np. Jeśli masz tysiące wierszy).

W tej sytuacji powiedzmy, że wiemy, że kolumna 2 zawsze ma potencjał do ukrycia (jest to świadoma funkcja twojej tabeli), wtedy warto zaprojektować styl CSS do obsługi tego przypadku użycia.

table.target-hidden .target { display: none; }

Następnie zamiast używać JS do przechodzenia między elementami DOM znajdującymi N, musimy po prostu przełączyć klasę na jednym (naszej tabeli).

$("table").addClass("target-hidden")

Przypisując do tabeli identyfikator, byłoby to jeszcze szybsze i możesz nawet po prostu odwołać się do kolumny za pomocą :nth-childselektora, co jeszcze bardziej zmniejszy twoje znaczniki, ale nie mogę komentować wydajności. Innym powodem tego jest to, że nienawidzę stylizacji wbudowanej i dołożę wszelkich starań, aby ją wyeliminować!

Ian Clark
źródło
1
+1 za „grupy i poszczególne elementy” oraz za efektywne wykorzystanie struktury dokumentu
deltab 11.09.2013
5

Nie przyniesie to efektu, jeśli zastosujesz klasę do elementu HTML, a klasa ta nie zostanie zdefiniowana w CSS. Jest to powszechna praktyka i jak powiedział Aamir afridi, jeśli używasz klas wyłącznie w celu js, dobrą praktyką jest poprzedzenie ich js-.

Dotyczy to nie tylko calsses, ale także atrybutu id elementów HTML.

Altaf Hussain
źródło
4

Nie ma żadnego problemu z użyciem klas do zapytania o elementy. Kiedyś nadawałem takim nazwom klas sys-prefiks (na przykład nazwę twoją klasę sys-target), aby odróżnić je od klas używanych do stylizacji. Była to konwencja stosowana w przeszłości przez niektórych programistów Microsoft. Zauważyłem również rosnącą praktykę używania js-prefiksu do tego celu.

Jeśli nie masz doświadczenia w używaniu klas do celów innych niż stylizacja, polecam użycie wtyczki jQuery Role.js, która pozwala osiągnąć ten sam cel za pomocą roleatrybutu, więc możesz napisać znaczniki jako <td role="target">i użyć zapytania $("@target"). Strona projektu ma dobry opis i przykłady. Używam tej wtyczki do dużych projektów, ponieważ naprawdę lubię utrzymywać klasy wyłącznie w celach związanych ze stylizacją.

Ashraf Sabry
źródło
3

Zobacz silnik sprawdzania poprawności jQuery . Nawet tam używamy nieistniejących klas do dodawania reguł sprawdzania poprawności atrybutów HTML . Więc nie ma nic złego w korzystaniu z klas, które nie zostały zadeklarowane w arkuszu stylów.

dhruvin
źródło