CSS Architecture for Design Systems

właśnie stworzyliśmy system projektowania dla ogromnej organizacji i stworzyliśmy architekturę CSS, z której jesteśmy bardzo zadowoleni. To jeden z pierwszych przypadków, kiedy dotarłem do mety projektu, nie żałując, że zrobiłem co najmniej kilka rzeczy inaczej. Pomyślałem więc, że byłoby wspaniale podzielić się tym, jak zaczęliśmy tworzyć architekturę CSS naszego systemu.

aby dać trochę kontekstu dla projektu, powierzono nam zadanie stworzenia systemu projektowania i przewodnika po stylu, który ma służyć tysiącom programistów organizacji, którzy wykorzystują szeroką gamę technologii do budowy ponad 500 wewnętrznych aplikacji internetowych.

przytłaczająca większość programistów organizacji Nie specjalizuje się w tworzeniu frontendu, ale raczej koncentruje się na programowaniu aplikacji, danych i logice. Ponieważ ci programiści muszą szybko uruchamiać swoje aplikacje, często po prostu kopiują i wklejają kod frontendowy z innych aplikacji lub sięgają po frameworki, takie jak Bootstrap, aby wykonać zadanie UI. Jak można się spodziewać, łączny wynik tych działań jest hodgepodge niespójnych doświadczeń internetowych. Oczywiście jest to, co chcieliśmy naprawić, budując organizację własną przemyślany, solidny system projektowania interfejsu użytkownika.

ustal Zasady CSS

na początku projektu rozmawialiśmy z programistami o ich procesie i punktach bólu oraz zapytaliśmy, w jaki sposób system projektowania interfejsu może ułatwić im życie.

przeszliĺ „my i wypeĹ 'niliĺ” my kwestionariusz wytycznych dotyczÄ … cych frontendu, ktĂłry zaowocowaĺ 'zestawem zasad dotyczÄ … cych frontendu, ktĂłre miaĹ’ y byÄ ‡ zawarte w systemie. Oto zasady specyficzne dla CSS, które ustaliliśmy:

  • zrób to modułowo. – System projektowania jest modułowy pod każdym względem, co bardzo odnosi się do sposobu pisania CSS. Powinna istnieć wyraźna separacja między komponentami.
  • czytelność jest kluczem. – Programiści powinni być w stanie zrozumieć kod CSS na pierwszy rzut oka i zrozumieć cel każdego selektora.
  • klarowność przewyższa zwięzłość – system projektowania może czasami wydawać się gadatliwy, ale w zamian zapewnia jasność i odporność. Utrzymanie czytelności i skalowalności CSS oznacza rezygnację z krótszej składni.
  • Keep things flat – w miarę możliwości należy unikać długich ciągów selektora, aby CSS był jak najbardziej niezależny od DOM i modularny.
  • unikaj konfliktów-ponieważ komponenty będą wdrażane w wielu różnych aplikacjach, ważne jest, aby upewnić się, że CSS systemu projektowania nie jest w konflikcie z innymi bibliotekami i systemami. Jest to możliwe dzięki systemowej przestrzeni nazw klas, opisanej bardziej szczegółowo poniżej.

stamtąd stworzyliśmy konwencje i składnię, która uwzględniała te zasady, aby zaspokoić potrzeby programistów. Oto spojrzenie na składnię klasową, którą wymyśliliśmy:

globalna Przestrzeń nazw

wszystkie klasy powiązane z systemem projektowania są poprzedzone globalną przestrzenią nazw, która jest nazwą firmy, po której następuje myślnik:

.cn-

jeśli pracujesz nad architekturą CSS, która ma być obsługiwana tylko przez jedną witrynę lub masz dużą kontrolę nad swoim środowiskiem, w tym globalną przestrzenią nazw, prawdopodobnie nie jest to konieczne. Ale jeśli Twój system projektowania przeplata się z innymi technologiami, sensowne może być utworzenie identyfikatora dla kodu specyficznego dla systemu. Lightning Design System stosuje podobne podejście do swojego systemu (z prefiksem .slds-), ponieważ zewnętrzni programiści używają swojego systemu w środowiskach, nad którymi Salesforce może nie mieć kontroli. W naszym przypadku wielu programistów naszego klienta używa Angular, więc są już zaznajomieni z pojęciem przestrzeni nazw, ponieważ Angular używa ng- jako przestrzeni nazw dla kodu specyficznego dla Angular.

prefiksy klas

oprócz globalnej przestrzeni nazw dodaliśmy prefiksy do każdej klasy, aby było bardziej widoczne, jakie zadanie wykonuje ta klasa. Oto na jakich przedrostkach klasowych wylądowaliśmy:

zostałem wprowadzony do tej koncepcji przez Harry ’ ego Robertsa i chociaż myślałem, że mają one sens, na początku byłem trochę sceptyczny, ponieważ były to Dodatkowe znaki i myślałem, że prefiksy mogą faktycznie zmniejszyć czytelność kodu. Wcale tak nie było. Po zaimplementowaniu prefiksów klas okazało się, że są one niezwykle pomocne w wyjaśnieniu roli każdej klasy i ułatwiły rozszyfrowanie kodu aplikacji na pierwszy rzut oka. Ten rodzaj jasności jest szczególnie pomocny dla użytkowników systemu projektowania, aby mogli łatwo zrobić głowy lub ogony rzeczy.

składnia BEMA

bem oznacza „Block Element Modifier”, co oznacza:

ta metodologia zyskuje dużą popularność, a połączenie tych pojęć z globalną przestrzenią nazw i prefiksami klas pozwoliło nam stworzyć jeszcze bardziej wyraźne, zamknięte nazwy klas.

łączenie tego wszystkiego: anatomia klasy

połączenie globalnej przestrzeni nazw, prefiksów kategorii i składni BEM skutkuje wyraźnym (i tak, gadatliwym) ciągiem klas, który pozwala programistom wywnioskować, jakie zadanie odgrywa w konstruowaniu interfejsu użytkownika.

spójrzmy na poniższy przykład:

.cn-c-btn--secondary
  • cn- jest globalną przestrzenią nazw dla wszystkich stylów pochodzących z systemu projektowania.
  • c- jest kategorią klasy, co w tym przypadku c- oznacza „Składnik”
  • btn jest nazwą bloku („Block” jest „B” w BEM)
  • --secondary jest modyfikatorem, wskazującym na odmianę stylistyczną bloku („modyfikator „jest” M ” w BEM)

oto kolejny przykład:

.cn-l-grid__item
  • cn- po raz kolejny jest globalną przestrzenią nazw systemu.
  • l- jest kategorią klasy, co w tym przypadku l- oznacza „układ”
  • grid czy nazwa bloku
  • __item jest elementem, wskazującym, że jest to potomek bloku („Element” jest ” E ” w BEM)

i jeszcze jedno:

.cn-c-primary-nav__submenu
  • cn- jest globalną przestrzenią nazw systemu.
  • c- jest kategorią klasy, co w tym przypadku C- oznacza”component”
  • primary-nav to nazwa bloku
  • __submenu jest elementem, wskazującym, że jest to potomek bloku („Element” jest ” E ” w BEM)

ponownie, nie ma wątpliwości, że te klasy są bardziej gadatliwe niż większość innych podejść tam, ale dla tego konkretnego systemu te konwencje miały dużo sensu.

inne sztuczki

będąc wyraźnym z minutią

aby zapobiec rozpadowi rzeczy, wyszczególniliśmy, jak obsługiwać wiele drobnych szczegółów, takich jak komentarze, odstępy wokół bloków kodu, tabulatory vs spacje itp. Na szczęście Harry Roberts przygotował doskonały i wszechstronny zasób o nazwie wytyczne CSS, które wykorzystaliśmy jako punkt odniesienia dla tego rodzaju konwencji. Przeczesaliśmy wszystko i oznaczyliśmy obszary, w których planowaliśmy odbiegać od tego, co napisał Harry.

Sass parent selectors

jednym z problemów, które zawsze miałem z CSS, jest ustalenie, gdzie do cholery umieścić daną regułę. Jeśli mam podstawowy komponent nawigacyjny, ale chcę dostosować jego wyrównanie, gdy pojawia się w komponencie nagłówka, czy umieszczam te style w moim nagłówku lub podstawowym Sass nawigacyjnym? Na szczęście istnieją selektory nadrzędne Sass, co pozwala nam zachować wszystkie style specyficzne dla komponentów pod jednym dachem:

oznacza to, że wszystkie moje podstawowe style nawigacyjne można znaleźć w głównym Sass nawigacji częściowej, zamiast dzielić je między wiele plików.

wyraźne reguły dotyczące zagnieżdżania Sassa

Zagnieżdżanie w Sassie może być bardzo wygodne, ale wiąże się z ryzykiem słabego wyjścia przy zbyt długich ciągach selektora. Postępowaliśmy zgodnie z zasadą Incepcji i nigdy nie zagnieżdżaliśmy Sass głębiej niż trzy warstwy.

mając na uwadze zasadę płaskości CSS systemu projektowania, chcieliśmy ograniczyć zagnieżdżanie do następujących przypadków użycia:

  1. modyfikatory bloku stylów
  2. zapytania o Media
  3. selektory nadrzędne
  4. Stany

1. Modyfikatory bloków stylów

w przypadku modyfikatorów, jeśli reguła ma tylko kilka linii, modyfikator może być zagnieżdżony wewnątrz rodzica w ten sposób:

.cn-c-alert { border: 1px solid gray; color: gray; /** * Error Alert */ &--error { border-color: red; color: red; }}

dzięki symbolowi & skompiluje się to do:

.cn-c-alert { border: 1px solid gray; color: gray;}.cn-c-alert--error { border-color: red; color: red;}

w przypadku dłuższych bloków stylów nie zagnieżdżaliśmy kodu modyfikującego, ponieważ zmniejszało to czytelność kodu.

2. Zapytania o Media

zapytania o media specyficzne dla komponentu powinny być zagnieżdżone wewnątrz bloku komponentów.

.cn-c-primary-nav { /* Base styles */ /** * 1) On larger displays, convert to a horizontal list */ @media all and (min-width: 40em) { display: flex; }}

to kompiluje się do:

.cn-c-primary-nav { /* Base styles */}@media all and (min-width: 40em) { .cn-c-primary-nav { display: flex; }}

3. Selektory rodzica

system projektowania wykorzysta mechanizm selektora rodzica Sass. Pozwala to na utrzymanie wszystkich reguł dla danego komponentu w jednym miejscu.

to skompiluje się do:

.cn-c-header .cn-c-primary-nav { display: flex;}

wszystkie style dla cn-c-primary-nav powinny być znalezione w jednym miejscu, a nie rozproszone po wielu plikach częściowych.

4. Stany

Stanów komponentu powinny być zawarte jako element zagnieżdżony. Dotyczy to Stanów hover, focus i active :

.cn-c-btn { background: blue; &:hover, &:focus { background: red; }}

to skompiluje się do:

.cn-c-btn { background: blue;}.cn-c-btn:hover, .cn-c-btn:focus { background: red;}

Stany mogą również przybierać formę klas użyteczności, takich jak is- i has-:

.cn-c-accordion__panel { overflow: hidden; max-height: 0; &.cn-is-active { max-height: 40em; }}

to skompiluje się do:

.cn-c-accordion__panel { overflow: hidden; max-height: 0;}.cn-c-accordion__panel.cn-is-active { max-height: 40em;}

wprowadzenie tych zasad dało nam pewne ograniczenia i konwencje, których musieliśmy przestrzegać, aby stworzyć solidny system. Gdy napotkaliśmy przypadki, w których Konwencja nie była oczywista lub rozwiązanie można było rozwiązać na kilka różnych sposobów, rozmawialiśmy o tym, jak sobie z tym poradzić i w razie potrzeby aktualizowaliśmy wytyczne.

czy to działa na wszystkich?

zanim zaczniesz się denerwować i nie zgadzać się z konkretnymi decyzjami, które podjęliśmy podczas tworzenia naszego systemu, zrozum, że ta architektura ma sens dla systemu, nad którym pracowaliśmy. Czy to oznacza, że jest to kuloodporne rozwiązanie dla każdego projektu? Nie, i tego nie proponuję. Specyficzne potrzeby i konfiguracja organizacji powinny w dużym stopniu wpływać na architekturę CSS Twojego systemu projektowania.

pracuję nad wieloma projektami, w których mogę poradzić sobie z ciągami takimi jak .table-of-contents li a, ale te projekty są głównie zarządzane przeze mnie. W przypadku projektów klientów, które wiążą się z pracą w środowisku zespołowym, bardzo skłaniam się ku bardziej gadatliwym, wyraźnym składniom, takim jak opisałem powyżej, ponieważ zapewniają one mniej miejsca dla ludzi na spieprzenie rzeczy. Wspaniale jest widzieć, jak inne zespoły, takie jak Sparkbox, dochodzą do podobnych wniosków.

po kilku tygodniach przerwy od projektu wracamy do kontynuowania prac nad wersją 1.1 systemu projektowego. Nie mogę się doczekać powrotu do tej bazy kodów i zobaczenia, jak szybko mogę się z nią ponownie zaaklimatyzować!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.