Ako pochopiť a pracovať s okrajmi CSS

CSS dostane zlý rap za to, že sa nespráva tak, ako to ľudia očakávajú. Jednou z vecí, ktorá ľudí vyhadzuje najviac, sú marže. Vyzerajú tak jednoducho, napriek tomu majú potenciál spôsobiť skutočne podivné problémy.

Pre ľudí, ktorí sa práve dostanú do CSS, je to jedna z vecí, ktoré vás môžu prinútiť myslieť si: „toto je hlúpy jazyk, ktorý nemá zmysel!“

Vidím to každý deň - ako v triede, keď sa ľudia snažia prísť na svoje problémy s medzerami, tak aj v mojich sekciách s komentármi na YouTube.

Svojím spôsobom sú marže všeobecne trochu mikrokozmom CSS. CSS sa zdá byť so svojimi property: valuepármi taký jednoduchý , ale keď s ním budete postupovať, uvedomíte si, že sa toho deje naozaj veľa.

Okraje sa tiež zdajú také jednoduché. Pridajte trochu a okolo tohto prvku pridáte nejaké prázdne miesto. Ale potom sa zrazu v jednej situácii správajú trochu inak ako v inej, alebo ak nejaké pridáte margin-topk podradenému prvku, namiesto toho sa posúva nadol rodič.

Nasleduje frustrácia.

Dúfam, že v tomto článku vrhnem trochu svetla na to, ako fungujú rezervy. Pozrime sa na niektoré bežné problémy, ktoré sa vyskytnú, ako aj na jednoduché riešenia týchto problémov.

Aby som to všetko prešiel, použijem príklady z môjho Bootcampu s responzívnym webovým dizajnom na Scrimbe, z ktorého som vytiahol toto jednoduché rozloženie:

Rozloženie CSS pomocou okrajov a výplne

Čo sú vlastne marže?

Predtým, ako tu skutočne skočíme do hlbokého konca, chcem sa ubezpečiť, že všetci vieme, čo sú vlastne marže!

Budem predpokladať, že všetci vieme, že okraje sú súčasťou škatuľového modelu, pričom okraje sú úplne navonok a prichádzajú za samotný obsah, výplň a orámovanie.

MDN ich vysvetľuje naozaj dobre (dôraz môj):

Okraj je najvzdialenejšia vrstva, ktorá obalí obsah, výplň a orámovanie ako medzery medzi týmto rámčekom a ostatnými prvkami . Jeho veľkosť je možné ovládať pomocou okraja a súvisiacich vlastností.

Inými slovami, je to skutočne prázdny priestor, ktorý môžeme použiť na vytvorenie priestoru medzi jedným poľom a druhým v našom rozložení.

Zaoberanie sa šablónami štýlov user-agent

Prehliadače majú predvolene prekvapivé množstvo CSS, ktoré nazývame štýly štýlov user-agent . Tieto štýly sú dôvodom, že bez akýchkoľvek CSS z našej strany,

je väčšie ako

, a prečo má na sebe rezervu, ktorú máme tendenciu vždy odstraňovať.

Tieto štýly sú dôležité, ale tiež vedú k jednej z najväčších problémov, s ktorými sa ľudia stretávajú s okrajmi! Okraje predvolene neobsahujú 0všetky naše prvky, čo môže spôsobiť najrôznejšie podivné problémy, ktoré čoskoro preskúmame.

Zoznamy, blokové úvodzovky, odseky a nadpisy, ktoré všetky obsahujú margin(okrem iných prvkov). Aj keď to niekedy predstavuje len malú nepríjemnosť, zdá sa, že predvolená marža odsekov a nadpisov je tá, ktorá spôsobuje väčšinu problémov po vybalení z krabice.

V predvolenom nastavení je ľavý a pravý okraj textového prvku nastavený na hodnotu 0, ale všetky majú znak margin-topa margin-bottom.

Často hovorím ľuďom, že tieto predvolené hodnoty pre hornú a dolnú časť sú zhruba rovnaké ako font-sizepre daný prvok, pretože to platí pre

ako aj

cez

. Pre

je to vlastne 0.67ema pre

to je 0.83em.

To znamená, že medzi prvkami na našej stránke existuje priestor, aj keď sme výslovne nenastavili okraj.

K týmto predvoleným nastaveniam sa vrátime za chvíľu.

Kolapsové marže

Bolestivé okraje sú miesta, kde bolesti hlavy často začínajú.

Keď majú dva prvky zvislé okraje, ktoré sa navzájom dotýkajú, efektívne sa spájajú do seba.

Je to už čudné správanie, a potom ho prirátam k tomu, že je to iba pre zvislé okraje (hore a dole), a dostanem dôvod, prečo sú ľudia z nich zmätení a mrzutí.

Môžeme to vidieť v akcii na nasledujúcom príklade:

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

.linksKurz sa nachádza v poslednom odseku, aby ilustroval, čo sa tu deje, (

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 :)