Wszystko, co musisz wiedzieć o marżach CSS
Opublikowany: 2022-03-10 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.
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.
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.
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.
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ć.
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.
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.
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.
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.
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.
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.
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.
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.
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.