Apply design psychology principles — Hick's Law, Fitts's Law, cognitive load, progressive disclosure, and anchoring — to create interfaces that reduce friction, speed decision-making, and guide users toward intended actions.
Design psychology is the study of how human perception, cognition, and behavior interact with visual interfaces. Several well-established psychological principles directly affect how users interact with web interfaces — and knowing them gives developers and designers powerful tools for creating effective, ethical UIs.
These principles are not tricks. They describe how the human mind works and how design can either work with that natural functioning or against it. The goal is to reduce friction, speed comprehension, and guide users toward actions that serve their goals — not to manipulate users into actions they would not consciously choose.
Hick's Law states that the time to make a decision increases logarithmically with the number of choices. Double the options, add roughly 50% more decision time. Every unnecessary choice is friction.
Hick's Law in practice:
12 choices → 1 unit of decision time
24 choices → 2 units of decision time
38 choices → 3 units of decision time
416 choices → 4 units of decision timeApplications in UI design:
Navigation: limit top-level nav to 5-7 items:
1<!-- BAD: 12 nav items — too many decisions -->
2<nav>
3 <a>Courses</a><a>Guides</a><a>Blog</a><a>Podcast</a>
4 <a>Community</a><a>Tools</a><a>Resources</a><a>Events</a>
5 <a>Newsletter</a><a>About</a><a>Pricing</a><a>Contact</a>
6</nav>
7
8<!-- GOOD: 5 top-level items, group secondary in dropdowns -->
9<nav>
10 <a>Learn</a> <!-- courses + guides + blog -->
11 <a>Community</a> <!-- community + events -->
12 <a>Resources</a> <!-- tools + newsletter -->
13 <a>Pricing</a>
14 <a>About</a>
15</nav>Pricing tiers — the rule of three:
1<!-- 3 pricing tiers is optimal — more creates confusion -->
2<div class="pricing-grid">
3 <div class="plan-basic">Free</div>
4 <div class="plan-pro">Pro — recommended</div> <!-- highlight middle -->
5 <div class="plan-team">Team</div>
6</div>Form fields — only ask what is necessary:
1Registration form with 8 fields → LOW conversion
2 First name, Last name, Email, Password, Confirm password,
3 Job title, Company, Country
4
5Registration form with 3 fields → HIGH conversion
6 Email, Password, [Sign up]
7 (Everything else collected progressively after signup)Calls-to-action — one primary action per view:
1/* GOOD: One obvious primary action */
2.page-cta { /* one primary button */ }
3
4/* BAD: Multiple competing CTAs at same weight */
5.btn-primary { /* Enroll now */ }
6.btn-primary { /* Start free trial */ } /* competing = paralysis */
7.btn-primary { /* Book demo */ } /* three primaries = no primary */Fitts's Law states that the time to move to a target is a function of the distance to the target and the size of the target. Larger targets and closer targets are faster to click.
Fitts's Law formula (simplified):
1Time = a + b × log₂(Distance/Width + 1)
2Larger target → more accurate, faster
3Closer target → faster to reachPractical applications:
Minimum touch target size:
1/* Apple HIG: 44×44pt minimum, Google Material: 48×48dp minimum */
2.btn {
3 min-height: 2.75rem; /* 44px */
4 min-width: 2.75rem;
5 /* Interactive area >= 44px regardless of visual size */
6}
7
8/* Extending tap area for small icons without changing visual size */
9.icon-btn {
10 position: relative;
11 width: 1.5rem; /* 24px visual */
12 height: 1.5rem;
13 cursor: pointer;
14}
15
16/* Pseudo-element extends tap area to 44px */
17.icon-btn::before {
18 content: '';
19 position: absolute;
20 inset: -0.625rem; /* -10px extends 24+20=44px each dimension */
21}Positioning primary actions where fingers naturally rest:
1/* Mobile: primary action in bottom half — reachable with thumbs */
2.mobile-cta {
3 position: fixed;
4 bottom: 0;
5 left: 0;
6 right: 0;
7 padding: var(--space-4);
8 background: white;
9 border-top: 1px solid var(--color-border);
10 /* Bottom of screen = thumbs can reach without repositioning phone */
11}
12
13/* Desktop: primary action in upper-right or central — near mouse travel path */
14.desktop-cta {
15 /* Upper-right: near browser navigation tools (Fitts: targets near edges) */
16 /* Center: equal travel distance from all directions */
17}Spacing related buttons close together:
1/* Confirm + Cancel close together = both easy to reach from same position */
2/* Confirm + Cancel far apart = Cancel takes extra movement */
3.dialog-actions {
4 display: flex;
5 gap: var(--space-3); /* 12px gap — easy to move between options */
6 justify-content: flex-end;
7}
8
9/* Danger zone: put destructive actions FAR from confirmation (reverse Fitts) */
10.danger-section {
11 margin-top: var(--space-16); /* Far from main form — accidental clicks prevented */
12 padding: var(--space-6);
13 border: 1px solid var(--color-danger-subtle);
14 border-radius: var(--radius-lg);
15}Cognitive load is the mental effort required to use an interface. Interfaces with high cognitive load cause errors, abandonment, and frustration. Progressive disclosure reduces cognitive load by showing only what users need at each moment.
Types of cognitive load:
Reduce extraneous cognitive load with clear language:
1<!-- HIGH cognitive load: vague labels -->
2<input placeholder="Entry 1"> <!-- What does Entry 1 mean? -->
3
4<!-- LOW cognitive load: clear labels -->
5<label for="card-number">Card number</label>
6<input id="card-number" placeholder="4242 4242 4242 4242" inputmode="numeric">Progressive disclosure in forms:
1<!-- Initial form: minimum required information -->
2<form class="register-form">
3 <input type="email" placeholder="Email address">
4 <input type="password" placeholder="Create password">
5 <button type="submit">Create account</button>
6</form>
7
8<!-- Progressive disclosure: collect additional info AFTER signup -->
9<!-- Step 2 (post-signup): occupation, learning goals, experience level -->
10<!-- Step 3 (first lesson): preferences, notifications -->
11<!-- All spread across journey, not dumped at signup -->CSS for progressive disclosure:
1/* Advanced settings: hidden by default, revealed on click */
2.advanced-section {
3 display: grid;
4 grid-template-rows: 0fr;
5 transition: grid-template-rows var(--transition-slow);
6}
7
8.advanced-section[data-open='true'] {
9 grid-template-rows: 1fr;
10}
11
12.advanced-inner { overflow: hidden; }
13
14/* Toggle button */
15.advanced-toggle {
16 display: flex;
17 align-items: center;
18 gap: var(--space-2);
19 font-size: var(--text-sm);
20 color: var(--color-action);
21 background: none;
22 border: none;
23 cursor: pointer;
24 padding: 0;
25}
26
27.advanced-toggle-icon {
28 width: 1rem;
29 height: 1rem;
30 transition: transform var(--transition-base);
31}
32
33[data-open='true'] .advanced-toggle-icon {
34 transform: rotate(180deg); /* chevron rotates when open */
35}Anchoring: the first number seen establishes a reference point that influences subsequent judgments. In pricing design, anchoring makes the value of a plan feel better or worse based on what is shown first.
Anchoring in pricing:
1High anchor shown first:
2 $299/year → $99/year → $29/month
3 Users perceive $99 as a good deal relative to $299
4
5Low anchor shown first:
6 $29/month → $99/year → $299/year
7 Users compare $99 to $29 and see it as more expensive
8
9Recommendation: for annual plans, show monthly cost with annual label
10 'Pro: $8.25/month, billed $99/year'
11 Users anchor on the low monthly number, conversion is higherCSS for pricing with anchoring:
1/* Annual pricing: show monthly equivalent prominently */
2.price-display {
3 display: flex;
4 align-items: baseline;
5 gap: var(--space-1);
6}
7
8.price-currency {
9 font-size: var(--text-xl);
10 font-weight: 600;
11 color: var(--color-text);
12 line-height: 1;
13 margin-top: 0.375rem; /* optical alignment with main number */
14}
15
16.price-value {
17 font-size: 3rem; /* large anchor number */
18 font-weight: 700;
19 color: var(--color-text);
20 line-height: 1;
21}
22
23.price-period {
24 font-size: var(--text-sm);
25 color: var(--color-text-muted);
26 line-height: 1.4;
27}
28
29.price-annual-note {
30 font-size: var(--text-xs);
31 color: var(--color-text-muted);
32 margin-top: var(--space-1);
33}
34
35/* Strikethrough original price = savings anchor */
36.price-original {
37 font-size: var(--text-lg);
38 color: var(--color-text-muted);
39 text-decoration: line-through;
40 text-decoration-color: var(--color-danger);
41}
42
43.price-savings {
44 font-size: var(--text-sm);
45 font-weight: 600;
46 color: var(--color-success);
47 background-color: var(--color-success-subtle);
48 padding: 0.125rem 0.375rem;
49 border-radius: var(--radius-full);
50 display: inline-flex;
51 align-items: center;
52}
53
54/* Decoy effect: highlight the plan you want users to choose */
55.plan-card--featured {
56 border: 2px solid var(--color-action); /* visual emphasis */
57 transform: scale(1.03); /* slightly larger = more prominent */
58 box-shadow: 0 12px 32px rgb(37 99 235 / 0.15);
59}
60
61.plan-badge {
62 position: absolute;
63 top: -0.75rem;
64 left: 50%;
65 transform: translateX(-50%);
66 background-color: var(--color-action);
67 color: white;
68 font-size: var(--text-xs);
69 font-weight: 700;
70 text-transform: uppercase;
71 letter-spacing: 0.05em;
72 padding: 0.25rem 0.75rem;
73 border-radius: var(--radius-full);
74}Implementing the course enrollment section with Hick's Law (one decision), Fitts's Law (large target), anchoring (monthly equivalent), and progressive disclosure (show details on demand).
1/* Enrollment section: psychology-informed design */
2
3/* 1. HICK'S LAW: One clear primary action */
4.enrollment-card {
5 background: white;
6 border: 1px solid var(--color-border);
7 border-radius: var(--radius-xl);
8 padding: var(--space-6);
9 box-shadow: 0 4px 16px rgb(0 0 0 / 0.08);
10}
11
12/* 2. ANCHORING: Monthly equivalent price prominent */
13.price-block {
14 margin-bottom: var(--space-6);
15}
16
17.price-monthly {
18 display: flex;
19 align-items: baseline;
20 gap: var(--space-1);
21 margin-bottom: var(--space-1);
22}
23
24.price-monthly-currency { font-size: 1.25rem; font-weight: 600; }
25.price-monthly-value { font-size: 3rem; font-weight: 700; line-height: 1; }
26.price-monthly-label { font-size: 0.875rem; color: var(--color-text-muted); }
27
28.price-annual {
29 font-size: 0.875rem;
30 color: var(--color-text-muted);
31}
32
33.price-original {
34 text-decoration: line-through;
35 text-decoration-color: var(--color-danger);
36 margin-right: var(--space-2);
37}
38
39.price-save {
40 font-size: 0.75rem;
41 font-weight: 600;
42 color: var(--color-success);
43 background: var(--color-success-subtle);
44 padding: 0.125rem 0.5rem;
45 border-radius: var(--radius-full);
46}
47
48/* 3. FITTS'S LAW: Full-width, large-height CTA */
49.enroll-btn {
50 display: flex;
51 align-items: center;
52 justify-content: center;
53 width: 100%; /* full width = maximum horizontal target size */
54 min-height: 3.25rem; /* 52px — well above 44px minimum */
55 padding: 0.875rem;
56 background-color: var(--color-action);
57 color: white;
58 font-size: 1.0625rem;
59 font-weight: 600;
60 border: none;
61 border-radius: var(--radius-lg);
62 cursor: pointer;
63 transition: background-color var(--transition-base), transform var(--transition-fast);
64 margin-bottom: var(--space-3);
65}
66
67.enroll-btn:hover {
68 background-color: var(--color-action-hover);
69 transform: translateY(-1px); /* subtle lift on hover */
70}
71
72.enroll-btn:active {
73 transform: translateY(0); /* press effect */
74}
75
76/* 4. PROGRESSIVE DISCLOSURE: What is included? */
77.includes-summary {
78 font-size: var(--text-sm);
79 color: var(--color-text-muted);
80 text-align: center;
81 margin-bottom: var(--space-4);
82}
83
84.includes-toggle {
85 display: flex;
86 align-items: center;
87 justify-content: center;
88 gap: var(--space-1);
89 font-size: var(--text-sm);
90 color: var(--color-action);
91 background: none;
92 border: none;
93 cursor: pointer;
94 padding: 0;
95 width: 100%;
96 margin-bottom: var(--space-3);
97}
98
99.includes-detail {
100 display: grid;
101 grid-template-rows: 0fr;
102 transition: grid-template-rows var(--transition-slow);
103}
104
105.includes-detail[data-open='true'] {
106 grid-template-rows: 1fr;
107}
108
109.includes-inner {
110 overflow: hidden;
111 font-size: var(--text-sm);
112}
113
114.includes-list {
115 list-style: none;
116 padding: var(--space-3) 0 0;
117 margin: 0;
118 display: flex;
119 flex-direction: column;
120 gap: var(--space-2);
121}
122
123.includes-item {
124 display: flex;
125 align-items: center;
126 gap: var(--space-2);
127 color: var(--color-text);
128}
129
130.includes-check {
131 color: var(--color-success);
132 flex-shrink: 0;
133 width: 1rem;
134 height: 1rem;
135}
136
137/* 5. COGNITIVE LOAD reduction: guarantee below CTA */
138.guarantee-text {
139 font-size: var(--text-xs);
140 color: var(--color-text-muted);
141 text-align: center;
142 margin-top: var(--space-4);
143 display: flex;
144 align-items: center;
145 justify-content: center;
146 gap: var(--space-1);
147}The enrollment card applies all four psychology principles: Hick's Law is honored by having exactly one primary action (Enroll) — the secondary actions (gift, try free) are not present in this implementation. Fitts's Law: the enroll button is full-width and 52px tall — the largest feasible target on the card. Anchoring: the large font-size monthly price ($8.25) is shown prominently, with the annual billing note ($99/year, was $199) shown smaller below — the low monthly anchor anchors perception before the annual cost is seen. Progressive disclosure: the 'What is included?' section starts hidden and expands on demand — reducing the cognitive load of the initial view.
The next lesson covers Balance, Harmony, and Unity — the compositional principles that make layouts feel stable, organized, and aesthetically satisfying without requiring formal design training.
Your progress is saved in this browser, on this device only.