Κανόνες 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 επειδή διαβάζει καλά.
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
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.