White space is to be regarded as an active element, not a passive background.
– Jan Tschichold
Negative space is arguably the most important part of a visual composition.
Just as in music, the rests, breathing room, and headspace are the key players in rhythm. Without them, you just have noise. Similarly, negative space in design helps create the rhythm, contrast, and motion in a visual composition.
When creating visual rhythm on the web, margin and padding is the abstraction we use most commonly for negative space. Despite its importance in the overall composition, margin isn't usually treated as a declarative equal in component based architectures. And, because of this, it's difficult to determine whether white space belongs to the child component or the parent.
I sometimes like to think of an element’s whitespace as it's personal bubble. That is, different societies of humans have different distances at which they consider normal to keep when having a conversation. Some cultures have much smaller personal bubbles than Americans, and when people from these cultures visit or immigrate to the US, americans may feel uncomfortable with how close the other person is standing to them and unconsciously back away. Similarly, when Americans visit cultures with larger personal bubbles, the American is the one forcing others to back away.
Components obviously aren't people but they too can differ in the amount of whitespace they need, and create interesting dynamics among the different parts of a UI.
There are two predominant ways of handling whitespace in component based systems. The first involves components defining their own margins, which is how Rebass and Reflexbox provide margin props. The second involves a parent component wrapping child components with padded containers, similar to Hugo Bessa’s Spacing component. A third, but less common approach is Rebass‘s Space component, which declaratively creates space between other elements.
Let's explore the first method where a component defines its own margins.
Now let's take a look at the second method, where the parent defines margins of its children.
Lastly, let's explore a space component that declaratively adds space between components.
We can actually devise a system that allows for all of the approaches listed above. To start, we need a component that manages its own margin.
Each has its trade offs
Declarative spacer is verbose and can be cumbersome to manage efficiently. It also destroys a convenient aspect of CSS: margin collapsing
Parent spacer has its own limitations Similar to traditional CSS grid sys it doesn't allow for much flexibility