blog

git clone https://git.ce9e.org/blog.git

commit
4fb09ca7203f0e03ab6ed40f7f798257f68e8890
parent
63b317a6f02ca42712995a97c840bd128c42f2b9
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-04-24 12:02
add post on margin collapsing

Diffstat

A _content/posts/2024-04-24-margin-collapsing/01-defaults-combined.png 0
A _content/posts/2024-04-24-margin-collapsing/02-bottom-combined.png 0
A _content/posts/2024-04-24-margin-collapsing/03-top-combined.png 0
A _content/posts/2024-04-24-margin-collapsing/05-flex-combined.png 0
A _content/posts/2024-04-24-margin-collapsing/index.md 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

5 files changed, 154 insertions, 0 deletions


diff --git a/_content/posts/2024-04-24-margin-collapsing/01-defaults-combined.png b/_content/posts/2024-04-24-margin-collapsing/01-defaults-combined.png

Binary files differ.

diff --git a/_content/posts/2024-04-24-margin-collapsing/02-bottom-combined.png b/_content/posts/2024-04-24-margin-collapsing/02-bottom-combined.png

Binary files differ.

diff --git a/_content/posts/2024-04-24-margin-collapsing/03-top-combined.png b/_content/posts/2024-04-24-margin-collapsing/03-top-combined.png

Binary files differ.

diff --git a/_content/posts/2024-04-24-margin-collapsing/05-flex-combined.png b/_content/posts/2024-04-24-margin-collapsing/05-flex-combined.png

Binary files differ.

diff --git a/_content/posts/2024-04-24-margin-collapsing/index.md b/_content/posts/2024-04-24-margin-collapsing/index.md

@@ -0,0 +1,154 @@
   -1     1 ---
   -1     2 title: What is the best approach for margins in body text?
   -1     3 date: 2024-04-24
   -1     4 tags: [css]
   -1     5 description: By default, browsers add margins both at the top and bottom of elements, which results in excessive whitespace in padded boxes. Is there a better way?
   -1     6 ---
   -1     7 
   -1     8 By default, browsers add margins both at the top and bottom of elements. That
   -1     9 is not a problem because [adjacent borders
   -1    10 collapse](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_box_model/Mastering_margin_collapsing).
   -1    11 
   -1    12 However, as we can see in the screenshot below, margins do not collapse when
   -1    13 there is a border or padding, which results in excessive whitespace in padded
   -1    14 boxes.
   -1    15 
   -1    16 ```css
   -1    17 h2 {
   -1    18   margin-block: 1.5em 1rem;
   -1    19 }
   -1    20 p, ul {
   -1    21   margin-block: 1em;
   -1    22 }
   -1    23 ```
   -1    24 
   -1    25 ![Screenshot: browser defaults](01-defaults-combined.png)
   -1    26 
   -1    27 ## Margins on the bottom
   -1    28 
   -1    29 In 2012, [Harry
   -1    30 Roberts](https://csswizardry.com/2012/06/single-direction-margin-declarations/)
   -1    31 proposed that you should only apply margins in one direction, preferably the
   -1    32 bottom. The argument was that margin collapsing is a bit of complexity we just
   -1    33 don't need.
   -1    34 
   -1    35 This is the general rule I currently use and that is also employed in popular
   -1    36 frameworks such as bootstrap. Of course there are exceptions: Headings need a
   -1    37 top margin.
   -1    38 
   -1    39 For the problem with the padding, Harry recommends to use the `:first-child`
   -1    40 and `:last-child` selectors. [Chris
   -1    41 Coyier](https://css-tricks.com/spacing-the-bottom-of-modules/) added that there
   -1    42 might also be a margin on the last child of the last child (and so on), so you
   -1    43 have to do a little more work then that.
   -1    44 
   -1    45 All put together, you end up with code like this:
   -1    46 
   -1    47 ```css
   -1    48 h2 {
   -1    49   margin-block: 1.5em 1rem;
   -1    50  }
   -1    51 p, ul {
   -1    52   margin-block: 0 1em;
   -1    53 }
   -1    54 > :first-child {
   -1    55   margin-block-start: 0;
   -1    56 }
   -1    57 > :last-child {
   -1    58   margin-block-end: 0;
   -1    59 }
   -1    60 ```
   -1    61 
   -1    62 ![Screenshot: Margin on the bottom](02-bottom-combined.png)
   -1    63 
   -1    64 ## Margins between elements
   -1    65 
   -1    66 In 2014, [Heydon
   -1    67 Pickering](https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/)
   -1    68 proposed that margins should not be defined on elements, but between elements.
   -1    69 This can be done by using the adjacent sibling combinator and top margins. The
   -1    70 code could look something like this:
   -1    71 
   -1    72 ```css
   -1    73 h2, p, ul {
   -1    74   margin-block: 0;
   -1    75 }
   -1    76 * + h2 {
   -1    77   margin-block-start: 1.5em;
   -1    78 }
   -1    79 * + p,
   -1    80 * + ul {
   -1    81   margin-block-start: 1em;
   -1    82 }
   -1    83 ```
   -1    84 
   -1    85 ![Screenshot: Margins between elements](03-top-combined.png)
   -1    86 
   -1    87 One benefit of this approach is that it keeps very low specificity, which is an important property for base styles.
   -1    88 
   -1    89 On the other hand, I am not convinced that the basic premise is even correct.
   -1    90 Note how there is no margin between the list items in the second list (the one
   -1    91 that contains paragraphs). The visual hierarchy is off here because the margin
   -1    92 inside of the list items creates a bigger separation than the list items
   -1    93 themselves.
   -1    94 
   -1    95 You could argue that the list should be in charge of adding margins here. But
   -1    96 the list doesn't know whether it contains paragraphs or not. So maybe just
   -1    97 looking at siblings isn't enough.
   -1    98 
   -1    99 I really like this approach. But because of its limitations I currently only
   -1   100 use it in some special cases, e.g. top borders on headings.
   -1   101 
   -1   102 ## flex gap
   -1   103 
   -1   104 The previous approaches are both 10 years old. A lot has happened in the
   -1   105 meantime, so more options have become available. Specifically, I sometimes hear
   -1   106 people say that we should use the `gap` property instead of margins. That could
   -1   107 look something like this:
   -1   108 
   -1   109 ```css
   -1   110 .container {
   -1   111   display: flex;
   -1   112   flex-direction: column;
   -1   113   gap: 1em;
   -1   114 }
   -1   115 
   -1   116 h2 {
   -1   117   margin-block: calc(1.5em - 1rem) 0;
   -1   118 }
   -1   119 p, ul {
   -1   120   margin-block: 0;
   -1   121 }
   -1   122 ```
   -1   123 
   -1   124 ![Screenshot: flex gap](05-flex-combined.png)
   -1   125 
   -1   126 While I love `gap`, I am not 100% convinced it is the right approach in this
   -1   127 case. Since it only adds space between elements, it has some of the same issues
   -1   128 as the previous approach. Also note how the paragraphs inside list elements do
   -1   129 not have any margins because the flex styling is only applied to the box
   -1   130 itself.
   -1   131 
   -1   132 ## margin-trim
   -1   133 
   -1   134 In 2023,
   -1   135 [Apple](https://developer.apple.com/videos/play/wwdc2023/10121/?time=240)
   -1   136 proposed a new CSS attribute called `margin-trim` that is supposed to finally
   -1   137 fix the problem for good. This would indeed be nice, but so far there seems to
   -1   138 be little interest from other vendors.
   -1   139 
   -1   140 ## Conclusion
   -1   141 
   -1   142 I had already done all the screenshots when I realized I should have included a
   -1   143 nested list. That is another case that frequently produces unexpected results.
   -1   144 At least I was able to include it in the
   -1   145 [codepen](https://codepen.io/xi-the-bashful/pen/qBwgrjB) I used for all the
   -1   146 examples.
   -1   147 
   -1   148 It is still hard (impossible?) to produce base styles that just work out of the
   -1   149 box for every kind of content and at the same time don't make it extremely
   -1   150 complicated to overwrite them for custom components.
   -1   151 
   -1   152 If we have to live with some edge cases, I feel like excessive margins at the
   -1   153 bottom are more acceptable than excessive margins at the top or missing
   -1   154 margins. So I will stick with the bottom margin approach for now.