CSS pravila koja će vam olakšati život

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.json

Boje

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 #3426D1i #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 1je 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-facepravila, ja bih dodati atomske satove font koji mijenjaju font-size(preko rem), a uključuju line-height, letter-spacingi word-spacingda 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-heightumjesto paddingili marginće stvoriti greške kada se tekst premota. Prilagođavanje font-weightodvojeno od deklaracije fonta riskira stvaranje umjetnog podebljanog fonta. Promjenom font-stylefonta koji ga ne podržava stvara se umjetna kosa.

Na kraju, izbjegavajte postavljanje veličina fonta u bilo čemu osim u remjedinicama. Upotreba emuzrokuje probleme pri ugnježđivanju elemenata jer emje 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-sizena ono što je dobro za njih nije progla font-sizena bodyili htmlelementa 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: .5emizgleda poput svake veličine fonta.

Koristite emza 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 rowili colgrid 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-alignse često koristi za poravnavanje stvari osim teksta. Ovo nije pravi alat za posao. Za ovu vrstu poravnanja upotrijebite flexbox. Korištenje vrijednosti left i rightne funkcionira uvijek s jezicima koji su zdesna nalijevo ili okomito (neki preglednici mapiraju te vrijednosti na relativni protok starti end, ali ne sve). Korištenje vrijednosti justifyteksta može u nekim jezicima stvoriti probleme s digrafima, a može i kod ljudi s disleksijom. Svaki slučaj upotrebe text-alignbolje 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 outlinestil 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 :focusstila 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 :hoveri :focuspseudo-selektore za isti skup pravila. (Dodavanje :focusbirača stilovima lebdenja gumba može rezultirati pritiskom gumba koji izgleda "zaglavljen".)

Neprozirnost

Postavljanje opacityelementa na njega 0zapravo 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 opacitysvojstva je prilikom prijelaza elementa u prikaz (brzi prijelaz iz 0u 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 idatributi 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 .hiddenatomsku klasu u svoj CSS, jer postoji bolja opcija koja će raditi čak i ako se CSS ne učita - hiddenatribut. Zadana postavka preglednika u postavkama display: noneskrivenih 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.css

Još jedan uslužni program koji često smatram potrebnim je visually-hiddenklasa. 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. /> tells me exactly what kind of button it is. My one break from the Official BEM™ methodology is that I like to use one class on an element (with the possible exception of atomic classes). It offends my sensibilities to see