Wszystko, co musisz wiedzieć o marżach CSS

Opublikowany: 2022-03-10
Szybkie podsumowanie ↬ Marginesy w CSS na pierwszy rzut oka wydają się dość proste. Nałożony na element tworzy przestrzeń wokół elementu, odpychając inne elementy. Jednak margines jest większy, niż mogłoby się wydawać.

Jedną z pierwszych rzeczy, których większość z nas nauczyła się, gdy uczyliśmy się CSS, były szczegóły różnych części pudełka w CSS, opisane jako Model pudełka CSS. Jednym z elementów modelu Box jest margines, przezroczysty obszar wokół pudełka, który odsunie inne elementy od zawartości pudełka. Właściwości margin-top , margin-right , margin-bottom i margin-left zostały opisane w CSS1, wraz ze skróconym margin do ustawienia wszystkich czterech właściwości jednocześnie.

Margines wydaje się być dość nieskomplikowaną rzeczą, jednak w tym artykule przyjrzymy się niektórym rzeczom, które potykają ludzi w kwestii korzystania z marginesów. W szczególności przyjrzymy się, w jaki sposób marże współdziałają ze sobą i jak faktycznie działa zwijanie marży.

Model pudełka CSS

Podobnie jak w przypadku wszystkich artykułów o częściach modelu CSS Box, powinniśmy zdefiniować, co przez to rozumiemy i jak model został wyjaśniony w wersjach CSS. Model pudełka odnosi się do tego, jak różne części pudełka — zawartość, wypełnienie, obramowanie i margines — są ułożone i współdziałają ze sobą. W CSS1 model pudełkowy został szczegółowo opisany za pomocą diagramu graficznego ASCII pokazanego na poniższym obrazku.

rysunek sztuki ascii modelu pudełka
Przedstawienie modelu pudełkowego CSS w CSS1

Cztery właściwości marginesów dla każdej strony pudełka i skróty margin zostały zdefiniowane w CSS1.

Specyfikacja CSS2.1 zawiera ilustrację demonstrującą model pudełkowy, a także definiuje terminy, których wciąż używamy do opisywania różnych pudełek. Specyfikacja opisuje content box padding box border box i margin box , z których każdy jest zdefiniowany odpowiednio przez krawędzie zawartości, dopełnienie, obramowanie i margines.

diagram Modelu Pudełkowego CSS
Detekcja modelu pudełkowego CSS w CSS2

Istnieje teraz specyfikacja modelu pudełkowego poziomu 3 jako wersja robocza. Ta specyfikacja odnosi się do CSS2 dla definicji modelu pudełkowego i marginesów, dlatego to właśnie definicja CSS2 będziemy używać w większości tego artykułu.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Zapadanie się marginesu

Specyfikacja CSS1, ponieważ określała marginesy, określała również, że pionowe marginesy się zwijają . To upadające zachowanie jest od tego czasu źródłem frustracji związanej z marżą. Zwijanie marginesów ma sens, jeśli weźmie się pod uwagę, że w tamtych czasach CSS był używany jako język formatowania dokumentów. Zwijanie się marginesów oznacza, że ​​gdy po nagłówku z dolnym marginesem następuje akapit z górnym marginesem, nie powstaje duża przerwa między tymi elementami.

Kiedy marginesy się zwijają, połączą się tak, że przestrzeń między dwoma elementami stanie się większa z dwóch marginesów. Mniejszy margines zasadniczo kończy się wewnątrz większego.

Marginesy zapadają się w następujących sytuacjach:

  • Przylegające rodzeństwo
  • Całkowicie puste pudełka
  • Rodzic i pierwszy lub ostatni element podrzędny

Przyjrzyjmy się po kolei każdemu z tych scenariuszy, zanim przyjrzymy się rzeczom, które zapobiegają załamywaniu się marż w tych scenariuszach.

Przylegające rodzeństwo

Mój wstępny opis zapadania się marginesów jest demonstracją tego, jak zapadają się marginesy między sąsiednim rodzeństwem. Poza sytuacjami wymienionymi poniżej, jeśli masz dwa elementy wyświetlane jeden po drugim w normalnym przepływie, dolny margines pierwszego elementu zostanie zwinięty z górnym marginesem następnego elementu.

W poniższym przykładzie CodePen są trzy elementy div . Pierwszy ma górny i dolny margines o wielkości 50 pikseli. Drugi ma górny i dolny margines 20px. Trzeci ma górny i dolny margines 3em. Margines między pierwszymi dwoma elementami wynosi 50 pikseli, ponieważ mniejszy margines górny jest połączony z większym marginesem dolnym. Margines między drugimi dwoma elementami w 3em, ponieważ 3em jest większy niż 20 pikseli na dole drugiego elementu.

Zobacz pióro [Marginesy: sąsiednie rodzeństwo](https://codepen.io/rachelandrew/pen/OevMPo) Rachel Andrew.

Zobacz Marginesy pióra: sąsiednie rodzeństwo autorstwa Rachel Andrew.

Całkowicie puste pudełka

Jeśli pole jest puste, jego górny i dolny margines mogą się ze sobą zwinąć. W poniższym przykładzie CodePen element z klasą empty ma margines górny i dolny równy 50 pikseli, jednak odstęp między pierwszym a trzecim elementem nie wynosi 100 pikseli, ale 50. Jest to spowodowane załamaniem się dwóch marginesów. Dodanie czegokolwiek do tego pola (nawet dopełnienia) spowoduje, że marginesy górny i dolny będą używane i nie będą się zwijać.

Zobacz pióro [Marginesy: puste pola](https://codepen.io/rachelandrew/pen/JQLGMr) Rachel Andrew.

Zobacz Marginesy pióra: puste pudełka autorstwa Rachel Andrew.

Element nadrzędny i pierwszy lub ostatni element potomny

Jest to scenariusz załamywania się marży, który najczęściej łapie ludzi, ponieważ nie wydaje się szczególnie intuicyjny. W poniższym CodePen mam div z klasą wrappera i nadałem temu div outline na czerwono, aby można było zobaczyć, gdzie on jest. Wszystkie trzy elementy podrzędne mają margines 50 pikseli. Jednak pierwszy i ostatni element są równo z krawędziami opakowania; między elementem a opakowaniem nie ma marginesu 50 pikseli.

Zobacz pióro [Marginesy: margines na pierwsze i ostatnie dziecko](https://codepen.io/rachelandrew/pen/BgrKGp) Rachel Andrew.

Zobacz marginesy pióra: margines na pierwsze i ostatnie dziecko autorstwa Rachel Andrew.

Dzieje się tak dlatego, że margines na dziecku zapada się wraz z każdym marginesem na rodzicu, co kończy się na zewnątrz rodzica. Możesz to zobaczyć, sprawdzając pierwsze dziecko za pomocą DevTools. Podświetlony żółty obszar to margines.

Element z podświetlonym na żółto marginesem widocznym na zewnątrz rodzica
DepvTools może pomóc Ci zobaczyć, gdzie kończy się Twoja marża

Tylko blokowe marginesy Zwiń

Ostatni przykład pokazuje również coś na temat zapadania się marży. W CSS2 do zwinięcia określone są tylko pionowe marginesy — to znaczy górny i dolny margines elementu, jeśli jesteś w trybie pisania poziomego. Tak więc lewy i prawy margines powyżej nie zapadają się i nie kończą poza opakowaniem.

Uwaga : Warto pamiętać, że marginesy zwijają się tylko w kierunku bloku, na przykład między akapitami.

Rzeczy, które zapobiegają załamywaniu się marginesu

Marginesy nigdy nie zwijają się, jeśli element ma pozycjonowanie bezwzględne lub jest pływający. Jednak zakładając, że natknąłeś się na jedno z miejsc, w których marginesy się zapadają, jak opisano powyżej, jak możesz powstrzymać te marginesy?

Pierwszą rzeczą, która przestaje się zapadać, są sytuacje, w których coś znajduje się między elementami, o których mowa.

Na przykład, pole całkowicie pozbawione zawartości nie zwinie swojego górnego i dolnego marginesu, jeśli ma obramowanie lub zastosowane wypełnienie. W poniższym przykładzie dodałem 1px wypełnienia do pudełka. Nad i pod ramką znajduje się teraz 50-pikselowy margines.

Zobacz pióro [Marginesy: puste pola z wypełnieniem się nie zwijają](https://codepen.io/rachelandrew/pen/gNeMpg) autorstwa Rachel Andrew.

Zobacz marginesy pióra: puste pudełka z wyściółką nie zapadają się przez Rachel Andrew.

Ma to za sobą logikę, jeśli pudełko jest całkowicie puste bez obramowania lub wypełnienia, jest w zasadzie niewidoczne. Może to być pusty element akapitu wrzucony do znacznika przez Twój CMS. Jeśli Twój CMS dodaje zbędne elementy akapitu, prawdopodobnie nie chciałbyś, aby powodowały duże odstępy między innymi akapitami ze względu na ich marginesy. Dodaj cokolwiek do pudełka, a otrzymasz te luki.

Podobne zachowanie można zaobserwować w przypadku marginesów pierwszego lub ostatniego dziecka, które zapadają się przez rodzica. Jeśli dodamy obramowanie do rodzica, marginesy na dzieciach pozostaną w środku.

Zobacz pióro [Marginesy: margines na pierwszym i ostatnim dziecku nie zwija się, jeśli rodzic ma obramowanie](https://codepen.io/rachelandrew/pen/vqRKKX) autorstwa Rachel Andrew.

Zobacz marginesy pióra: margines na pierwszym i ostatnim dziecku nie zapada się, jeśli rodzic ma obramowanie autorstwa Rachel Andrew.

Po raz kolejny jest pewna logika w zachowaniu. Jeśli masz owijające elementy w celach semantycznych, które nie wyświetlają się wizualnie, prawdopodobnie nie chcesz, aby wprowadzały duże przerwy w wyświetlaniu. Miało to sens, gdy sieć składała się głównie z tekstu. Jest mniej przydatny jako zachowanie, gdy używamy elementów do rozplanowania projektu.

Tworzenie kontekstu formatowania bloku

Nowy kontekst formatowania bloku (BFC) zapobiegnie również zwijaniu marginesów przez element zawierający. Jeśli ponownie przyjrzymy się przykładowi pierwszego i ostatniego dziecka, które kończy się z ich marginesami poza opakowaniem i display: flow-root , tworząc w ten sposób nowy BFC, marginesy pozostaną w środku.

Zobacz pióro [Margins: nowy kontekst formatowania bloków zawiera marginesy](https://codepen.io/rachelandrew/pen/VJXjEp) autorstwa Rachel Andrew.

Zobacz marginesy pióra: nowy kontekst formatowania bloków zawiera marginesy autorstwa Rachel Andrew.

Aby dowiedzieć się więcej o display: flow-root , przeczytaj mój artykuł „Zrozumienie układu CSS i kontekstu formatowania bloków”. Zmiana wartości właściwości overflow na auto będzie miała ten sam efekt, ponieważ powoduje to również utworzenie nowego BFC, chociaż może również tworzyć paski przewijania, których nie chciałeś w niektórych scenariuszach.

Pojemniki elastyczne i siatkowe

Kontenery Flex i Grid ustanawiają konteksty formatowania Flex i Grid dla swoich elementów podrzędnych, dzięki czemu zachowują się inaczej przy blokowaniu układu. Jedną z tych różnic jest to, że marże się nie zapadają:

„Kontener flex ustanawia nowy kontekst formatowania flex dla swojej zawartości. Jest to to samo, co ustanawianie kontekstu formatowania blokowego, z wyjątkiem tego, że zamiast układu blokowego używany jest układ flex. Na przykład pływaki nie wchodzą do kontenera elastycznego, a marginesy kontenera elastycznego nie zapadają się wraz z marginesami jego zawartości”.

— Flexbox Poziom 1

Jeśli weźmiemy powyższy przykład i przekształcimy opakowanie w kontener flex, wyświetlając elementy za pomocą flex-direction: column , możesz zobaczyć, że marginesy są teraz zawarte w opakowaniu. Ponadto marginesy między sąsiednimi elementami elastycznymi nie zapadają się względem siebie, więc w efekcie otrzymujemy 100 pikseli między elementami elastycznymi, czyli łącznie 50 pikseli na górze i na dole elementów.

Zobacz pióro [Marginesy: marginesy na elementach elastycznych nie zwijają się](https://codepen.io/rachelandrew/pen/mZxreL) autorstwa Rachel Andrew.

Zobacz marginesy pióra: marginesy na elementach elastycznych nie zapadają się przez Rachel Andrew.

Strategie marży dla Twojej witryny

Ze względu na zapadanie się marży warto wymyślić spójny sposób radzenia sobie z marżami w witrynie. Najprostszą rzeczą do zrobienia jest zdefiniowanie tylko marginesów na górze lub na dole elementów. W ten sposób nie powinieneś zbyt często natrafiać na problemy ze zwijaniem marginesów, ponieważ strona z marginesem zawsze będzie sąsiadować ze stroną bez marginesu.

Uwaga : Harry Roberts ma doskonały post, w którym szczegółowo opisuje powody, dla których ustawianie marginesów tylko w jednym kierunku jest dobrym pomysłem, a nie tylko ze względu na rozwiązywanie problemów z zapadającymi się marginesami.

To rozwiązanie nie rozwiązuje problemów, które możesz napotkać z marginesami na dzieci, które załamują się przez rodzica. Ten konkretny problem jest zwykle mniej powszechny, a wiedza o tym, dlaczego się dzieje, może pomóc w znalezieniu rozwiązania. Idealnym rozwiązaniem jest zapewnienie display: flow-root , jako rozwiązanie awaryjne dla starszych przeglądarek można użyć overflow do utworzenia BFC, zmienić rodzica w kontener flex, a nawet wprowadzić pojedynczy piksel wypełnienia. Nie zapominaj, że możesz używać zapytań o funkcje do wykrywania obsługi display: flow-root , dzięki czemu tylko stare przeglądarki uzyskują mniej optymalne rozwiązanie.

Przez większość czasu uważam, że kluczowa jest wiedza o tym, dlaczego marginesy się załamują (lub nie). Możesz wtedy dowiedzieć się, jak sobie z tym poradzić w każdym przypadku. Cokolwiek wybierzesz, udostępnij te informacje swojemu zespołowi. Dość często zapadanie się marginesu jest nieco tajemnicze, więc powód robienia rzeczy, aby temu przeciwdziałać, może być nieoczywisty! Komentarz w Twoim kodzie jest bardzo pomocny — możesz nawet zamieścić link do tego artykułu i pomóc podzielić się wiedzą na temat zapadania się marginesów.

Pomyślałem, że podsumuję ten artykuł kilkoma innymi informacjami dotyczącymi marży.

Marże procentowe

Kiedy używasz procentu w CSS, musi to być procent czegoś. Marginesy (i dopełnienie) ustawione za pomocą wartości procentowych zawsze będą stanowić procent rozmiaru wbudowanego (szerokość w trybie pisania poziomego) rodzica. Oznacza to, że podczas używania wartości procentowych będziesz mieć dopełnienie o jednakowej wielkości na całym obwodzie elementu.

W poniższym przykładzie CodePen, mam opakowanie o szerokości 200 pikseli, w środku jest pudełko z marginesem 10%, margines wynosi 20 pikseli ze wszystkich stron, czyli 10% z 200.

Zobacz pióro [Margines: marginesy procentowe](https://codepen.io/rachelandrew/pen/orqzrP) autorstwa Rachel Andrew.

Zobacz Marginesy pióra: marginesy procentowe autorstwa Rachel Andrew.

Marginesy w świecie zależnym od przepływów

W tym artykule mówiliśmy o marginesach pionowych, jednak współczesny CSS ma tendencję do myślenia o rzeczach w sposób względny, a nie fizyczny. Dlatego kiedy mówimy o marginesach pionowych, tak naprawdę mówimy o marginesach w wymiarze blokowym. Marginesy te będą górne i dolne, jeśli jesteśmy w trybie pisania poziomego, ale będą prawe i lewe w trybie pisania pionowego pisane od lewej do prawej.

Po pracy z logicznymi kierunkami względnymi przepływu łatwiej jest mówić o początku bloku i końcu bloku, a nie o górze i dole. Aby to ułatwić, CSS wprowadził specyfikację Logical Properties and Values. Te mapy przenoszą względne właściwości na fizyczne.

W przypadku marginesów daje nam to następujące mapowania (jeśli pracujemy w języku angielskim lub innym trybie pisania poziomego z kierunkiem tekstu od lewej do prawej).

  • margin-top = margin-block-start
  • margin-right = margin-inline-end
  • margin-bottom = margin-block-end
  • margin-left = margin-inline-start

Mamy również dwa nowe skróty, które pozwalają na ustawienie obu bloków naraz lub obu w linii.

  • margin-block
  • margin-inline

W następnym przykładzie CodePen użyłem tych słów kluczowych związanych z przepływem, a następnie zmieniłem tryb pisania pola, możesz zobaczyć, jak marginesy podążają za kierunkiem tekstu, a nie są powiązane z fizycznym górnym, prawym, dolnym i lewym.

Zobacz pióro [Margins: przepływ względne marginesy](https://codepen.io/rachelandrew/pen/BgrQRj) autorstwa Rachel Andrew.

Zobacz Marginesy pióra: względne marginesy przepływu autorstwa Rachel Andrew.

Możesz przeczytać więcej o logicznych właściwościach i wartościach w MDN lub w moim artykule „Understanding Logical Properties and Values” tutaj w Smashing Magazine.

Owinąć

Wiesz już większość tego, co trzeba wiedzieć o marżach! W skrócie:

  • Zapadanie się marży to rzecz. Zrozumienie, dlaczego tak się dzieje, a kiedy nie, pomoże Ci rozwiązać wszelkie problemy, jakie może powodować.
  • Ustawienie marginesów tylko w jednym kierunku rozwiązuje wiele problemów związanych z marginesami.
  • Jak w przypadku wszystkich elementów CSS, dziel się ze swoim zespołem decyzjami, które podejmujesz i komentuj swój kod.
  • Myślenie o wymiarach blokowych i śródliniowych, a nie o fizycznym górnym, prawym, dolnym i lewym, pomoże ci, gdy sieć będzie dążyć do bycia niezależnym od trybu pisania.