Како разумети и радити са ЦСС маргинама

ЦСС се лоше оглашава јер се не понаша онако како људи очекују. Једна од ствари која људе највише баца су маргине. Изгледају тако једноставно, али имају потенцијал да изазову неке заиста чудне проблеме.

За људе који тек улазе у ЦСС то је лако једна од ствари због којих можете помислити „ово је глуп језик који нема смисла!“

Видим то свакодневно - и у учионици док људи покушавају да открију проблеме са размаком, као и у одељцима за моје коментаре на ИоуТубе-у.

На неки начин, марже су помало микрокосмос ЦСС-а уопште. ЦСС делује тако једноставно са својим property: valueпаровима, али како напредујете са њим, схватате да се много тога догађа.

Марже се такође чине тако једноставним. Додајте мало маргине и додаћете празан простор око тог елемента. Али онда се одједном у једној ситуацији понашају мало другачије од друге, или додате неки margin-topелементу дете, а уместо тога родитељ се помера надоле.

Настаје фрустрација.

Надам се да ћу у овом чланку осветлити како функционишу марже. Размотрићемо неке од уобичајених проблема који се дешавају, као и једноставна решења тих проблема.

Да бих прешао преко свега овога, користићу примере из мог Респонсиве Веб Десигн Боотцампа на Сцримби, из којег сам извукао овај једноставан изглед:

ЦСС распоред помоћу маргина и подлога

Шта су уопште марже?

Пре него што овде заиста ускочимо у дубину, желим да се уверим да сви знамо које су заправо марже!

Претпоставићу да сви знамо да су маргине део оквира модела, с тим што је маргина споља скроз, а долази после самог садржаја, попуњавања и обруба.

МДН их заиста добро објашњава (нагласак је мој):

Маргина је најудаљенији слој, који омотава садржај, попуњавање и обрубе као размак између овог оквира и других елемената . Његова величина се може контролисати помоћу маргине и сродних својстава.

Другим речима, то је ефективно празан простор који можемо користити за стварање простора између једне и друге кутије у нашем распореду.

Суочавање са табелама стилова корисничког агента

Прегледачи подразумевано имају изненађујућу количину ЦСС-а, који називамо табелама стилова корисничког агента . Ови стилови су разлог што, без икаквог ЦСС-а са наше стране, ан

је већи од

, и зашто знак има маргину коју обично уклањамо.

Ови стилови су важни, али доводе и до једног од највећих проблема на које људи наилазе с маргинама! Маргине се не подразумевају за 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 :)