Πώς να κατανοήσετε και να εργαστείτε με τα περιθώρια CSS

Το CSS παίρνει ένα κακό ραπ γιατί δεν συμπεριφέρεται όπως περιμένουν οι άνθρωποι. Ένα από τα πράγματα που ρίχνει τους ανθρώπους περισσότερο είναι τα περιθώρια. Φαίνονται τόσο απλοί, αλλά έχουν τη δυνατότητα να προκαλέσουν κάποια πραγματικά περίεργα ζητήματα.

Για τους ανθρώπους που μόλις εισέρχονται στο CSS, είναι εύκολα ένα από αυτά τα πράγματα που μπορεί να σας κάνουν να σκεφτείτε "αυτή είναι μια ηλίθια γλώσσα που δεν έχει νόημα!"

Το βλέπω καθημερινά - τόσο στην τάξη όσο οι άνθρωποι προσπαθούν να καταλάβουν τα διαστήματα τους και στις ενότητες σχολίων μου στο YouTube.

Κατά κάποιο τρόπο, τα περιθώρια είναι λίγο μικρόκοσμος του CSS γενικά. Το CSS φαίνεται τόσο απλό με τα property: valueζευγάρια του, αλλά καθώς προχωράτε με αυτό, συνειδητοποιείτε ότι υπάρχουν πολλά που συμβαίνουν.

Τα περιθώρια φαίνονται επίσης τόσο απλά. Προσθέστε κάποιο περιθώριο και προσθέτετε κενό χώρο γύρω από αυτό το στοιχείο. Αλλά τότε ξαφνικά συμπεριφέρονται λίγο διαφορετικά σε μια κατάσταση από την άλλη, ή προσθέτετε κάποια margin-topσε ένα παιδικό στοιχείο, και αντ 'αυτού είναι ο γονέας που κινείται προς τα κάτω.

Ακολουθεί η απογοήτευση.

Σε αυτό το άρθρο, ελπίζω να ρίξω λίγο φως στο πώς λειτουργούν τα περιθώρια. Θα εξετάσουμε μερικά από τα κοινά προβλήματα που συμβαίνουν, καθώς και απλές λύσεις σε αυτά τα ζητήματα.

Για να ξεπεράσω όλα αυτά, θα χρησιμοποιήσω παραδείγματα από το Bootcamp Responsive Web Design στο Scrimba, το οποίο έβγαλα αυτήν την απλή διάταξη από:

Διάταξη CSS χρησιμοποιώντας περιθώρια και παραγέμισμα

Τι είναι τα περιθώρια ούτως ή άλλως;

Πριν προχωρήσουμε πραγματικά στο βάθος εδώ, θέλω να βεβαιωθώ ότι όλοι γνωρίζουμε ποια είναι πραγματικά τα περιθώρια!

Θα υποθέσω ότι όλοι γνωρίζουμε ότι τα περιθώρια είναι μέρος του μοντέλου κουτιού, με το περιθώριο να είναι εντελώς έξω, ακολουθώντας το ίδιο το περιεχόμενο, την επένδυση και το περίγραμμα.

Το MDN τα εξηγεί πολύ καλά (δική μου έμφαση):

Το περιθώριο είναι το εξώτατο στρώμα, περιτυλίγματος του περιεχομένου, παραγέμισμα και περίγραμμα ως κενό μεταξύ αυτού του πλαισίου και άλλων στοιχείων . Το μέγεθός του μπορεί να ελεγχθεί χρησιμοποιώντας περιθώριο και σχετικές ιδιότητες.

Με άλλα λόγια, είναι ουσιαστικά κενός χώρος που μπορούμε να χρησιμοποιήσουμε για να δημιουργήσουμε χώρο μεταξύ ενός πλαισίου και ενός άλλου στη διάταξή μας.

Αντιμετώπιση φύλλων στυλ παράγοντα χρήστη

Τα προγράμματα περιήγησης συνοδεύονται από εκπληκτικό ποσό CSS από προεπιλογή, το οποίο ονομάζουμε φύλλα στυλ παράγοντα χρήστη . Αυτά τα στυλ είναι ο λόγος που, χωρίς κανένα CSS από την πλευρά μας, ένα

είναι μεγαλύτερο από ένα

και γιατί έχει το περιθώριο που τείνουμε πάντα να αφαιρούμε.

Αυτά τα στυλ είναι σημαντικά, αλλά οδηγούν επίσης σε ένα από τα μεγαλύτερα ζητήματα που αντιμετωπίζουν οι άνθρωποι με περιθώρια! Τα περιθώρια δεν είναι προεπιλεγμένα 0σε όλα τα στοιχεία μας και αυτό μπορεί να προκαλέσει κάθε είδους παράξενα ζητήματα τα οποία θα εξετάσουμε σύντομα.

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

Από προεπιλογή, τα αριστερά και δεξιά περιθώρια ενός στοιχείου κειμένου έχουν ρυθμιστεί σε 0, αλλά όλα έρχονται με ένα margin-topκαι margin-bottom.

Λέω συχνά στους ανθρώπους ότι αυτές οι προεπιλογές πάνω και κάτω είναι περίπου οι ίδιες με αυτές font-sizeτου στοιχείου, δεδομένου ότι ισχύει

καθώς

διά μέσου

. Για

είναι στην πραγματικότητα 0.67emκαι για

είναι 0.83em.

Αυτό σημαίνει ότι υπάρχει κενό μεταξύ των στοιχείων στη σελίδα μας, ακόμη και αν δεν έχουμε ορίσει ρητά ένα περιθώριο.

Θα επιστρέψουμε σε αυτές τις προεπιλογές σε ένα δευτερόλεπτο.

Σύμπτυξη περιθωρίων

Τα καταρρέοντα περιθώρια είναι εκεί όπου αρχίζουν συχνά οι πονοκέφαλοι.

Όταν δύο στοιχεία έχουν κάθετα περιθώρια που αγγίζουν το ένα το άλλο, συγχωνεύονται αποτελεσματικά το ένα με το άλλο.

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

Μπορούμε να το δούμε σε δράση με το ακόλουθο παράδειγμα:

p { font-size: 18px; margin-bottom: 40px; } .links { margin-top: 40px; } 

Για να δείξουμε τι συμβαίνει εδώ, το .linksμάθημα βρίσκεται στην τελευταία παράγραφο (

When people do something like this, they expect the margin between the middle paragraph and the links below it to be 80px (40px + 40px), but in reality, it's 40px. The two margins are touching each other, so they merge into one another.

Paragraph and links with 40px space between

To push it even more, let's give our

s' a  margin-bottom to 100px:

p { font-size: 18px; margin-bottom: 100px; } .links { margin-top: 40px; } 

Again, the two margins don't add together, they collapse into one another, so the total space here is 100px.

Paragraph and links with 100px space between

This is a good thing

In cases like this, it's actually a good thing, though. If there are several elements with different margins, there is no need to add the margins together to see how large the gap between the elements is because we can rely on the fact that the larger margin always wins.

We often don't even think about it, it just works the way we expect it to work.

When it's not a good thing

That said, one instance where margin collapse causes all sorts of confusion is when the first child within an element has a margin-top that merges with the parent's margin-top.

Let's look at that same screenshot again:

Paragraph and links with 100px space between

There is a white space between the top of the viewport and the black box. That's not from the body (it's much bigger than the 8px margin the body would have).

Care to guess where it's coming from?

It's actually coming from the

at the top of that black box.

Remember when I mentioned that the user-agent stylehsheets can do some odd things?

To help explain exactly what's happening here, let's add a much bigger margin-top to the h1.

.card { background: #000; color: white; width: 560px; margin: 0 auto; } h1 { font-size: 24px; margin-top: 100px; } p { font-size: 18px; margin-bottom: 100px; } .links { margin-top: 10px; } 

I see people do this all the time, trying to push the title down within its parent. However, rather than working as expected, we get a giant space on top of the entire card!

 h1 with collapsed margin

This is because the margin-top on the

merges with the margin-top on the parent element.

There is nothing separating the top of the child and the parent in this case. So when we add margin-top to the child, it touches the parent's margin-top. And, as we saw above, when two margins touch one another, they merge into a single margin.

So while we are giving the margin to the child, it's being applied to the parent.

This is why people hate CSS.

Similarly, in the code above we gave all paragraphs a margin-bottom. That margin on the p.link elements touches the margin-bottom of the .card element, which means that the two merge together and the margin affects the .card element instead of the links.

Card element with collapse margin

Although this isn't causing an issue for the site we are currently creating, it could cause problems if we later decided to add further elements to the page.

The problem is, we're using margin for the wrong purpose

If I want space between the top of the .card element and the children inside it, I shouldn't be using margin anyway.

Beginners often get mixed up between margin and padding. My general rule of thumb is if you want empty space, use margin. If you want more background, use padding.

In this case, we want our .card to have more background, so we shouldn't be adding a margin to its children. Instead we should add padding to that element itself.

Result of adding padding to the parent element

In the image above, we can see the padding and the margin. The

on top still has a margin, but it's no longer merging with the .card because the padding has added in a buffer. This prevents the .card's and h1 margin from touching one another.

As the padding adds sufficient space between the

s and the

s, we can now remove the margins we previously added to them.

Site with larger margin-bottom on last child element.

Margins don't always collapse

There are some exceptions to collapsing margins. The direct descendants of grid and flex parents do not have collapsing margins.

Cue the ?.

But there is a bit of a workaround for this as well, which brings us full circle back to those user agent-stylesheets we talked about at the start.

There is an easy way to avoid even thinking about collapsing margins

First off, there is my general rule of thumb that I talked about above:

  • If you need empty space, use margin
  • If you need more background, use padding

That will get you out of trouble most of the time. But let's add an extra rule to this that will help even more:

  • Try to avoid margin-top except when you really need it

This rule is in a bit of conflict with the user-agent-styles, which set a margin-top and margin-bottom to a bunch of elements, which is one reason I often will do something like this:

h1, h2, h3, h4, h5, h6, p, ul, ol { margin: 0 0 1em 0; }

It eliminates a lot of the issues that come from collapsing margins on their own, as well as differences in your layout when some places are using flex or grid and others are not.

(Note: if you inspect the code here on freeCodeCamp, you'll see they do something similar as well!)

It's not a perfect solution, and I often do use a little margin-top on certain subtitles or in specific situations where it's called for. But I'm doing it very intentionally instead of letting the user-agent-styles potentially get in the way in some unforeseen way.

These lessons are just a snippet of my much larger course on responsive web design. To continue this coding journey, take a look at the course.

In the course I cover an introduction to responsive web design, and dive into both flexbox and grid, all the while trying to show people how much fun CSS really is once you start to understand how it works.

Happy coding :)