Lesson 08 / 24
Navigation Models
Comparing hierarchical, flat, and matrix navigation; computing the trade-off between menu width and depth, and how reorientation cost shifts the best width.
Contents
Card sorting produced five groups and group names. This is not yet a navigation. How many of the groups are shown at once, how many levels the sub-breakdowns descend, and how many steps a user needs to reach an item are separate decisions, and they depend on each other: as the menu narrows the tree deepens, and as it widens the tree shallows.
This lesson distinguishes three navigation models, then computes the trade-off between depth and width with a cost model. The result is not a rule of the “a menu should have seven items” kind, but a computation that gives which width is cheapest under which condition.
Three Models
Hierarchical navigation places items in nested groups. The user starts at the root, makes a choice at each level, and descends to a leaf. This is the catalog interface’s subject tree. Its strength is that it reduces the options at every level; its weakness is that the hierarchy imposes a single order — the question of subject-first or material-type-first must have one answer, and the user pays a cost if the order in their mind differs.
Flat navigation shows all items at a single level. There is no depth, the user never gets lost, everything is one step away. It does not scale: as the item count grows, scanning cost grows linearly.
Matrix navigation gives access to the same items from multiple independent axes. If a record in the catalog interface can be reached both by subject and by material type, matrix navigation is present. Its strength is that the user can pick their own axis; its cost is that each axis needs separate maintenance.
The Trade-off Between Width and Depth
With the number of leaf nodes fixed in a tree, menu width and depth are inversely
proportional: with width b and leaf count N, depth is approximately log_b N. As
width grows, the items to read at each level grow; as depth shrinks, page changes and
reorientation shrink. Which width is cheaper depends on the ratio between these two costs.
// depth-and-width.mjs — the trade-off between menu width and depth const N = 1000; // number of leaf nodes to reach const REORIENT = 1.2; // page change and reorientation per level (seconds) const ITEM = 0.12; // reading one menu item (seconds) const depth = (b) => Math.ceil(Math.log(N) / Math.log(b)); console.log(`N = ${N} leaf nodes, ${REORIENT} s reorientation per level, ${ITEM} s reading per item`); console.log("width depth items scanned total time"); let best = { b: 0, time: Infinity }; for (const b of [2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 20, 32, 64]) { const d = depth(b); const time = d * (REORIENT + ITEM * b); if (time < best.time) best = { b, time }; console.log( `${String(b).padStart(5)} ${String(d).padStart(5)} ${String(b * d).padStart(13)} ${time.toFixed(2).padStart(10)} s` ); } console.log(`\nsmallest time: width ${best.b}, ${best.time.toFixed(2)} s`); // Which width would be chosen if only the number of items scanned were measured let fewestItems = { b: 0, items: Infinity }; for (let b = 2; b <= 64; b++) { const t = b * depth(b); if (t < fewestItems.items) fewestItems = { b, items: t }; } console.log(`if only items scanned were measured: width ${fewestItems.b}, ${fewestItems.items} items`); // How the best width shifts as reorientation cost changes console.log("\nreorientation per level best width depth time"); for (const s of [0.0, 0.4, 1.2, 3.0, 6.0]) { let top = { b: 0, time: Infinity, d: 0 }; for (let b = 2; b <= 64; b++) { const d = depth(b), time = d * (s + ITEM * b); if (time < top.time) top = { b, time, d }; } console.log( `${s.toFixed(1).padStart(23)} ${String(top.b).padStart(10)} ${String(top.d).padStart(5)} ${top.time.toFixed(2)} s` ); }
N = 1000 leaf nodes, 1.2 s reorientation per level, 0.12 s reading per item
width depth items scanned total time
2 10 20 14.40 s
3 7 21 10.92 s
4 5 20 8.40 s
5 5 25 9.00 s
6 4 24 7.68 s
7 4 28 8.16 s
8 4 32 8.64 s
10 3 30 7.20 s
12 3 36 7.92 s
16 3 48 9.36 s
20 3 60 10.80 s
32 2 64 10.08 s
64 2 128 17.76 s
smallest time: width 10, 7.20 s
if only items scanned were measured: width 2, 20 items
reorientation per level best width depth time
0.0 2 10 2.40 s
0.4 4 5 4.40 s
1.2 10 3 7.20 s
3.0 10 3 12.60 s
6.0 32 2 19.68 s
Three results emerge.
The best width depends on the metric. If only the number of items scanned were counted, the binary menu would win: twenty items are read, the smallest value in the table. But ten levels must be descended, and each level carries a reorientation cost. When duration is measured, the binary menu becomes one of the most expensive options: 14.40 seconds.
Total time is a flat curve. Between width 6 and 12, time stays between 7.20 and 7.92 seconds. Within this range, the choice belongs not to the computation but to other constraints: how many items fit on a narrow screen, the length of group names, the natural number of groups that came out of card sorting. The computation does not decide; it says within which range the decision is free.
If reorientation is expensive, the menu widens. If per-level reorientation were zero, the best width would be 2; it rises to 10 at 1.2 seconds and to 32 at 6.0 seconds. The design equivalent of this is a direct rule: if page transitions are slow, if the user’s place in the list is lost during a transition, or if the user has to reorient at every level, a deep tree becomes expensive and the menu is widened. Conversely, if the level transition is instant and context is preserved, a deep tree is cheap.
This connects directly to a phenomenon measured in the fourth lesson: in our interface, the search state is not preserved on return. The state not being preserved raises the reorientation cost, and the higher reorientation cost makes depth more expensive. The same flaw bills twice, in two separate places.
The User’s Axis and the Menu’s Axis
The order the hierarchy imposes produces a measurable cost. The catalog collection can be classified along two axes: twenty-four subject headings and five material types.
// navigation-models.mjs — scanning cost of flat, hierarchical, and matrix navigation const TOPIC = 24; // number of subject headings const TYPE = 5; // number of material types const LEAVES = TOPIC * TYPE; // 120 leaf nodes const BACKTRACK = 1; // back step after starting on the wrong axis // Average scan: half the list is read before the target is found const flat = LEAVES / 2; const matched = TOPIC / 2 + TYPE / 2; // the user's axis matches the menu's axis const mismatched = TOPIC + TYPE / 2 + BACKTRACK; // user thinks in type first, menu starts with topic const matrix = TOPIC / 2 + TYPE / 2; // user starts from their own axis console.log(`collection: ${TOPIC} topics x ${TYPE} types = ${LEAVES} leaf nodes`); console.log("\nmodel entry points steps to leaf avg items scanned"); console.log(`${"flat".padEnd(18)} ${String(LEAVES).padStart(13)} ${String(1).padStart(14)} ${flat.toFixed(1).padStart(19)}`); console.log(`${"hierarchical".padEnd(18)} ${String(TOPIC).padStart(13)} ${String(1).padStart(14)} ${"variable".padStart(19)}`); console.log(`${"matrix".padEnd(18)} ${String(TOPIC + TYPE).padStart(13)} ${String(2).padStart(14)} ${matrix.toFixed(1).padStart(19)}`); console.log("\nin the hierarchical model, does the user's axis match the menu"); console.log(` matches : ${matched.toFixed(1)} items`); console.log(` does not match: ${mismatched.toFixed(1)} items`); console.log("\nshare thinking by type axis hierarchical matrix gap"); for (const p of [0, 0.1, 0.2, 0.3, 0.4, 0.5]) { const h = matched * (1 - p) + mismatched * p; console.log( `${p.toFixed(2).padStart(28)} ${h.toFixed(2).padStart(12)} ${matrix.toFixed(2).padStart(6)} ${(h - matrix).toFixed(2)}` ); } // The matrix's cost: both axes must cover every leaf node console.log("\nmatrix's maintenance load"); console.log(` links to maintain on the topic axis : ${LEAVES}`); console.log(` links to maintain on the type axis : ${LEAVES}`); console.log(` links to maintain in the hierarchy : ${LEAVES}`); console.log(` matrix total : ${2 * LEAVES} (${((2 * LEAVES) / LEAVES).toFixed(1)}x)`);
collection: 24 topics x 5 types = 120 leaf nodes
model entry points steps to leaf avg items scanned
flat 120 1 60.0
hierarchical 24 1 variable
matrix 29 2 14.5
in the hierarchical model, does the user's axis match the menu
matches : 14.5 items
does not match: 27.5 items
share thinking by type axis hierarchical matrix gap
0.00 14.50 14.50 0.00
0.10 15.80 14.50 1.30
0.20 17.10 14.50 2.60
0.30 18.40 14.50 3.90
0.40 19.70 14.50 5.20
0.50 21.00 14.50 6.50
matrix's maintenance load
links to maintain on the topic axis : 120
links to maintain on the type axis : 120
links to maintain in the hierarchy : 120
matrix total : 240 (2.0x)
Flat navigation makes the user scan an average of sixty items out of one hundred twenty; hierarchy and matrix, fourteen and a half. This shows that grouping itself saves more than a quarter, and it gives flat navigation’s limit: it is good up to a few dozen items, not at hundreds.
The difference between hierarchy and matrix depends on how many users think along the menu’s axis. If everyone thinks by subject, the gap is zero. If a fifth think by material type, the hierarchy is 2.6 items more expensive; if half do, 6.5 items. The matrix’s gain is not a fixed advantage but a gain directly proportional to the rate of axis mismatch.
This rate is not estimated, it is measured. The card-sorting data from the previous lesson exists exactly for this: whichever axis the participants grouped the cards along is navigation’s primary axis.
The matrix’s cost is in the last block: because every leaf node sits on both axes, the number of links to maintain doubles. This is not a runtime cost but a maintenance cost. When a new subject heading is added, both axes must be updated, and if one axis falls out of date, the same content shows two different realities in two different places. Matrix navigation is for teams that can commit to keeping two navigations consistent.
The Model’s Limits
The calculations above rest on two assumptions, and both must be stated explicitly.
First, it is assumed that the user scans the menu start to finish and recognizes the right item. In reality the user sometimes does not recognize the right item: someone looking for “interlibrary loan” may not think to enter the “borrowing operations” group. In this case the cost is not scanning but entering the wrong branch and backtracking, and it is not in the model.
Second, the search box was not accounted for. In an interface where search exists, navigation is not the only path; some users search without ever entering a menu. Navigation structure is still needed: search serves those who know what they are looking for, navigation serves those who do not. The Subject Browser persona built in the second lesson is exactly in the second group.
Summary
- Hierarchical navigation reduces the options at every level but imposes a single order; flat navigation does not scale; matrix navigation gives access from multiple axes.
- Width and depth are inversely proportional, and the best width depends on the metric: a narrow menu wins if the number of items scanned is minimized, a wide menu wins if duration is minimized.
- In the sample model, total time stays flat between width 6 and 12; the computation does not decide, it says within which range the decision is free.
- As per-level reorientation cost rises, the best width grows; flaws such as state not being preserved make reorientation more expensive and, with it, deep trees.
- The matrix’s advantage over the hierarchy is proportional to how many users think outside the menu’s axis, and its cost is that the number of links to maintain doubles.
Next Step
Navigation structure explains how items are reached, but not the decisions inside a task. The act of borrowing is not a single click: membership is verified, the record’s status is checked, a reservation is offered if it’s checked out, and the transaction stops if the member has an overdue book. When these branches are described in prose, which state connects to which gets lost. The next lesson builds the flow as a graph and searches for two flaws by computation: a state unreachable from the start, and a node with no exit.
To keep your progress and take notes, Log in
My notes
Log in to take notes.