Skip to content
academia.sh

Lesson 10 / 22

Screen Size and Input Type

Input type as a variable independent of screen width; auditing target size criteria, the spacing exception, and hit area expansion by computation.

Contents

The previous lesson treated width as the only variable and computed how the layout changes with width. But a narrow viewport is not only narrow. Input type often changes with it too: the finger takes the place the pointer left, target size gets redefined, and pointer-dependent interactions lose their counterpart.

The Density Decisions lesson found that the 33-pixel record row passed the lowest target threshold but fell short of the enhanced one. This lesson computes those thresholds by criterion number, tests the icon buttons in the catalog record row, and derives the cost of the fix.

Input Type Is Independent of Screen Size

Input modality specifies the precision with which the user reaches the interface — by touch, pointer, or keyboard. The common assumption is that a narrow screen means touch and a wide screen means pointer. This assumption breaks in three places: wide touch surfaces, pointer-driven sessions in a window shrunk to a narrow size, and devices that carry both. Moreover, input type can change within a session; a user can work with a finger for one minute and a pointer the next on the same screen.

Two design rules follow from this:

  • Sizing decisions are made for the coarsest input. Every interactive area is a touch target, and its size is set to the value touch requires; a pointer-driven user is not harmed by a large target.
  • Capability decisions are made by feature detection, not by width. Whether hover is supported cannot be inferred from screen width; it is tested with the relevant media feature.

Target Size Criteria

There are two criteria, and both are measured in CSS pixels. WCAG 2.5.8 requires a target’s smallest side to be 24 pixels; 2.5.5 raises the same measure to 44 pixels. The first has a spacing exception: even if a target is smaller than 24 pixels, the criterion is considered satisfied as long as the 24-pixel-diameter circles drawn on each target’s bounding box do not intersect.

The program below generates the four icon buttons on the right side of the catalog record row under three separate sizing decisions and audits both criteria.

// 10-target.mjs — target size, spacing exception, and the cost of expanding the hit area

const MIN = 24; // WCAG 2.5.8 Target Size (Minimum)
const ENHANCED = 44; // WCAG 2.5.5 Target Size (Enhanced)

// The four icon buttons on the right side of the catalog record row.
// Icon 16px, padding on both sides, GAP of space between buttons.
function buttonRow(icon, padding, gap, count, startX) {
  const side = icon + 2 * padding;
  const buttons = [];
  for (let i = 0; i < count; i++) {
    buttons.push({
      name: `button-${i + 1}`,
      x: startX + i * (side + gap),
      y: 0,
      w: side,
      h: side,
    });
  }
  return buttons;
}

function center(d) {
  return { x: d.x + d.w / 2, y: d.y + d.h / 2 };
}
function centerDistance(a, b) {
  const ca = center(a);
  const cb = center(b);
  return Math.hypot(ca.x - cb.x, ca.y - cb.y);
}

function audit(name, buttons) {
  console.log(name);
  const smallestSide = Math.min(...buttons.map((d) => Math.min(d.w, d.h)));
  console.log(`  button size: ${buttons[0].w}x${buttons[0].h}px   button count: ${buttons.length}`);
  console.log(`  2.5.8 (>= ${MIN}px): ${smallestSide >= MIN ? "passes" : "fails"}`);
  console.log(`  2.5.5 (>= ${ENHANCED}px): ${smallestSide >= ENHANCED ? "passes" : "fails"}`);

  // Spacing exception: 24px-diameter circles drawn at each target's center must not
  // intersect, meaning the distance between two centers must be at least 24px.
  let closest = Infinity;
  for (let i = 0; i < buttons.length; i++) {
    for (let j = i + 1; j < buttons.length; j++) {
      closest = Math.min(closest, centerDistance(buttons[i], buttons[j]));
    }
  }
  console.log(
    `  closest two centers: ${closest}px   spacing exception: ${closest >= MIN ? "passes" : "fails"}`
  );
  console.log("");
}

audit("A) icon 16, padding 4, gap 4", buttonRow(16, 4, 4, 4, 0));
audit("B) icon 16, padding 2, gap 2", buttonRow(16, 2, 2, 4, 0));
audit("C) icon 16, padding 14, gap 4", buttonRow(16, 14, 4, 4, 0));

// Expanding the hit area to 44px without changing the visual size
const visual = 24;
const growth = (ENHANCED - visual) / 2;
console.log("expanding the hit area to 44px without changing the visual size");
console.log(`  to add on each side: ${growth}px`);
for (const gap of [4, 12, 20, 24]) {
  const remainingSpace = gap - 2 * growth;
  console.log(
    `  button gap ${String(gap).padStart(2)}px -> hit areas ` +
      `${remainingSpace >= 0 ? `${remainingSpace}px apart` : `${-remainingSpace}px overlap`}`
  );
}

// If the entire row is the target: the effect of a 44px row height on scan cost
console.log("");
const LIST_AREA = 640;
console.log("records per screen if the entire row is the target");
for (const row of [33, 44, 73]) {
  const records = Math.floor(LIST_AREA / row);
  console.log(
    `  row ${String(row).padStart(3)}px -> ${String(records).padStart(2)} records/screen   ` +
      `${Math.ceil(200 / records)} screens for 200 results`
  );
}
A) icon 16, padding 4, gap 4
  button size: 24x24px   button count: 4
  2.5.8 (>= 24px): passes
  2.5.5 (>= 44px): fails
  closest two centers: 28px   spacing exception: passes

B) icon 16, padding 2, gap 2
  button size: 20x20px   button count: 4
  2.5.8 (>= 24px): fails
  2.5.5 (>= 44px): fails
  closest two centers: 22px   spacing exception: fails

C) icon 16, padding 14, gap 4
  button size: 44x44px   button count: 4
  2.5.8 (>= 24px): passes
  2.5.5 (>= 44px): passes
  closest two centers: 48px   spacing exception: passes

expanding the hit area to 44px without changing the visual size
  to add on each side: 10px
  button gap  4px -> hit areas 16px overlap
  button gap 12px -> hit areas 8px overlap
  button gap 20px -> hit areas 0px apart
  button gap 24px -> hit areas 4px apart

records per screen if the entire row is the target
  row  33px -> 19 records/screen   11 screens for 200 results
  row  44px -> 14 records/screen   15 screens for 200 results
  row  73px ->  8 records/screen   25 screens for 200 results

All three sizing decisions carry the same 16-pixel icon; only the padding creates the difference. Decision A stops at exactly 24 pixels with 4 pixels of padding and passes the lowest threshold. Decision B drops to 20 pixels with 2 pixels of padding and fails both criteria. Decision C rises to 44 pixels with 14 pixels of padding and passes both.

The only variable between them is a value that never appears on screen. Padding is the transparent area around the icon; the user does not see it, and notices its existence only when they touch it. Target size is therefore not a visual decision, it is an invisible one, and it cannot be audited by eye.

What the Spacing Exception Saves

In decision B, button size dropped to 20 pixels, and the criterion failed. Could the spacing exception have saved this case? The output says no: the closest two centers are 22 pixels apart, and 24 is required. The exception is not satisfied either.

The arithmetic is interesting. In decision B, the buttons are 20 pixels wide with 2 pixels between them; the distance between centers is 22 pixels. For the exception to pass, either the button has to grow to at least 22 pixels or the gap between them has to be at least 4 pixels. The second route is cheaper: at the same visual size, the criterion is satisfied with just 2 more pixels of gap.

This shows what the spacing exception is for. The exception does not exist to legitimize small targets; it exists to say that the space between targets is part of the target size. Two small buttons standing side by side make each other risky; a small button standing alone does not. The criterion rewards isolation.

The Hidden Cost of Expanding the Hit Area

A common solution is to expand the hit area without changing the visual size: the button looks 24 pixels but is clickable across 44. The output’s second block gives this solution’s hidden cost.

Going from 24 pixels to 44 pixels adds 10 pixels on every side. If the gap between buttons is 4 pixels, two neighboring buttons’ hit areas overlap by 16 pixels: which button a touch in the overlapping region goes to is something the design cannot say. At a 12-pixel gap, 8 pixels of overlap still remain. Separation is achieved only at a 20-pixel gap.

The conclusion is this: the hit area cannot be expanded without also expanding the gap. The promise of gaining touch ease while keeping the visual size fixed goes unanswered when neighboring targets exist. On a button standing alone — the “Borrow” button in the record detail view, for instance — the promise holds, because there is no neighbor to collide with.

If the Entire Row Is the Target

In the catalog results list, what is clickable is most often not the individual icons but the entire record row. In that case, target size is directly the row height, and it ties to the same number as the density decision.

The output’s last block shows the link. The compact layout’s 33-pixel row shows 19 records on screen, and 200 results are scanned in 11 screens. When the row is raised to the enhanced threshold of 44 pixels, 14 records remain on screen and scanning rises to 15 screens — four more screens. In the balanced layout’s 73-pixel row, the cost is 25 screens.

This confirms that the trade-off in the Density Decisions lesson depends on input type. The same list can be scanned in 11 screens with a 33-pixel row in a pointer-driven session; in a touch-driven session, holding the enhanced threshold raises it to 15 screens. The difference is 36 percent, and the design has to either accept it or resolve it with a target other than the row — for instance, making only the record title the target instead of the entire row, and raising the title’s own height to the threshold.

Pointer-Dependent Interaction Has No Counterpart

Beyond size, there is also a difference in capability. A pointer reports a position, and this position is known even without a click; touch does not produce such a position. Anything that appears under hover either never appears in a touch-driven session, or appears only after the target has been touched.

A constraint follows from this: hover cannot be the only channel that carries information. If the icon buttons in a record row appear only on hover, a touch-driven user cannot know they exist. In the same way, if an abbreviation’s expansion or a shelf code’s meaning is given only in a tooltip, that information does not exist for one set of users.

The legitimate use of hover is reinforcement: emphasizing the clickability of something already visible, making a label already written more prominent. Whether the capability exists is read not from screen width but from the relevant media feature; the hover and pointer media features query this distinction directly, and a pointer: coarse value reports a coarse-resolution input. Sizing decisions should not be tied to this query: target size is set for the coarsest input under every condition, because input type can change within a session.

Summary

  • Input type cannot be derived from screen width; sizing decisions are made for the coarsest input, while capability decisions are made by querying a media feature.
  • Target size is an invisible decision: the same 16-pixel icon produces a 20-, 24-, or 44-pixel target depending on padding, and the difference is invisible on screen.
  • The spacing exception does not legitimize small targets; it says that the space between targets is part of the target size, and it rewards an isolated target.
  • Expanding the hit area without changing the visual size goes unanswered when neighboring targets exist: going from 24 to 44 pixels adds 10 pixels on every side, and at gaps narrower than 20 pixels, hit areas overlap.
  • If the entire row is the target, the density decision and target size tie to the same number; a 33-pixel row is scanned in 11 screens, a 44-pixel row in 15.
  • Hover cannot be the only channel that carries information; its legitimate use is reinforcing something already visible.

Next Step

The layout skeleton is complete with this lesson: columns, gutters, and grid margins are derived from screen width, spacing comes from a closed scale, density is derived from the task, and target size is set for the coarsest input. The text that will fill the skeleton has not been chosen yet, though. Nearly all the weight the catalog interface carries is text, and throughout this topic, text has always been treated as a rectangle — a block made of characters 16 pixels tall and 8 pixels wide. The next topic opens up this assumption and moves font selection from taste to criterion: how apparent size is computed, which characters get confused with each other, how many hierarchy levels a font family can carry.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close