
Nakon godina pisanja i održavanja nekoliko vrlo velikih web projekata i brojnih manjih, razvio sam neke heuristike za pisanje održivog CSS-a. Za imenovanje sam koristio BEM, SMACSS i CSS module, iako ovaj članak nije sam o imenovanju. (Obično koristim kombinaciju atomskih klasa i BEM-ish imenovanja.) Ovaj je članak više o svojstvima i vrijednostima koje koristim ili izbjegavam.
Moja konfiguracija StyleLinta: //github.com/NickGard/css-utils/blob/master/stylelint.config.jsonBoje
Moj kućni ljubimac prekomjerno je obilje vrijednosti boja u web projektu. Veliki, dugovječni projekt na kojem sam radio prije nekoliko godina imao je preko 40 jedinstvenih CSS datoteka prijavljenih preko 300 jedinstvenih boja. Trećina njih bile su sive sjene. Boje marke ponovljene su s malim razlikama u nijansi. Mnoge od ovih boja razlikovale su se doslovno neprimjetnim vrijednostima, poput #3426D1
i #3426D2
. Rješenje za to je ili uporaba atomskih klasa boja ili varijabli (u SCSS-u ili CSS-u) za prihvaćene boje marke.
Ograničavanje broja prihvaćenih boja ima dodatnu prednost što pojednostavljuje osiguravanje da boje pozadine i prednjeg plana zadovoljavaju smjernice kontrasta boja WCAG2.0.
Druga praksa sklona bugovima je korištenje boja alfa-kanala, obično deklariranjem boje pomoću rgba()
ili hsla()
funkcija. Ovako stvorena boja s vrijednosti alfa kanala bilo čega osim što 1
je poluprozirna. Opažena boja sada se mijenja ovisno o tome što je u pozadini . Obično je željena boja kako ova izgleda na bijeloj pozadini, tako da umjesto nje možete upotrijebiti hex vrijednost. Neke funkcije pretprocesora, poput SASS-ovih lighten()
, generirat će poluprozirnu boju, zato se pridržavajte teško kodiranih vrijednosti ili varijabli.
Tipografija
Sva svojstva koja utječu ili su pogođeni font bi trebao biti proglašen jednom okupljanja. Odmah nakon proglašenja bilo @font-face
pravila, ja bih dodati atomske satove font koji mijenjaju font-size
(preko rem
), a uključuju line-height
, letter-spacing
i word-spacing
da su prikladne za tu kombinaciju slova i veličine. Nakon toga, nijedno font-*
ili text-*
(s izuzetkom text-overflow
) svojstvo ne bi se trebalo koristiti u bilo kojem skupu pravila.
Izjava ovih svojstava jednom u kombinaciji s fontom lica osigurava da kopija na web mjestu uvijek izgleda ispravno. Prilagođavanjem line-height
umjesto padding
ili margin
će stvoriti greške kada se tekst premota. Prilagođavanje font-weight
odvojeno od deklaracije fonta riskira stvaranje umjetnog podebljanog fonta. Promjenom font-style
fonta koji ga ne podržava stvara se umjetna kosa.
Na kraju, izbjegavajte postavljanje veličina fonta u bilo čemu osim u rem
jedinicama. Upotreba em
uzrokuje probleme pri ugnježđivanju elemenata jer em
je skalarni višekratnik strujefont-size
. Korištenje px
(ili bilo koje drugo „fiksno“ mjerenje) riskira stvaranje kopije koja se teško čita i koju korisnik ne može prilagoditi. Omogućuje korisniku (ili korisnikov preglednik) za postavljanje font-size
na ono što je dobro za njih nije progla font-size
na body
ili html
elementa i samo pomoću rem
.
Razmak
Na web mjestu s prvim sadržajem razmak treba nadopuniti kopiju. Svako statično mjerenje, na primjer padding: 4px
, izgleda pogrešno na određenoj veličini fonta. Dinamično mjerenje koje odgovara veličini fonta padding: .5em
izgleda poput svake veličine fonta.
Koristite em
za svojstva razmaka.
Mreža
CSS Grid je vrlo dobro podržan (natrag na IE10!) I omogućuje slaganje sadržaja u dvije dimenzije bez dodanih elemenata spremnika poput Bootstrapova row
ili col
grid elemenata. Dizajneri često rade u rešetkama od 12 stupaca, a CSS okviri obično slijede njihov primjer, ali mreže, kao i svi razmaci, trebaju dopunjavati kopiju, a ne je ograničavati. Mreže treba pisati ad hoc, a ne u unaprijed određenom obliku bez konteksta. Nemojte nadimati svoj CSS "mrežnim okvirom".
Poravnanje teksta
text-align
se često koristi za poravnavanje stvari osim teksta. Ovo nije pravi alat za posao. Za ovu vrstu poravnanja upotrijebite flexbox. Korištenje vrijednosti left
i right
ne funkcionira uvijek s jezicima koji su zdesna nalijevo ili okomito (neki preglednici mapiraju te vrijednosti na relativni protok start
i end
, ali ne sve). Korištenje vrijednosti justify
teksta može u nekim jezicima stvoriti probleme s digrafima, a može i kod ljudi s disleksijom. Svaki slučaj upotrebe text-align
bolje je riješiti flexboxom, pa umjesto toga upotrijebite. Stalno.
Obrisi
Obrisi fokusiranih elemenata su način na koji preglednici izvorno komuniciraju koji element prima ulaz. Zadani obrisi obično su dovoljno istaknuti da budu korisni svakom korisniku, uključujući one kojima je potreban visok kontrast. Zadani se obris obično prepisuje (ili uklanja) jer se ne uklapa u dizajn web stranice. Ako ne zamijenite fokusirani outline
stil nekim drugim istaknutim i dostupnim pokazateljem fokusa, nemojte uklanjati ili poništiti svojstvo obrisa .
Fokus i pokazivač
Kao što je gore spomenuto, pazite na promjenu :focus
stila jer djeluje kao pokazatelj za koji element trenutno prima ulaz. Dodavanje stilova elementu na :hover
često je lijep dodir, ali nemojte koristiti taj pseudo-selektor za prikaz dodatne kopije, osim ako to ne učinite za :focus
(i, naravno, ako je element fokusiran ). Obično je, ali ne uvijek, dobra ideja koristiti :hover
i :focus
pseudo-selektore za isti skup pravila. (Dodavanje :focus
birača stilovima lebdenja gumba može rezultirati pritiskom gumba koji izgleda "zaglavljen".)
Neprozirnost
Postavljanje opacity
elementa na njega 0
zapravo ga ne skriva od alata za pristupačnost. Element i dalje zauzima mjesto u tijeku dokumenta, a čitači zaslona i dalje čitaju njegovu kopiju. Jedina dva slučaja upotrebe koja opravdano zahtijevaju upotrebu opacity
svojstva je prilikom prijelaza elementa u prikaz (brzi prijelaz iz 0
u 1
) i prilikom oblikovanja dijaloškog sloja (tako da je sadržaj u nastavku donekle vidljiv). Pazite se "naslaganih" poluprozirnih slojeva. Razina neprozirnosti je multiplikativna, pa je sadržaj ispod dva prekrivača, svaki sa opacity: 50%
, prikazan kao da je ispod jednog elementa sa opacity: 25%
.
Selektori
Pridržavajte se korištenja selektora klase i klase. Korištenje id, tipa i univerzalnih selektora dolazi s glavoboljama. U specifičnosti CSS-a, selektori id-a uvijek će pobijediti bilo koji drugi selektor, ali id
atributi bi trebali biti jedinstveni (po stranici), tako da nisu korisni za primjenu stilova za višekratnu upotrebu.
Izvedba selektora u modernim preglednicima zanemariva je, pa unatoč onome što ste možda čuli o tome da univerzalni selektor ( *
) ne radi, moja je stvarna briga zbog njegove upotrebe to što je preopćenit za gotovo svaki slučaj upotrebe. Koristeći neki selektor poput .my-class >
; * na kraju će dovesti do isključivanja nekog djeteta, pa biste mogli dodati nastavu elementima koje želite oblikovati i izravno ih ciljati.
Sličan argument može se napraviti za nekorištenje tipa selektora, kao što su div
, main
. Oni se obično podudaraju s previše elemenata i obično zahtijevaju više detalja kako bi bili korisni, kao što su div.some-class
. Ovakvi složeni selektori imaju veću specifičnost od selektora jedne klase, problem stvaranja grešaka koji je opisan u nastavku.
Držite se selektora klase ( .class
), atributa ( [attribute]
) i pseudo-klase ( :focus
). Svi imaju istu razinu specifičnosti.
Specifičnost
At the opposite end of the spectrum of selectors being too general (like using *
) are selectors being too specific. Both cases cause problems. An overly-specific selector breeds even more specific selectors or the dreaded !important
declarations. Each successive selector becomes a new hurdle to overcome when making styling changes, and following this path leads to the ever-growing fragile stylesheets we all dread working with.
CSS has a naturally increasing specificity — the order of the rulesets. This is part of the cascade in Cascading Style Sheets. With this in mind, we can write rulesets in ascending order of “importance” without increasing the selector specificity level. For example:
.btn { color: black;}.btn--primary { color: green;}.btn--primary--light { color: white;}
In this example, each single-class-selector is more specific than its predecessor, eliminating the need to declare a ruleset for .btn.btn--primary
or .btn.btn--primary--light
.
The fix is to stick to single class selectors as much as possible, written in order of increasing “importance,” and avoid using !important
declarations.
Text-transform
For sites that support languages other than English, using text-transform
will probably cause problems. There are several cases where browsers replace a character with an incorrect version for the upper- or lower-case transformations. The fix is never to use text-transform
and instead rely on an accurately capitalized copy.
Z-index
If any z-index
rule is included in a stylesheet, there will eventually be two other rules that declare z-index: 9999;
and z-index: 99999;
. Attempting to use atomic classes or variables to limit the number of acceptable z-indexes will not only fail to curb developers from using calc()
and SCSS math to modify the value for their use-case, but will miss the target entirely because of how stacking contexts work.
It has been my experience that most, if not all, uses of z-index
can be replaced by restructuring the HTML to use the natural stacking context (elements lower on the page are higher in the context) or by adding a property to the element or its parent to force a new stacking context.
Avoid z-index
at all costs.
Pseudo-elements
Using the pseudo-elements ::before
and ::after
is not only helpful, but it’s often fun! Many stylistic tricks rely on the use of these two pseudo elements and, as long as there is no copy in them (via their content
property), they are considered semantic. The issue with putting copy in these elements is that whether or not they are read by accessibility devices varies across browsers and devices. It is better to not deal with that discrepancy by avoiding placing a copy in them.
The pseudo-elements ::first-letter
and ::first-line
do not work like you probably think they should. They only target the first letter/line in a block-level element. There are also issues with the ::first-line
selector incorrectly targeting double-byte characters (such as Japanese Kana) and digraphs.
Manipulating the styles of selected text or placeholder text via ::selection
and ::placeholder
, respectively, often leads to trouble. With ::placeholder
, the concern is simple: you shouldn’t be using placeholders. This is especially true for anything of importance, such as input labels or hints. By including ::placeholder
styles, you encourage developers, designers, and authors to use them, much to the frustration of your users.
Modifying selection styles, usually color
and background-color
, leads to more subtle but insidious bugs. While the default selection colors are not consistent across browsers or devices and they do not always provide an acceptable contrast with your site’s text color, users sometimes overwrite them for accessibility reasons. Changing the colors, in this case, could either not work (because of the user’s accessibility CSS trumps yours) or it could interfere with their style sheets (if you use !important
). Using this pseudo-element to try to guarantee an accessible contrast could end up disrupting the experience for the very people you wish to help.
(Though I’ve forgotten many of the details of this bug, I ran into an issue years ago where Chrome’s auto-translated text was rendered invisible because it relied on ::selection
styling which I had modified.)
Transitions & Animations
Transitioning or animating properties other than opacity
and transform
causes the browser to repaint or reflow the page. This may not seem like a problem on a high-end developer machine, but it will cause stuttering on low-end laptops and phones. Bad animation is worse than no animation.
Prefers Reduced Motion
Writing animations that are helpful, beautiful, and safe is not a simple undertaking. With the advent of the media query prefers-reduced-motion
, we can help make our pages safer for people with vestibular disorders, and less annoying for the rest of us. While adding this media query is not a silver bullet, it helps. I’ve written the nested rule to be opt-out, meaning that all CSS animations get stopped unless the author includes the class safe-animation
on the element.
/* //github.com/mozdevs/cssremedy/issues/11#issuecomment-462867630 */@media (prefers-reduced-motion: reduce) { *:not(.safe-animation), *:not(.safe-animation)::before, *:not(.safe-animation)::after { animation-duration: 0.01s !important; animation-iteration-count: 1 !important; transition-duration: 0s !important; scroll-behavior: auto !important; }}
Reset extensions
My go-to CSS reset is a modified form of the Meyers reset. There are a few rules I remove from the reset, though. I don’t like to remove list icons from ol
and ul
elements. I find that doing so encourages developers to use those elements in non-semantic ways, like grouping items that are physically proximate but not ontologically proximate. I also remove the rule setting the line-height
on the body
to 1
. Setting attributes that affect, or are affected by, the font separately from setting the font is a bug waiting to happen.
Neki dodaci u datoteci za poništavanje nalaze se u nastavku. Ne volim uključivati .hidden
atomsku klasu u svoj CSS, jer postoji bolja opcija koja će raditi čak i ako se CSS ne učita - hidden
atribut. Zadana postavka preglednika u postavkama display: none
skrivenih elemenata može se prebrisati, čak i slučajno, pa uključujem pravilo da se to izvrši.
body { /* more intuitive sizing */ box-sizing: border-box;}*, ::before, ::after { box-sizing: inherit;}i, cite, em, var, dfn, address { /* prevent faux italic */ font-style: normal;}b, h1, h2, h3, h4, h5, h6, strong, th { /* prevent faux bold */ font-weight: normal;}[hidden] { /* enforce accessible semantics */ display: none !important;}
Moj reset: //github.com/NickGard/css-utils/blob/master/reset.cssJoš jedan uslužni program koji često smatram potrebnim je visually-hidden
klasa. Iako aria-label
češće koristim za nevidljivi tekst koji se čita s ekrana, obično negdje uključim sljedeće pravilo:
/* //a11yproject.com/posts/how-to-hide-content/ */.visually-hidden { position: absolute !important; height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px);}
BEMish imenovanje

Original text
Ne mogu završiti ovaj članak bez barem jednog komentara na konvencije imenovanja. Sviđa mi se BEM imenovanje jer dobro čita.