CSS faalt meestal niet meteen. Het faalt een jaar later, wanneer het systeem echt in gebruik is en het veranderen van iets risicovol voelt. Styles beginnen zwaar te voelen.Je opent DevTools, springt door de regels en probeert te begrijpen waarom iets werkt zoals het doet.Refactoring voelt mentaal belastend en tijdrovend, dus je voegt een andere override toe om het ticket weg te laten gaan. Slecht CSS is niet alleen lelijk, het is duur.Het is de reden waarom eenvoudige UI-updates drie dagen duren in plaats van drie minuten. De code doet het . te veel Te veel nesting. te veel specificiteit. te veel beslissingen die vroeg zijn genomen die te moeilijk en te duur zijn om te annuleren. Niet door middel van trucs of tools, maar door middel van een paar gewoonten die CSS eenvoudig, leesbaar en goedkoop houden om te veranderen naarmate een project groeit. Dit zijn de dingen die ik eerder zou willen leren. Beginnen met CSS is de eerste fout Ik weet dat het artikel over CSS gaat, maar een van de meest voorkomende fouten die ik zie dat junioren maken, is in een taak springen en alles tegelijk bouwen. Meestal beginnen ze met het meest ingewikkelde deel, of het grappigste deel. Ik krijg het. CSS is verleidelijk omdat het tastbaar is. De betere aanpak is om CSS opzij te zetten, te pauzeren, te vertragen en te beginnen met de markering. Als je een hele app bouwt, begin dan met de schil van de pagina. Landmarks, headerhiërarchie, hoofdgedeelten. Werken op dat eerst. Lees de pagina beginnen om te eindigen. Heeft het zin? Ga alleen naar stijlen als het doet. Als u werkt aan een kleinere functie, geldt hetzelfde idee. Plaats eerst de markering en zie hoe deze past in de rest van de app. komen de tags overeen met de bedoeling? Beginnen met markeren dwingt je om na te denken over intentie, niet uiterlijk. Niet wat zij Met een HTML-first benadering definieer je structuur, betekenis en beperkingen die het systeem eenvoudig en voorspelbaar houden. zijn Kijk als CSS should adapt to that, not the other way around. Wanneer je haast in styling, je neigt om de markering te vormen rond visuele aanwijzingen. Extra wrappers. Verkeerde tags. Meestal eindigt u met dingen die goed, maar zijn semantisch verkeerd, of onmogelijk te schalen. Kijk Door eerst de markering te doen, sluit je je in een solide basis. Toegankelijkheid, documentbeschrijving, toetsenbordstroom en inhoudhiërarchie worden voornamelijk van tevoren opgelost. Het vertraagt je ook op een goede manier. Je vangt kant gevallen vroeg. Je ziet waar dingen niet horen. Kortom: HTML-first maakt alles anders zinvol. Wanneer CSS meer doet dan je denkt Een andere veel voorkomende fout die ik zie in code beoordelingen is junioren doen Ik weet het vaak niet, maar ik geef je een paar voorbeelden. te veel Stel dat u de inhoudscolumn horizontaal wilt centraal stellen: .entry-content { max-inline-size: 48rem; margin: 0 auto; /* ❌ Avoid this! */ } U stelt een max breedte en centraal het element met behulp van automatische marges. Wat je echter misschien niet realiseert, is dat je bovenste en onderste marges ook op nul stelt. Meestal wordt de afkorting gebruikt alleen omdat het korter is.Wat je waarschijnlijk wilt in plaats daarvan is dit: .entry-content { max-inline-size: 48rem; margin-inline: auto; /* ✅ Do this */ } Hetzelfde resultaat. geen bijwerkingen. meer intentie. Een ander gemeenschappelijk voorbeeld: .button--secondary { background: var(--color--dark-gray); } Hiermee wordt de achtergrondkleur ingesteld met behulp van Aangepaste eigenschappen, maar het reset ook een aantal andere achtergrondgerelateerde eigenschappen. --color--dark-gray Heel veel, in feite: achtergrondfoto geen achtergrondpositie → 0% 0% achtergrondgrootte auto achtergrond - herhaling achtergrond-origin → padding-box achtergrondclip → border-box Background-attachment → scroll Dit kan gemakkelijk leiden tot vervelende bijwerkingen die u later moet omgaan. Wat je in plaats daarvan waarschijnlijk wilt is dit. .button--secondary { background-color: var(--color--dark-gray); } Hetzelfde idee als voorheen. Maar chirurgisch. Verander alleen wat je daadwerkelijk wilt veranderen. Hetzelfde principe geldt voor andere korthandige eigenschappen, zoals - het - het - het , en anderen. Wees voorzichtig bij het gebruik ervan als snelkoppelingen. of vermijd het gebruik van snelkoppelingen helemaal. border transform transition font Een veel voorkomend voorbeeld van te veel doen is te vroeg specifiek zijn. a { text-decoration: none; background-image:linear-gradient(to right, currentColor, currentColor); background-position:0%100%; background-repeat: no-repeat; background-size:100%2px; transition: background-size 0.3s; &:hover, &:focus-visible { background-position:100%100%; } } Deze snippet voegt een geanimeerde ondertitel toe aan links. Het probleem is dat niet alle tag is een tekstlink. afbeeldingen kunnen links zijn. profielavatars kunnen links zijn. knoppen worden vaak gemarkeerd als anchors. <a> Plotseling voegt deze "slimme" wereldwijde stijl vreemde 2px lijnen toe onder je logo of breekt de achtergrondgradiënten op je primaire knoppen. Nu, u zult de rest van het project besteden aan het vechten tegen de cascade, het schrijven van "undo" stijlen voor elke niet-tekstlink die u werkt op. visual debt U kunt dit op verschillende manieren oplossen.Een optie is om tekstlinks binnen content te targeten. .entry-content:is(h1, h2, h3, h4, h5, h6, p, li) > a { /* styles here */ } Maar zelfs dit kan nog steeds te smal of te breed zijn, afhankelijk van de markering. Mijn favoriete aanpak is een utility class. .has-animated-underline { /* styles here */ } Door dit naar een klasse te verplaatsen, maakt u het gedrag Het is expliciet, opzettelijk en - het belangrijkste - het vereist niet dat je dingen kiest die in eerste instantie niet zijn gebroken. opt-in rather than opt-out Wanneer mobiel een afterthought is Toch zie ik nog steeds ontwerpers het grootste deel van hun tijd doorbrengen aan desktopcomps en het presenteren van werk desktop-first, met mobiel behandeld als een eenvoudige "stacked" versie van de desktop. Dat voelt nog steeds achteruit. Houdt u ervan of niet, we ervaren het internet eerst via een telefoon. dat kan weer veranderen, maar het is de realiteit van vandaag. De manier waarop we voor het web bouwen, moet dat weerspiegelen. In de praktijk, dit is hoe ik benadering van styling nu: Plaats de markering uit (over het gesproken 😉). Vergroot de browser naar ongeveer 400px en stijl de app of functie alsof de desktop niet bestaat. Zodra het op mobiel werkt, verandert u de browser in desktop en maakt u een tweede pas op de stijlen. Door op deze manier te werken krijg je natuurlijk 80% (een willekeurig getal dat goed lijkt) in termen van het maken van je project toegankelijk en klaar voor kleine schermen. Dit leidt ons organisch naar de mobile-first implementatie. Toen ik begon met het maken van webontwikkeling, media queries waren nauwelijks een ding. we browsen het web niet op telefoons. Toen kwam de iPhone en media queries werden het belangrijkste hulpmiddel voor responsieve lay-outs.Het aantal web-capable apparaten was beperkt, dus je kon weg met een rigide set van breakouts: /* phones */ @media (max-width: 480px) {} /* large phones and small tablets */ @media (max-width: 767px) {} /* tablets */ @media (min-width: 768px) and (max-width: 1024px) {} /* desktop */ @media (min-width: 1025px) {} Let op: dit is niet eens mobiel-first. De benadering. min-width Tegenwoordig is de werkelijkheid anders.Er zijn te veel apparaten en schermgroottes om te ontwerpen voor het gebruik van breakpoints alleen. Bijvoorbeeld : intrinsieke lay-outs met Grid of Flexbox vloeibare waarden met clamp() voor lettergroottes, spacing en dimensies Containers willen Media-verzoeken zijn nog steeds nuttig, maar ze moeten niet het eerste hulpmiddel zijn dat u bereikt. Als een lay-out alleen werkt vanwege breakouts, is het waarschijnlijk te stijf. Wanneer het zonder hen werkt, worden media-verzoeken kleine, opzettelijke aanpassingen aan de responsieve structuur, niet aan de basis. De Cascade bestrijden in plaats van het te gebruiken Dit is een ander gebied waar ik vaak jonge ingenieurs worstelen zie. Veel CSS frameworks en oplossingen bestaan om één hoofdfunctie op te lossen: de cascade.En ik krijg waarom.Als je in CSS springt zonder veel ervaring, kan het chaotisch voelen. Je schrijft een regel en het doet niets. je tweak het en plotseling breekt iets anders. Dat is frustrerend omdat CSS niets is als de meeste andere talen.In JavaScript kun je een module maken en niets lekken. Je kunt CSS niet op dezelfde manier benaderen.Als je het probeert, zal het je echt hard in het gezicht bijten. Elke CSS-verandering leeft in twee gebieden tegelijk: het ding dat je stylet en de rest van het systeem waarin het stroomt. Terug naar het vorige voorbeeld kun je niet alleen dit schrijven: a { text-decoration: none; background-image:linear-gradient(to right, currentColor, currentColor); background-position:0%100%; background-repeat: no-repeat; background-size:100%2px; transition: background-size 0.3s; &:hover, &:focus-visible { background-position:100%100%; } } Als u dat doet, worden achtergrondgerelateerde eigenschappen toegepast op elke anker op de pagina, zelfs als die anker geen tekstlink is. Het merendeel van de tijd is dat niet wat je wilt. Sommige ingenieurs leren dit op de harde manier en reageren door de cascade helemaal te vermijden, zoals het aanraken van een hete oven als kind en leren om het nooit meer te doen. Ik denk dat dit een vergissing is, want het leidt tot veel herhaling. Hier is een voorbeeld van een recent project waar ik aan heb gewerkt. @define-mixin focus-state { &:focus-visible { outline: var(--outline--color) var(--outline--style) var(--outline--width); outline-offset: var(--outline--offset); } } Het werd vervolgens opgenomen in meerdere componenten: .button { @mixin focus-state; } a { @mixin focus-state; } .pagination-link { @mixin focus-state; } ... en zo. Focusoverzichten moeten samenhangend zijn in een project, met zeer weinig uitzonderingen. In deze instelling genereert elke mixin-oproep steeds opnieuw hetzelfde CSS. Een meer elegante benadering is om te vertrouwen op de cascade en dit wereldwijd te definiëren: :focus-visible { outline-color:var(--outline--color); outline-offset:var(--outline--offset); outline-style:var(--outline--style); outline-width:var(--outline--width); } Nu krijgt elk element dat een zichtbare focustoestand ontvangt, standaard dezelfde styling. En in de zeldzame gevallen waar iets anders moet zijn, kunt u het lokaal overschrijven: .pagination-link { --outline--offset: -2px; } Dat is het. eenvoudig, compact en voorspelbaar. Hetzelfde geldt voor zaken als - het De marge herstelt, , en andere stijlen die consequent moeten gedragen in de app. box-sizing ::selection text-wrap Een snelle gut check helpt hier. als een stijl eruit ziet Hetzelfde geldt voor elk onderdeel, met Uitzonderingen, het behoort waarschijnlijk tot je wereldwijde stijlen. exactly very few Negeer de cascade niet. Gebruik het voor uw voordeel. Specificiteit is waar dingen voortdurend uit elkaar vallen Dit is meestal de reden achter "Ik schreef mijn CSS maar het werkt niet." Ik ga niet diep in wat specificiteit is gaan.MDN al Wat hier belangrijk is, is dat hoge specificiteit een van de belangrijkste oorzaken van pijn is bij het werken met bibliotheken van derden of met code van iemand anders. doet dat echt goed Neem dit voorbeeld: .layout > :not(.alignleft):not(.alignright):not(.alignfull):not(.alignwide) { max-width: var(--content-width); margin-left: auto; margin-right: auto; } Hier hebben we de directe kinderen van horizontaal en een max. breedte aanbrengen – alle kinderen behalve - het - het en . .layout alignleft alignright alignfull alignwide Er zijn twee belangrijke redenen waarom deze code ruikt. Eerst, dit is een zwarte lijst patroon. we stylen alles een groeiende lijst van dingen. Het probleem is dat "alles" altijd verandert na verloop van tijd. Naarmate het project groeit, zul je bijna zeker meer uitzonderingen toevoegen. Behalve Ten tweede verhoogt elke selector die je toevoegt de specificiteit. Dat betekent dat het overtreffen ervan een nog sterker selector vereist, - het Of om alles in te pakken Met andere woorden, je herstelt complexiteit met meer complexiteit. 0.5.0 !important @layer :where() WordPress is een goed voorbeeld van het beginnen zonder CSS-architectuur en eindigen met chaos. body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; } Ik krijg hier gemengde signalen.We hebben onszelf met de patroon, besefte dat het een slecht idee was, hersteld met En dan... toegepast Ik weet zeker dat er een reden was voor dit, maar man... is dat niet zo frustrerend. :not() :where() !important Je kunt dat allemaal zeker doen... ...of je kunt meer opzettelijk zijn en jezelf wat vrede kopen: /* 0.1.0 */ .layout > * { max-width: var(--content-width); margin-left: auto; margin-right: auto; } /* 0.2.0 */ .layout > .alignleft, .layout > .alignright { --content-width: var(--content-width--narrow); } /* 0.2.0 */ .layout > .alignwide { --content-width: var(--content-width--wide); } /* 0.2.0 */ .layout > .alignfull { --content-width: var(--content-width--full); } Dit is makkelijker te lezen en gemakkelijker te redeneren.De basisregel is De uitzonderingen zijn . 0.1.0 0.2.0 Voorspelbaar en opzettelijk. Hier is een andere gemeenschappelijke manier waarop specificiteit zonder goede reden groeit: /* ❌ combine element with a class ❌ element nested inside the block ❌ modifier nested inside the block */ a.button { &.button__label {...} &.button--secondary {...} } In dit voorbeeld: Als er geen reden is om a en .button te combineren, doe het dan niet. Als er geen reden is om de .button__label onder de .button te nestelen, doe dat dan niet. Hetzelfde geldt voor modifier klassen. Als u een nieuw onderdeel verzendt, is dit meestal wat u in plaats daarvan wilt: /* ✅ no element + class combination ✅ elements and modifiers stay flat */ .button {...} .button__icon {...} .button--primary {...} Hier is de vingerregel die ik volg: Stel de voorkeur aan een enkele klasse selector standaard. Gebruik variaties van hulpprogramma's in plaats van selectoren te stapelen. Houd de specificiteit op 0,1.0 of 0,1.1. Ga niet hoger dan 0.2.0 in functies die u verzendt. Vermijd #id selectors en inline stijlen in app code. ze spiken specificiteit en zijn pijnlijk om over te ronden. Gebruik alleen hogere specificiteit bij het overtreffen van code van derden of ouderwetse code die u nog niet kunt refactoren. Noot op - het en :where() @layer @scope Ik ben volledig op de hoogte van deze hulpmiddelen. U kunt de specificiteit tot nul verlagen met Isoleer stijlen met , en scope selectors met . :where() @layer @scope Ze zijn krachtig, en ze hebben hun plaats, maar ze repareren geen slechte architectuur. Dezelfde specificiteitsregels gelden nog steeds binnen elke laag en binnen elke reikwijdte. Houd de specificiteit laag.Je toekomstige zelf zal je bedanken.