Apply Alignment and Proximity — the final two CRAP principles — to create organized, scannable interfaces using CSS Grid, Flexbox alignment properties, and deliberate spacing to group related information.
Alignment and Proximity are the two CRAP principles that govern spatial relationships in a layout. Alignment creates visual order — invisible lines that connect elements across the page. Proximity communicates relationships — elements near each other are perceived as related, elements far apart are seen as separate.
Together, Alignment and Proximity eliminate the need for most borders, dividers, and decorative separators. When elements are correctly aligned and correctly spaced relative to each other, the layout reads naturally without explicit visual barriers.
Alignment means placing elements so their edges or centers share the same invisible line. This creates visual order — users sense that things are deliberately placed, not randomly scattered.
Types of alignment:
CSS alignment implementation:
1/* Left-align everything by default */
2body {
3 text-align: left; /* inherits to all text */
4}
5
6/* Center only for hero headings with explicit max-width */
7.hero {
8 text-align: center;
9 max-width: 42rem; /* limits centered text to readable width */
10 margin-inline: auto;
11}
12
13/* Table numbers: right-aligned for column scanning */
14td.price, th.price {
15 text-align: right;
16 font-variant-numeric: tabular-nums; /* fixed-width numbers for alignment */
17}
18
19/* Flexbox alignment for component layouts */
20.card-header {
21 display: flex;
22 align-items: center; /* vertically centered elements on same line */
23 gap: 0.75rem;
24}
25
26/* Grid alignment for multi-column layouts */
27.course-grid {
28 display: grid;
29 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
30 /* All cards snap to the same column grid */
31}Alignment violations:
1/* BAD: Inconsistent left margins break alignment */
2.nav-item:first-child { margin-left: 24px; }
3.nav-item:nth-child(2) { margin-left: 20px; } /* 4px different = visible */
4
5/* BAD: Mixed text alignment in same section */
6.section-title { text-align: center; }
7.section-body { text-align: left; } /* jarring transition */
8
9/* GOOD: Consistent alignment throughout */
10.nav { padding-left: var(--space-6); } /* same token for all items */
11.section { text-align: left; } /* consistent throughout */Proximity is the spacing principle: related elements should be close together; unrelated elements should be far apart. Users infer relationships from spatial proximity.
Proximity applied to a form:
1<!-- BAD: All elements equidistant — no grouping clear -->
2<form>
3 <label>First name</label>
4 <input type="text">
5 <label>Last name</label>
6 <input type="text">
7 <label>Email</label>
8 <input type="email">
9 <label>Password</label>
10 <input type="password">
11 <button>Create account</button>
12</form>
13
14<!-- GOOD: Proximity groups label with its input -->
15<form class="form">
16 <div class="form-group"> <!-- label + input are a unit -->
17 <label class="form-label">First name</label>
18 <input class="form-input" type="text">
19 </div>
20 <div class="form-group">
21 <label class="form-label">Email</label>
22 <input class="form-input" type="email">
23 </div>
24 <button class="btn-primary">Create account</button>
25</form>1/* Proximity CSS: label and input close; form-groups far apart */
2.form {
3 display: flex;
4 flex-direction: column;
5 gap: var(--space-6); /* 24px between form groups (far apart = unrelated) */
6}
7
8.form-group {
9 display: flex;
10 flex-direction: column;
11 gap: var(--space-1); /* 4px between label and input (close = related) */
12}
13
14/* The 4px label-to-input gap vs 24px group-to-group gap */
15/* makes the relationship obvious without any borders */Proximity in card design:
1/* Card proximity: category + title are a unit; meta is separate */
2.card-body {
3 display: flex;
4 flex-direction: column;
5 padding: var(--space-4);
6}
7
8.card-category {
9 margin-bottom: var(--space-1); /* 4px — category tight to title */
10}
11
12.card-title {
13 margin-bottom: var(--space-4); /* 16px — title separated from meta */
14}
15
16.card-meta {
17 margin-bottom: var(--space-4); /* 16px — meta separated from CTA */
18 display: flex;
19 gap: var(--space-2);
20 color: var(--color-text-muted);
21}
22
23.card-cta {
24 margin-top: auto; /* CTA floats to bottom, maximum separation from meta */
25}Proximity rule: label-to-input gap should be 25-33% of the input-group-to-input-group gap. If groups are 24px apart, labels should be 4-8px from their inputs.
CSS Grid and Flexbox alignment properties implement the Alignment principle directly. Understanding which alignment property does what lets you implement design specs precisely.
Flex alignment cheat sheet:
1/* Horizontal axis (flex-direction: row) */
2.container {
3 display: flex;
4 justify-content: flex-start; /* align left (default) */
5 justify-content: center; /* align center */
6 justify-content: flex-end; /* align right */
7 justify-content: space-between; /* first item left, last right */
8 justify-content: space-evenly; /* equal space around items */
9}
10
11/* Vertical axis in row direction */
12.container {
13 align-items: flex-start; /* top-align all items */
14 align-items: center; /* vertically center (most common for navs) */
15 align-items: flex-end; /* bottom-align */
16 align-items: baseline; /* align text baselines (mixed font sizes) */
17 align-items: stretch; /* fill height (default) */
18}
19
20/* Individual item override */
21.logo { align-self: center; } /* center just the logo, not other items */
22.cta { align-self: flex-end; } /* push CTA to bottom in a vertical list */Grid alignment:
1.grid {
2 display: grid;
3 grid-template-columns: repeat(3, 1fr);
4 gap: var(--space-6);
5
6 /* Align items within cells */
7 align-items: start; /* align cell content to top */
8 justify-items: start; /* align cell content to left */
9}
10
11/* Cards in a grid: all titles align to the same horizontal line */
12.course-card {
13 display: flex;
14 flex-direction: column;
15}
16
17.course-card__body {
18 flex: 1; /* all card bodies same height = all CTAs aligned to bottom */
19}
20
21.course-card__cta {
22 margin-top: auto; /* pushes CTA to bottom regardless of content length */
23}Baseline alignment (for mixed type sizes in a row):
1.nav-item {
2 display: flex;
3 align-items: baseline; /* aligns 'Courses' at 16px with count '42' at 12px */
4}
5
6.nav-label { font-size: 1rem; }
7.nav-count {
8 font-size: 0.75rem;
9 /* Without baseline: count floats oddly relative to label */
10 /* With baseline: count aligns to same text bottom line as label */
11}One of the most powerful applications of Proximity is eliminating visual noise. When proximity is used correctly, borders and dividers are unnecessary because space itself communicates separation.
Divider removal process:
1/* BEFORE: Borders everywhere because spacing is not doing the work */
2.sidebar-section {
3 border-bottom: 1px solid #e5e7eb; /* needed because sections run together */
4 padding-bottom: 1rem;
5 margin-bottom: 1rem;
6}
7
8.nav-item {
9 border-bottom: 1px solid #e5e7eb;
10 padding: 0.75rem 0;
11}
12
13/* AFTER: Space does the separation — borders removed */
14.sidebar-section {
15 /* No border needed — whitespace separates */
16 padding-bottom: 0; /* gap handles spacing */
17}
18
19.sidebar {
20 display: flex;
21 flex-direction: column;
22 gap: var(--space-8); /* 32px between sections = clear separation */
23}
24
25.nav-list {
26 display: flex;
27 flex-direction: column;
28 gap: var(--space-1); /* 4px between items = clear grouping */
29}
30
31.nav-item { padding: 0.5rem 0.75rem; } /* no border needed */When borders ARE appropriate:
When to remove borders:
Proximity audit:
1For every border/divider in your CSS:
21. What is it separating?
32. Could the content on each side be given more whitespace instead?
43. If yes, remove the border and add whitespace
54. If the items are still unclear without the border, reconsider
6 whether they should even be on the same sectionBuilding a course card that uses alignment (all text left-aligned, grid-constrained) and proximity (labels tight to values, sections well-separated) without any borders.
1/* Course card layout using ONLY alignment and proximity */
2/* No borders, no dividers, no rules — space does the work */
3
4.course-card {
5 display: flex;
6 flex-direction: column;
7 border-radius: var(--radius-lg);
8 border: 1px solid var(--color-border); /* card border is OK for elevation */
9 background: white;
10 overflow: hidden;
11}
12
13.course-card__thumbnail {
14 width: 100%;
15 height: 10rem;
16 object-fit: cover;
17 display: block;
18}
19
20.course-card__body {
21 display: flex;
22 flex-direction: column;
23 padding: var(--space-4);
24 flex: 1;
25
26 /* PROXIMITY: internal padding creates breathing room */
27 /* ALIGNMENT: text-align: left inherited from body */
28}
29
30/* Category + Title: tight proximity — they are a unit */
31.course-card__category {
32 font-size: 0.75rem;
33 font-weight: 500;
34 color: var(--color-text-muted);
35 text-transform: uppercase;
36 letter-spacing: 0.05em;
37 margin-bottom: var(--space-1); /* 4px — very tight to title */
38}
39
40.course-card__title {
41 font-size: var(--text-lg); /* 18px */
42 font-weight: 600;
43 line-height: 1.4;
44 color: var(--color-text);
45 margin: 0 0 var(--space-3); /* 12px below title — more than category gap */
46 /* Creates: category → [4px] → title → [12px] → description */
47 /* The 4px vs 12px contrast makes category-title a unit */
48}
49
50.course-card__description {
51 font-size: 0.9375rem;
52 line-height: 1.6;
53 color: var(--color-text-muted);
54 margin: 0;
55 display: -webkit-box;
56 -webkit-line-clamp: 2;
57 -webkit-box-orient: vertical;
58 overflow: hidden;
59}
60
61/* Meta: separated from description by larger gap */
62.course-card__meta {
63 display: flex;
64 align-items: center; /* ALIGNMENT: baseline items in row */
65 gap: var(--space-3); /* 12px between meta items */
66 margin-top: var(--space-3); /* 12px from description */
67 font-size: 0.875rem;
68 color: var(--color-text-muted);
69}
70
71.course-card__meta-item {
72 display: flex;
73 align-items: center; /* ALIGNMENT: icon and text on same baseline */
74 gap: var(--space-1); /* 4px — icon tight to its label */
75}
76
77.course-card__meta-icon {
78 width: 1rem;
79 height: 1rem;
80 flex-shrink: 0;
81 color: inherit;
82}
83
84/* Price + CTA: maximally separated from content above */
85.course-card__footer {
86 display: flex;
87 align-items: center;
88 justify-content: space-between; /* price left, button right */
89 margin-top: auto; /* PROXIMITY: pushes footer to bottom = maximum separation */
90 padding-top: var(--space-3);
91 /* No border-top needed — margin-top: auto creates the separation */
92}
93
94.course-card__price {
95 font-size: var(--text-lg);
96 font-weight: 700;
97 color: var(--color-text);
98}
99
100.course-card__cta {
101 padding: var(--space-2) var(--space-4);
102 background-color: var(--color-action);
103 color: white;
104 font-size: 0.875rem;
105 font-weight: 600;
106 border-radius: var(--radius-md);
107 border: none;
108 cursor: pointer;
109 text-decoration: none;
110 display: inline-flex;
111 align-items: center;
112 transition: background-color var(--transition-base);
113}
114
115.course-card__cta:hover {
116 background-color: var(--color-action-hover);
117}The card uses proximity through deliberate gap sizing: category to title is 4px (they are one unit), title to description is 12px (slight separation), description to meta is 12px (same level), and the footer uses margin-top: auto (maximum separation — it is a different type of information: action). No borders are used inside the card — whitespace does all the separation. Text alignment is consistently left throughout, with the footer using justify-content: space-between to place price and button at opposite ends of the same horizontal alignment line.
The next lesson covers Visual Hierarchy Fundamentals — how to create clear page structure where users instantly know what to look at first, second, and third using all four CRAP principles together.
Your progress is saved in this browser, on this device only.