<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Designing grids — Chris Armstrong</title>
<link>https://armstrong.is/designing-grids/</link>
<description>Posts on designing grids.</description>
<language>en</language>
<atom:link href="https://armstrong.is/designing-grids/feed.xml" rel="self" type="application/rss+xml"/>
<item>
<title>Vertical Web Design</title>
<link>https://armstrong.is/designing-grids/vertical-web-design/</link>
<guid isPermaLink="true">https://armstrong.is/designing-grids/vertical-web-design/</guid>
<description>Every new medium first imitates the old one. The case for moving the web past inherited print columns — through reading momentum, vertical pacing, and a vocabulary for how layouts feel.</description>
<content:encoded><![CDATA[<nav class="contents" aria-label="Contents">
  <p class="contents-label">Contents</p>
  <ol>
    <li><a href="#a-young-medium"><span class="c-num">I</span><span class="c-title">A young medium</span></a></li>
    <li><a href="#reading-momentum"><span class="c-num">II</span><span class="c-title">Reading momentum</span></a></li>
    <li><a href="#vertical-pacing"><span class="c-num">III</span><span class="c-title">Vertical pacing</span></a></li>
    <li><a href="#patterns-transitions"><span class="c-num">IV</span><span class="c-title">Patterns &amp; transitions</span></a></li>
  </ol>
</nav>

<h2 class="chapter" id="a-young-medium"><span class="chapter-num" aria-hidden="true">I</span><span class="chapter-title">A young medium</span></h2>

<figure class="wide">
  <img src="https://armstrong.is/assets/images/1904-oldsmobile.jpg" alt="A 1904 Oldsmobile — an early car styled like a motorised carriage.">
</figure>

<p class="lede">Every new medium mimics what came before.</p>

<p>Early cars looked like motorised carriages, and early cinema was filmed like a stage play from the audience&rsquo;s perspective&mdash;it took decades for early filmmakers to understand the power of editing, camera angles, lighting and more.</p>

<figure>
  <video src="https://armstrong.is/assets/media/irresistible-piano.mp4" autoplay muted loop playsinline></video>
  <figcaption><a href="https://www.youtube.com/watch?v=YEYjL90_lVk"><em>The Irresistable Piano (1907)</em></a>, Alice Guy Blanche</figcaption>
</figure>

<p>It takes time for a medium&rsquo;s unique characteristics&mdash;the strengths &amp; weaknesses that set it apart from its predecessors&mdash;to reveal themselves, but as our understanding of them grows we&rsquo;re able to move on from what came before and communicate through the medium in deeper, more meaningful ways.</p>

<p>The web is still a young medium, and our approach to designing for it is still heavily influenced&mdash;and shackled&mdash;by what came before; print design in particular. Of all the practices and concepts we inherited from print design, there&rsquo;s one in particular that I believe is massively holding us back from taking design on the web to the next level: columns.</p>

<p>It&rsquo;s time to move on from column-based layouts.</p>

<h2 class="chapter" id="reading-momentum"><span class="chapter-num" aria-hidden="true">II</span><span class="chapter-title">Reading momentum</span></h2>
<p>In most western printed media (books, magazines, etc), the <em>reading momentum</em> is horizontal. A composition&rsquo;s primary goal is usually to guide the reader&rsquo;s eye from the top left of the layout to the bottom right&mdash;at which point they turn the page, bringing their eye back to the top left, ready to go again.</p>

<p>One of the most effective ways to do this is by laying the content out in columns. Vertical bars cause our eyes to instinctively scan across them horizontally, so column-based compositions tend to have a strong <em>horizontal reading momentum</em>.</p>

<p>However, on the web we&rsquo;re scrolling through content vertically, not turning pages horizontally, so we need the reading momentum to be vertical, not horizontal. When we use a column-based composition on the web, it guides the reader&rsquo;s eyes horizontally, just as in print&hellip; except this time when their eyes get to the right edge of the screen there&rsquo;s nowhere to go. Since our compositions are fighting against the web&rsquo;s natural reading momentum, we&rsquo;ve had to resort to adding little &lsquo;scroll down&rsquo; arrows to prevent readers getting confused.</p>

<p>To create compositions that have an in-built <em>vertical</em> reading momentum, we need to base them on horizontal bars (or, y&rsquo;know, <em>rows</em>) that will guide the reader&rsquo;s eye downwards.</p>

<p>I&rsquo;m not saying columns are irrelevant in web design. Just as a baseline grid fills a strong supporting role in print, columns can still be used to great effect on the web, but they shouldn&rsquo;t be our primary concern. When designing for the web (or any medium with a vertical reading momentum), the <em>vertical grid</em> should take the lead. The backbone of our compositions should be rows, not columns.</p>

<h2 class="chapter" id="vertical-pacing"><span class="chapter-num" aria-hidden="true">III</span><span class="chapter-title">Vertical pacing</span></h2>
<p>We can&rsquo;t control the speed at which a reader scrolls through content, but we <em>can</em> control the pace.</p>

<p>Let&rsquo;s try an experiment. Below is a single column of lines that tightens and loosens over and over, across many screens. Don&rsquo;t worry about what it&rsquo;s for &mdash; just scroll down through it at whatever pace feels natural, and try not to think about it.</p>

<figure class="full-bleed pace" id="pace-column">
  <img src="https://armstrong.is/assets/images/pacing-gradient.svg" alt="A tall column of horizontal lines that fades in from a point, repeatedly tightens and loosens as it widens, then tapers back to a point.">
</figure>

<p>Now, I can&rsquo;t say for <em>sure</em> that you slowed as the lines spread apart and sped up as they tightened&hellip; but I bet you did. That&rsquo;s an emotional reaction, and demonstrates the power that simple compositional choices can have: our layouts can do so much more than simply &lsquo;fit the content&rsquo; onto the screen, or &lsquo;make it look good&rsquo;. When we embrace vertical pacing within our designs, we can use composition to connect with our readers on a much deeper, emotional level.</p>

<figure class="pace-chart" id="pace-chart" hidden>
  <figcaption class="pace-chart-cap">Your scroll speed against the line spacing, top of the column to bottom.</figcaption>
  <div class="pace-chart-canvas" id="pace-chart-canvas"></div>
  <p class="pace-verdict" id="pace-verdict"></p>
</figure>

<blockquote class="pullquote"><p>When we embrace vertical pacing within our designs, we can use composition to connect with our readers on a much deeper, emotional level.</p></blockquote>

<p>The great thing about vertical pacing is that it&rsquo;s relatively unaffected by screen size. If our primary concern when designing a composition is the vertical pacing of the content, then it shouldn&rsquo;t matter whether it&rsquo;s being expressed on a narrow mobile device or a 30&Prime; monitor. While the exact composition can (and usually should) adapt to the canvas on which it&rsquo;s being viewed, the vertical pacing&mdash;the emotional heartbeat of the composition&mdash;can still be maintained.</p>

<p>Film editors understand the power of pacing all too well: a common exercise in film schools is to have students watch a scene and &lsquo;clap&rsquo; every time they spot a cut. A romantic scene might result in a soft, steady clap, whereas watching a Hitchcock thriller may start slow and get gradually faster as the tension mounts. A fight scene from Michael Bay&rsquo;s Transformers films will make the classroom sound like a cheap fireworks display.</p>

<figure>
  <div class="embed"><iframe src="https://www.youtube.com/embed/3Q3eITC01Fg?start=204" title="Tony Zhou video essay on pacing" loading="lazy" allowfullscreen></iframe></div>
  <figcaption>In this video essay, Tony Zhou explores the impact pacing can have on how you feel about a shot.</figcaption>
</figure>

<p>Watching a film is a passive experience, but scrolling through a website requires <em>active</em> participation from a reader. Whether they&rsquo;re using a mouse or touching the content directly on their phone, they&rsquo;re literally <em>stroking</em> their way through our content. That&rsquo;s a far more intimate connection with our audience than film will ever have, and when we create compositions that dance to the rhythm the reader is setting, we can use that bond to leave a lasting emotional impression.</p>

<blockquote class="pullquote"><p>When we create compositions that dance to the rhythm the reader is setting, we can use that bond to leave a lasting emotional impression.</p></blockquote>

<p><em>Every</em> composition has a vertical pace, but if it&rsquo;s not designed intentionally then it&rsquo;s unlikely to be causing the reader to feel what we&rsquo;d hope. What kind of emotional journeys do we want to take readers on when they scroll through our content? Do we want them to feel excited? Relaxed? Somber? While we can certainly affect these things through traditional design tools like colour and typography, I believe we could do it on a much deeper level through vertical pacing, if we try.</p>

<h2 class="chapter" id="patterns-transitions"><span class="chapter-num" aria-hidden="true">IV</span><span class="chapter-title">Patterns &amp; transitions</span></h2>
<p>Web layout has a lot of untapped potential, but if we&rsquo;re to explore it (and ultimately master it) we first need to be able to talk about it. To do that, we&rsquo;re going to need a better vocabulary.</p>

<p>Cinematography has such a well-established vocabulary that when I say &ldquo;wide shot of deserted street, slow pan to cowboy, fade to closeup of cowboy&rsquo;s eyes, cut to medium shot as he reaches for his holster&rdquo;, you can probably imagine that exact scene&mdash;its pacing and emotion&mdash;without any visual reference.</p>

<p>Now, try and describe a web-based layout with words. The vocabulary we use to describe web layouts has been mostly borrowed from print, so while we can talk at length about &ldquo;a sidebar in column 1 and text block spanning columns 2&ndash;4&rdquo;, we&rsquo;re ill-equipped to have any nuanced discussions about vertical pacing.</p>

<p>What do you call it when you have three images with captions side-by-side? How about when you have images on the left and text on the right&hellip; or when you have image on the left and text on the right, then text on the left and image on the right, and so on? We use these layout patterns all the time, yet their lack of widely-understood labels means I probably need to show you an image to be sure you understand what I mean, and talking about them is exhausting. Imagine if Spielberg had to say &ldquo;ok at this point I want you to slowly rotate the camera horizontally, then gradually reduce the opacity of that shot while increasing the opacity of the shot where we changed the lens to a telephoto and aimed it at the actor&rsquo;s face&ldquo;? &ldquo;Slow pan, then fade to closeup&rdquo; is a lot quicker.</p>

<p>Once we have words to describe these patterns, we can have better conversations about the <em>emotional</em> impact they have on a reader, and when might be appropriate to use them.</p>

<p>How does the emotional impact differ between an image that takes up the entire screen, versus side-by-side images, versus &lsquo;staggered&rsquo; images and text blocks? How does it feel when we scroll from one pattern to another? How does it feel when the background of one section is dark and the next is light? Or what about when the background fades between the two? What happens if I gradually reduce the vertical padding of each section, will the reader feel like things are speeding up? if I zig-zag the content in this section, then square it all off in the next, how will that make the reader feel?</p>

<p>These are the kind of discussions we need to be having if we&rsquo;re going to explore the full potential of vertical web design.</p>
<script>
/* Vertical pacing — sample the reader's scroll speed against the line spacing
   as they move down a single modulating column, then draw a chart comparing
   the two and score the correlation. Progressive enhancement; the profile here
   mirrors the SVG generator (sin hump: tight → wide → tight). */
(function () {
  var col    = document.getElementById('pace-column');
  var chart  = document.getElementById('pace-chart');
  var canvas = document.getElementById('pace-chart-canvas');
  var verdict= document.getElementById('pace-verdict');
  if (!col || !chart || !canvas) return;

  var N = 90;                                  // bins down the column
  var sum = new Float64Array(N), cnt = new Float64Array(N);
  var lastY = window.scrollY, lastT = performance.now(), done = false;

  function densityAt(t) {                       // matches the SVG: 1 / period
    var P_MIN = 10, P_MAX = 120, CYCLES = 2;
    var shape = (1 - Math.cos(2 * Math.PI * CYCLES * t)) / 2;
    return 1 / (P_MIN + (P_MAX - P_MIN) * shape);
  }
  function colBounds() {
    var r = col.getBoundingClientRect();
    return { top: r.top + window.scrollY, height: col.offsetHeight };
  }

  var ticking = false;
  function onScroll() {
    if (ticking) return; ticking = true;
    requestAnimationFrame(function () {
      ticking = false;
      var now = performance.now(), y = window.scrollY;
      var dt = now - lastT, dy = y - lastY;
      var b = colBounds();
      var p = (y + window.innerHeight * 0.5 - b.top) / b.height;   // viewport centre
      // record only smooth, downward motion (ignore pauses & up-scrolls)
      if (dy > 0 && dt > 0 && dt < 250 && p >= 0 && p <= 1) {
        var i = Math.min(N - 1, Math.max(0, Math.floor(p * N)));
        sum[i] += dy / dt; cnt[i] += 1;
      }
      lastY = y; lastT = now;
      if (!done && p > 1) { done = true; finish(); }
    });
  }

  function norm(a) {
    var mn = Infinity, mx = -Infinity, i;
    for (i = 0; i < a.length; i++){ if (a[i] < mn) mn = a[i]; if (a[i] > mx) mx = a[i]; }
    var r = mx - mn;
    return a.map(function (v){ return r ? (v - mn) / r : 0.5; });
  }
  function fill(a) {                              // linear-interpolate nulls
    var i, k, j;
    for (i = 0; i < a.length; i++) if (a[i] === null) {
      j = i; while (j < a.length && a[j] === null) j++;
      var lo = i > 0 ? a[i - 1] : (j < a.length ? a[j] : 0);
      var hi = j < a.length ? a[j] : lo;
      for (k = i; k < j; k++) a[k] = lo + (hi - lo) * (j > i ? (k - i + 1) / (j - i + 1) : 0);
      i = j;
    }
    return a;
  }
  function smooth(a, w) {
    return a.map(function (_, i) {
      var s = 0, n = 0;
      for (var k = -w; k <= w; k++){ var j = i + k; if (j >= 0 && j < a.length){ s += a[j]; n++; } }
      return s / n;
    });
  }
  function pearson(a, b) {
    var n = a.length, sa = 0, sb = 0, saa = 0, sbb = 0, sab = 0;
    for (var i = 0; i < n; i++){ sa += a[i]; sb += b[i]; saa += a[i]*a[i]; sbb += b[i]*b[i]; sab += a[i]*b[i]; }
    var num = n*sab - sa*sb, den = Math.sqrt((n*saa - sa*sa) * (n*sbb - sb*sb));
    return den ? num / den : 0;
  }

  function finish() {
    var xs = [], speed = [], dens = [], filled = 0, i;
    for (i = 0; i < N; i++) {
      xs.push((i + 0.5) / N);
      dens.push(densityAt((i + 0.5) / N));
      if (cnt[i] > 0) { speed.push(sum[i] / cnt[i]); filled++; }
      else speed.push(null);
    }
    var enough = filled >= 10;
    var sp = smooth(fill(speed.slice()), 2);
    var r  = pearson(sp, dens);
    draw(norm(sp), norm(dens), xs, r, enough);
    say(r, enough);
    chart.hidden = false;
    window.removeEventListener('scroll', onScroll);
  }

  function draw(sp, dn, xs, r, enough) {
    var W = 1000, H = 360, L = 18, R = 18, T = 54, B = 40;
    var pw = W - L - R, ph = H - T - B;
    var X = function (t){ return (L + t * pw).toFixed(1); };
    var Y = function (v){ return (T + (1 - v) * ph).toFixed(1); };
    function line(a){ var d = ''; for (var i = 0; i < a.length; i++) d += (i ? 'L' : 'M') + X(xs[i]) + ' ' + Y(a[i]) + ' '; return d.trim(); }
    var area = 'M' + X(xs[0]) + ' ' + Y(0) + ' ';
    for (var i = 0; i < dn.length; i++) area += 'L' + X(xs[i]) + ' ' + Y(dn[i]) + ' ';
    area += 'L' + X(xs[xs.length - 1]) + ' ' + Y(0) + ' Z';

    var rTxt = (r >= 0 ? '+' : '\u2212') + Math.abs(r).toFixed(2);
    var svg =
      '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + W + ' ' + H + '" role="img" ' +
      'aria-label="Chart comparing your scroll speed with the line density down the column. Correlation ' + rTxt + '.">' +
        '<rect x="0" y="0" width="' + W + '" height="' + H + '" fill="#ffffff"/>' +
        '<line x1="' + L + '" y1="' + Y(0) + '" x2="' + (W - R) + '" y2="' + Y(0) + '" stroke="rgba(0,0,0,0.2)" stroke-width="1"/>' +
        '<path d="' + area + '" fill="#111111" fill-opacity="0.07"/>' +
        '<path d="' + line(dn) + '" fill="none" stroke="rgba(0,0,0,0.35)" stroke-width="2" stroke-dasharray="2 5" stroke-linecap="round"/>' +
        '<path d="' + line(sp) + '" fill="none" stroke="#111111" stroke-width="3" stroke-linejoin="round"/>' +
        // legend
        '<rect x="' + L + '" y="20" width="22" height="3" fill="#111111"/>' +
        '<text x="' + (L + 30) + '" y="24" font-family="Pitch, monospace" font-size="15" fill="rgba(0,0,0,0.6)">your scroll speed</text>' +
        '<rect x="' + (L + 200) + '" y="20" width="22" height="3" fill="rgba(0,0,0,0.35)"/>' +
        '<text x="' + (L + 230) + '" y="24" font-family="Pitch, monospace" font-size="15" fill="rgba(0,0,0,0.6)">how tightly the lines packed</text>' +
        // r value
        '<text x="' + (W - R) + '" y="24" text-anchor="end" font-family="Pitch, monospace" font-size="15" fill="#111111">r = ' + rTxt + '</text>' +
        // x labels
        '<text x="' + L + '" y="' + (H - 14) + '" font-family="Pitch, monospace" font-size="14" fill="rgba(0,0,0,0.4)">top of column</text>' +
        '<text x="' + (W - R) + '" y="' + (H - 14) + '" text-anchor="end" font-family="Pitch, monospace" font-size="14" fill="rgba(0,0,0,0.4)">bottom</text>' +
      '</svg>';
    canvas.innerHTML = svg;
  }

  function say(r, enough) {
    if (!enough) { verdict.textContent = 'That was more of a leap than a scroll — too few samples to chart fairly. Give it a proper scroll if you\u2019re curious.'; return; }
    var rTxt = (r >= 0 ? '+' : '\u2212') + Math.abs(r).toFixed(2);
    var msg;
    if (r >= 0.5)      msg = 'Strong match (' + rTxt + '). Your speed rose and fell with the lines — the composition was setting your pace, not you.';
    else if (r >= 0.2) msg = 'A loose match (' + rTxt + '). Your pace drifted toward the lines\u2019 rhythm more often than not.';
    else if (r > -0.2) msg = 'No real link (' + rTxt + '). You held a steady pace and ignored the lines entirely. Stubborn — respect.';
    else               msg = 'You did the opposite (' + rTxt + '): quicker through the open stretches, slower through the dense ones. A contrarian scroll.';
    verdict.textContent = msg;
  }

  window.addEventListener('scroll', onScroll, { passive: true });
  onScroll();
})();
</script>]]></content:encoded>
<pubDate>Sat, 07 May 2022 00:00:00 +0000</pubDate>
</item>
<item>
<title>Margins</title>
<link>https://armstrong.is/designing-grids/margins/</link>
<guid isPermaLink="true">https://armstrong.is/designing-grids/margins/</guid>
<description>Two kinds of margin: passive (leftover template space) and active (space that binds content to its canvas).</description>
<content:encoded><![CDATA[<p class="lede">Margins help define the relationship between content and its canvas. They can play a key role in making a composition feel like it fits snugly into the space available&hellip; not too big, not too small.</p>

<p>There are two main kinds of margins: <em>passive</em> and <em>active</em>.</p>

<h2>Passive margins</h2>
<p>Passive margins are everywhere. They&rsquo;re what you get when a browser window is larger than the content was designed for. They don&rsquo;t care about the relationship between content and its canvas. They&rsquo;re simply leftover space, and a reminder that you&rsquo;re looking at a template rather than a layout that&rsquo;s been hand-composed for your exact circumstance.</p>

<h2>Active margins</h2>
<p>Active margins actively work to bind the content to its canvas by maintaining some form of relationship between the two, no matter the canvas size.</p>]]></content:encoded>
<pubDate>Wed, 29 Dec 2021 00:00:00 +0000</pubDate>
</item>
</channel>
</rss>
