Skip to content

Commit e7d7dfd

Browse files
Add margin-trim Article
1 parent 00acf05 commit e7d7dfd

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
const { isTrimmed } = Astro.props
3+
---
4+
5+
<style>
6+
* {
7+
box-sizing: border-box;
8+
}
9+
10+
.card {
11+
padding: 1em;
12+
background-color: var(--theme-text);
13+
border: 1px solid var(--theme-bg);
14+
border-radius: 1rem;
15+
max-width: 30rem;
16+
margin: 0 auto;
17+
}
18+
19+
.child {
20+
margin-bottom: 2rem;
21+
color: var(--theme-bg);
22+
}
23+
24+
.card.trim :last-child {
25+
margin-bottom: 0;
26+
}
27+
</style>
28+
29+
<div class={`card ${isTrimmed ? "trim" : ""}`}>
30+
<div class="child">Child 1</div>
31+
<div class="child">Child 2</div>
32+
<div class="child">Child 3</div>
33+
</div>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
layout: "@layouts/BlogPost.astro"
3+
title: "New CSS Property margin-trim"
4+
date: "2023-12-11"
5+
description: "The new CSS property margin-trim is very simple, but incredibly useful when working in a component based design system."
6+
tags: ["CSS"]
7+
---
8+
9+
import MarginTrimCard from "@blogComponents/marginTrim/MarginTrimCard.astro"
10+
11+
One of the most annoying things to deal with in CSS is margins. They have weird interactions with collapsing and more often than not you end up with extra spacing where you don't want it. This becomes an even larger pain when moving to a component based design system since now you need to ensure your components all work well with each other without leaking styles outside themselves.
12+
13+
The new `margin-trim` property helps solve part of this problem by making it very easy to remove extra margin from the children of an element.
14+
15+
## The Problem
16+
17+
Let's say we have a simple card with a list of children inside it.
18+
19+
```html
20+
<div class="card">
21+
<div class="child">Child 1</div>
22+
<div class="child">Child 2</div>
23+
<div class="child">Child 3</div>
24+
</div>
25+
```
26+
27+
```css
28+
.card {
29+
background-color: var(--accent-color);
30+
padding: 1rem;
31+
}
32+
33+
.child {
34+
margin-bottom: 2rem;
35+
}
36+
```
37+
38+
This will result in the following:
39+
40+
<MarginTrimCard />
41+
42+
As you can see, the bottom margin of the last child is forcing the card to have extra
43+
space on the bottom which makes the card taller than it should be. This is relatively
44+
easy to fix if we change our CSS by using the `:last-child` selector to remove the
45+
margin from the last child.
46+
47+
```css
48+
.child {
49+
margin-bottom: 1rem;
50+
}
51+
52+
.child:last-child {
53+
margin-bottom: 0;
54+
}
55+
```
56+
57+
This will result in the following:
58+
59+
<MarginTrimCard isTrimmed />
60+
61+
This works, but it is not ideal since this code does not work well in a component based system. Our child component needs to know that the parent component wants to remove margin from it. This is not ideal since it means that the child component is now coupled to the parent component. We could instead write our CSS like this to make it so the parent component handles everything.
62+
63+
```css
64+
.card {
65+
background-color: var(--accent-color);
66+
padding: 1rem;
67+
}
68+
69+
.card > :last-child {
70+
margin-bottom: 0;
71+
}
72+
```
73+
74+
This still isn't ideal, though, since now we are selecting elements outside the parent component which breaks the encapsulation of the component. This is where the `margin-trim` property comes in.
75+
76+
## `margin-trim` Solution
77+
78+
The `margin-trim` property is a very simple property that allows you to specify which edges of an element should be trimmed and it will remove all excess spacing from those edges. This means that we can now write our CSS like this:
79+
80+
```css {4}
81+
.card {
82+
background-color: var(--accent-color);
83+
padding: 1rem;
84+
margin-trim: block-end;
85+
}
86+
87+
.child {
88+
margin-bottom: 1rem;
89+
}
90+
```
91+
92+
This will result in the following:
93+
94+
<MarginTrimCard isTrimmed />
95+
96+
As you can see, the `margin-trim` property removed the extra margin from the bottom of the card without us needing to write any extra CSS.
97+
98+
This property can be used for any of the 4 directions `block-start`, `block-end`, `inline-start`, and `inline-end`. It can also be used with just `block` or `inline` to remove margin from both the start and end of the specified axis.
99+
100+
```css
101+
.card {
102+
/* All these assume the direction is left to right, top to bottom */
103+
margin-trim: block; /* Removes from top and bottom */
104+
margin-trim: inline; /* Removes from left and right */
105+
margin-trim: block-start block-end; /* Removes from top and bottom */
106+
margin-trim: inline-start; /* Removes from left */
107+
}
108+
```
109+
110+
By using `margin-trim` we are able to keep all our CSS inside the component without the need for any complex children selectors or `:last-child` selectors which makes it much easier to maintain and refactor our code.
111+
112+
## Browser Support
113+
114+
Unfortunately, Safari is the only browser that supports this feature which leads to just [14% support](https://caniuse.com/mdn-css_properties_margin-trim) across all browsers at the time of writing this article. Hopefully, in the coming months/years this number will increase as more browsers support this useful property.
115+
116+
## Conclusion
117+
118+
The `margin-trim` property is a very simple, but incredibly useful property that makes it easy to remove extra margin from the children of an element. This makes it easier to work with components in a component based design system since you no longer need to worry about parent/child components leaking styles outside themselves.

0 commit comments

Comments
 (0)