Κανόνες CSS που θα κάνουν τη ζωή σας πιο εύκολη

Μετά από χρόνια γραφής και συντήρησης μερικών πολύ μεγάλων έργων Ιστού και πολυάριθμων μικρότερων, έχω αναπτύξει κάποια ευρετήρια για τη συγγραφή συντηρήσιμων CSS. Έχω χρησιμοποιήσει BEM, SMACSS και CSS Modules για την ονομασία, αν και αυτό το άρθρο δεν αφορά την ονομασία. (Τείνω να χρησιμοποιώ ένα συνδυασμό ατομικών τάξεων και ονομάτων BEM-ish.) Αυτό το άρθρο αφορά περισσότερο τις ιδιότητες και τις τιμές που χρησιμοποιώ ή αποφεύγω.

Διαμόρφωση My StyleLint: //github.com/NickGard/css-utils/blob/master/stylelint.config.json

Χρωματιστά

Ένα κατοικίδιο ζώο μου είναι μια υπερβολική πληθώρα τιμών χρώματος σε ένα διαδικτυακό έργο. Ένα μεγάλο, μακράς διάρκειας έργο στο οποίο δούλευα πριν από λίγα χρόνια είχε πάνω από 300 μοναδικά χρώματα που δηλώθηκαν σε 40-μερικά αρχεία CSS. Το ένα τρίτο αυτών ήταν αποχρώσεις του γκρι. Τα χρώματα μάρκας επαναλήφθηκαν με μικρές διαφορές απόχρωσης. Πολλά από αυτά τα χρώματα διέφεραν από κυριολεκτικά ανεπαίσθητες τιμές, όπως #3426D1και #3426D2. Η λύση σε αυτό είναι είτε να χρησιμοποιήσετε ατομικές κατηγορίες χρωμάτων είτε μεταβλητές (σε SCSS ή CSS) για τα αποδεκτά χρώματα μάρκας.

Ο περιορισμός του αριθμού των αποδεκτών χρωμάτων έχει το πρόσθετο πλεονέκτημα που καθιστά απλό να διασφαλίσετε ότι τα χρώματα φόντου και προσκηνίου πληρούν τις οδηγίες WCAG2.0 Color Contrast.

Μια άλλη πρακτική που είναι επιρρεπής σε σφάλματα είναι η χρήση χρωμάτων άλφα-καναλιού, συνήθως δηλώνοντας το χρώμα με rgba()ή hsla()λειτουργίες. Ένα χρώμα δημιουργήθηκε με αυτόν τον τρόπο με μια τιμή καναλιού άλφα οτιδήποτε άλλο από το 1ημι-αδιαφανές Το αντιληπτό χρώμα αλλάζει τώρα ανάλογα με το τι βρίσκεται στο παρασκήνιο . Συνήθως, το επιθυμητό χρώμα είναι αυτό που μοιάζει με λευκό φόντο, οπότε μπορείτε να χρησιμοποιήσετε μια δεκαεξαδική τιμή. Ορισμένες λειτουργίες προεπεξεργαστών, όπως οι SASS lighten(), θα δημιουργήσουν ένα ημι-αδιαφανές χρώμα, οπότε κολλήστε στις τιμές ή τις μεταβλητές με κωδικοποίηση.

Τυπογραφία

Όλες οι ιδιότητες που επηρεάζουν ή επηρεάζονται από τη γραμματοσειρά πρέπει να δηλώνονται μία φορά μαζί. Αμέσως μετά την κήρυξη τυχόν @font-faceκανόνες, θα ήθελα να προσθέσω ατομική μαθήματα για τη γραμματοσειρά ότι η αλλαγή του font-size(μέσω rem) και περιλαμβάνουν line-height, letter-spacingκαι word-spacingπου είναι κατάλληλα για το συγκεκριμένο συνδυασμό γραμματοσειρά και το μέγεθος. Μετά από αυτό, καμία font-*ή text-*(με εξαίρεση text-overflow) ιδιότητα δεν πρέπει να χρησιμοποιείται σε οποιοδήποτε σύνολο κανόνων.

Η δήλωση αυτών των ιδιοτήτων μία φορά σε συνδυασμό με τη γραμματοσειρά διασφαλίζει ότι το αντίγραφο στον ιστότοπο φαίνεται πάντα σωστό. Προσαρμογή του line-heightαντί για paddingή marginθα δημιουργήσει σφάλματα κατά την αναδίπλωση του κειμένου. Η font-weightξεχωριστή προσαρμογή από τη δήλωση γραμματοσειράς διατρέχει τον κίνδυνο δημιουργίας γραμματοσειράς faux. Η αλλαγή font-styleσε μια γραμματοσειρά που δεν την υποστηρίζει δημιουργεί μια πλαϊνή πλάγια.

Τέλος, αποφύγετε τον καθορισμό μεγεθών γραμματοσειρών σε οτιδήποτε άλλο εκτός από remμονάδες. Η χρήση emπροκαλεί προβλήματα κατά την ένθεση στοιχείων επειδή emείναι πολλαπλάσιο του τρέχοντοςfont-size . Η χρήση px(ή οποιασδήποτε άλλης «σταθερής» μέτρησης) κινδυνεύει να δημιουργήσει αντίγραφο που είναι δύσκολο να διαβαστεί και είναι αδύνατο για τον χρήστη να προσαρμοστεί. Αφήστε το χρήστη (ή το πρόγραμμα περιήγησης του χρήστη) για να ρυθμίσετε το font-sizeό, τι είναι σωστό για αυτούς με το να μην το χαρακτηρισμό font-sizeγια το bodyή htmlστοιχείο και μόνο χρήση rem.

Διάστημα

Σε έναν ιστότοπο που είναι πρώτο για περιεχόμενο, το διάστημα πρέπει να συμπληρώνει το αντίγραφο. Οποιαδήποτε στατική μέτρηση, όπως padding: 4px, φαίνεται λάθος σε κάποιο μέγεθος γραμματοσειράς. Μια δυναμική μέτρηση που ανταποκρίνεται σε μεγέθη γραμματοσειρών, όπως padding: .5em, φαίνεται ακριβώς σε κάθε μέγεθος γραμματοσειράς.

Χρήση emγια ιδιότητες απόστασης.

Πλέγμα

Το CSS Grid υποστηρίζεται πολύ καλά (πίσω στο IE10!) Και επιτρέπει την τακτοποίηση του περιεχομένου σε δύο διαστάσεις χωρίς πρόσθετα στοιχεία κοντέινερ, όπως στοιχεία Bootstrap rowή colπλέγμα. Οι σχεδιαστές συχνά εργάζονται σε πλέγματα 12 στηλών και τα πλαίσια CSS τείνουν να ακολουθούν, αλλά τα πλέγματα, όπως όλα τα διαστήματα, πρέπει να συμπληρώνουν το αντίγραφο, όχι να το περιορίζουν. Τα πλέγματα πρέπει να είναι γραμμένα ad hoc, όχι σε προκαθορισμένη μορφή χωρίς πλαίσιο. Μην φουσκώνετε το CSS σας με ένα «πλαίσιο πλέγματος».

Ευθυγράμμιση κειμένου

text-alignχρησιμοποιείται συχνά για την ευθυγράμμιση άλλων πραγμάτων εκτός από το κείμενο. Αυτό δεν είναι το σωστό εργαλείο για την εργασία. Χρησιμοποιήστε το flexbox για αυτό το είδος ευθυγράμμισης. Η χρήση των τιμών left και rightδεν λειτουργεί πάντα με γλώσσες από δεξιά προς τα αριστερά ή κάθετες (ορισμένα προγράμματα περιήγησης αντιστοιχούν αυτές τις τιμές στη σχετική ροή startκαι end, αλλά όχι σε όλες). Η χρήση της τιμής justifyστο κείμενο μπορεί να προκαλέσει προβλήματα σε ορισμένες γλώσσες με γραφήματα και μπορεί να προκαλέσει προβλήματα σε άτομα με δυσλεξία. Κάθε περίπτωση χρήσης για text-alignκαλύτερη επίλυση από το flexbox, οπότε χρησιμοποιήστε την αντ 'αυτού. Πάντα.

Περιγράμματα

Τα περιγράμματα στα εστιασμένα στοιχεία είναι ο τρόπος με τον οποίο τα προγράμματα περιήγησης επικοινωνούν εγγενώς σε ποιο στοιχείο λαμβάνουν είσοδο. Τα προεπιλεγμένα περιγράμματα είναι συνήθως αρκετά εμφανή ώστε να είναι χρήσιμα σε κάθε χρήστη, συμπεριλαμβανομένων εκείνων που χρειάζονται υψηλή αντίθεση. Το προεπιλεγμένο περίγραμμα συνήθως αντικαθίσταται (ή καταργείται) επειδή δεν ταιριάζει με το σχεδιασμό του ιστότοπου. Εκτός εάν αντικαθιστάτε το εστιασμένο outlineστυλ με κάποια άλλη εμφανή και προσιτή ένδειξη εστίασης, μην καταργείτε ή ακυρώνετε την ιδιότητα περιγράμματος .

Focus & Hover

Όπως αναφέρθηκε παραπάνω, προσέξτε να αλλάξετε :focusστυλ επειδή λειτουργεί ως δείκτης για το οποίο το στοιχείο λαμβάνει εισροές. Η προσθήκη στυλ σε ένα στοιχείο :hoverείναι συχνά μια ωραία πινελιά, αλλά μην χρησιμοποιείτε αυτόν τον ψευδο-επιλογέα για να εμφανίσετε επιπλέον αντίγραφο, εκτός εάν κάνετε το ίδιο για :focus(και, φυσικά, εάν το στοιχείο είναι εστιασμένο ). Είναι συνήθως, αλλά όχι πάντα, μια καλή ιδέα να χρησιμοποιήσετε και τα δύο τους :hoverκαι :focusψευδο-επιλογείς για το ίδιο σύνολο κανόνων. (Η προσθήκη του :focusεπιλογέα στα στυλ αιωρημάτων για ένα κουμπί μπορεί να οδηγήσει σε ένα πατημένο κουμπί που φαίνεται "κολλημένο".)

Αδιαφάνεια

Η ρύθμιση opacityτου στοιχείου σε 0δεν το κρύβει πραγματικά από τα εργαλεία προσβασιμότητας Το στοιχείο καταλαμβάνει ακόμη χώρο στη ροή του εγγράφου και το αντίγραφό του εξακολουθεί να διαβάζεται από τους αναγνώστες οθόνης. Οι μόνες δύο περιπτώσεις χρήσης που εύλογα απαιτούν τη χρήση της opacityιδιότητας είναι κατά τη μετάβαση ενός στοιχείου σε προβολή (γρήγορη μετάβαση από 0σε 1) και όταν ορίστε μια επικάλυψη διαλόγου (έτσι το παρακάτω περιεχόμενο είναι κάπως ορατό). Προσοχή στις στοιβαγμένες ημι-αδιαφανείς επικαλύψεις. Το επίπεδο αδιαφάνειας είναι πολλαπλασιαστικό, οπότε το περιεχόμενο κάτω από δύο επικαλύψεις το καθένα opacity: 50%εμφανίζεται σαν να είναι κάτω από ένα μόνο στοιχείο με opacity: 25%.

Επιλογείς

Παραμείνετε στη χρήση επιλογών τάξης και τάξης. Η χρήση αναγνωριστικών, τύπων και καθολικών επιλογών έρχεται με πονοκεφάλους. Στην εξειδίκευση CSS, οι επιλογείς αναγνωριστικών θα κερδίζουν πάντα έναντι οποιουδήποτε άλλου επιλογέα, αλλά τα idχαρακτηριστικά υποτίθεται ότι είναι μοναδικά (ανά σελίδα), επομένως δεν είναι χρήσιμα για την εφαρμογή επαναχρησιμοποιήσιμων στυλ.

Η απόδοση του επιλογέα στα σύγχρονα προγράμματα περιήγησης είναι μια αμελητέα ανησυχία, οπότε παρά ό, τι μπορεί να έχετε ακούσει για το ότι ο καθολικός επιλογέας ( *) δεν έχει απόδοση, η πραγματική μου ανησυχία με τη χρήση του είναι ότι είναι πολύ γενικό για σχεδόν κάθε περίπτωση χρήσης. Χρησιμοποιώντας κάποιον επιλογέα όπως .my-class >? * θα οδηγήσει τελικά στην εξαίρεση κάποιου παιδιού, οπότε μπορείτε επίσης να προσθέσετε μαθήματα στα στοιχεία που θέλετε να σχεδιάσετε και να τα στοχεύσετε απευθείας.

A similar argument can be made for not using type selectors, like div, main. They tend to match too many elements and usually require more details to be useful, such as div.some-class. Compound selectors like this have a higher specificity than a single class selector, a bug-generating problem addressed below.

Stick to class (.class), attribute ([attribute]), and pseudo-class (:focus) selectors. They all have the same level of specificity.

Specificity

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.

Ορισμένες προσθήκες που κάνω στο αρχείο επαναφοράς είναι παρακάτω. Δεν θέλω να συμπεριλάβω μια .hiddenατομική τάξη στο CSS μου, επειδή υπάρχει μια καλύτερη επιλογή που θα λειτουργήσει ακόμη και αν το CSS δεν φορτώσει - το hiddenχαρακτηριστικό. Η προεπιλεγμένη συμπεριφορά του προγράμματος περιήγησης display: noneσε κρυφά στοιχεία μπορεί να αντικατασταθεί, ακόμη και κατά λάθος, επομένως συμπεριλαμβάνω έναν κανόνα για την επιβολή του.

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;}
Η επαναφορά μου: //github.com/NickGard/css-utils/blob/master/reset.css

Ένα άλλο βοηθητικό πρόγραμμα που θεωρώ συχνά απαραίτητο είναι μια visually-hiddenτάξη. Ενώ χρησιμοποιώ aria-labelπιο συχνά για αόρατο κείμενο με δυνατότητα ανάγνωσης οθόνης, συνήθως συμπεριλαμβάνω κάπου τον ακόλουθο κανόνα:

/* //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 ονομασία

Δεν μπορώ να τελειώσω αυτό το άρθρο χωρίς τουλάχιστον ένα σχόλιο σχετικά με τις συμβάσεις ονομασίας. Μου αρέσει η ονομασία BEM επειδή διαβάζει καλά. /> tells me exactly what kind of button it is. My one break from the Official BEM™ methodology is that I like t o use one class on an element (with the possible exception of atomic classes). It offends my sensibilities t o see because the second class already tells me the styles extend from the base btn ruleset. This also creates two reasons for a line to change, which is a red flag.

In my CSS, this looks like this:

.btn, .btn--primary { /* base button styles */}.btn--primary { /* primary button overrides */ /* has naturally higher specificity */}

In SCSS, you can achieve this same effect using @extend.

Conclusion

These have been my rules of thumb for several years now and have helped me maintain large codebases with many contributors. It’s not perfect and I’m always adjusting it (prefers-reduced-motion is new) but I hope that by sharing it, it will help others.