HeydonWorks https://heydonworks.com Writing and creative coding from Heydon Pickering en-us 2024-03-10T08:30:11.946Z What Is A Single-page Application? https://heydonworks.com/article/what-is-a-single-page-application/ 2024-02-26T00:00:00.000Z https://heydonworks.com/article/what-is-a-single-page-application/ <div style="display: none"> <svg id="spinner" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"><animateTransform attributeName="transform" type="rotate" dur="2s" values="0 12 12;360 12 12" repeatCount="indefinite"></animateTransform></path></svg> </div> <p>A spa is a place you go to drink mimosas and have slices of cucumber placed over your eyes, which is a very specific experience. The term comes from the Latin <em>sanitus per aquam</em> meaning “health through water”. When you visit a spa during the day, you are having what is called a “spa day”. When you visit a spa at night, they are closed.</p> <p>That’s a spa, but what is a SPA? A SPA is a much less appealing and relaxing proposition. It is a type of web document named after the English expressions <em>single-page application</em> and <em>sadness per Angular</em>.</p> <p>SPAs replace the bad user experience of having to wait a second or two for 20KBs of HTML to be sent to your browser from a server with the good user experience of waiting several seconds for the server to send a 300KB JavaScript bundle, used to render HTML from scratch. It’s a good user experience because it means you get to look at one of these:</p> <svg width="50" height="50" role="img" aria-label="Loading, please wait"> <use href="#spinner"></use> </svg> <p>By taking the content and functionality of several web pages and shoving it up the guts of a single document, it is easier to persist data within the application, making transitioning between screens (fake pages) <em>blazingly fast</em>. Or it would, if the person who created the single-page application you’re looking at didn’t make it fetch content from a GraphQL server every time you switch between these screens. Considering <code>localStorage</code> has been supported since Internet Explorer 8, you’d think good use would be made of that. But then you wouldn’t get to look at one of these:</p> <svg width="50" height="50" role="img" aria-label="Loading, please wait some more"> <use href="#spinner"></use> </svg> <p>To make single-page applications load faster, you can render them as static HTML on a server, then send that static HTML to the browser (like you did before single-page applications were invented). However, to make them <em>behave</em> as single-page applications in the browser, you still have to send the 300KB JavaScript bundle alongside that static HTML. During the time that elapses between the HTML and JavaScript arriving in the browser and the JavaScript re-rendering the HTML <em>in situ</em>, the interface has no functionality. To save you from pressing buttons that don’t do anything yet, a courteous developer will take this opportunity to show you one of these while you wait:</p> <svg width="50" height="50" role="img" aria-label="Still loading, keep waiting, sucker"> <use href="#spinner"></use> </svg> <p>Once your SPA JavaScript is all loaded up, it may be that it does a lot of DOM operations. In which case, it may benefit from using a Virtual DOM. With a Virtual DOM, you don’t operate on the DOM directly, which is inefficient. Instead, you create a virtual, serialized representation of the DOM, which you query and evaluate before you do any DOM operations. Which, of course, you still have to do. Because, otherwise, nothing actually happens. This overhead isn’t an issue if your DOM is not especially large. But, well, you’re using React with Tailwind, so have another one of these:</p> <svg width="50" height="50" role="img" aria-label="Still loading, keep waiting, sucker"> <use href="#spinner"></use> </svg> <p>You can’t create a complex modern web application like Google Mail without JavaScript and a SPA architecture. Google Mail is a webmail client and webmail clients existed some time before JavaScript became the language it is today or frameworks like Angular JS or Angular BS existed. However, you <em>cannot</em> create a complex modern web application like Google Mail <em>without</em> JavaScript. Google Mail itself offers a basic HTML version that works perfectly well without JavaScript of any form—let alone a 300KB bundle. But, still, you <em>cannot</em> create a complex modern web application like Google Mail without JavaScript. Just keep saying that. Keep repeating that line in perpetuity. Keep adding more and more JavaScript and calling it good. Incidentally, you do not need to create a complex modern web application like Google Mail with JavaScript or otherwise because it already f**king exists.</p> <p>This site is rendered statically and uses no JavaScript whatsoever, largely because it is a blog so there really is no need. But equating <em>familiar</em> with <em>good</em> is common and I aim to please, so here’s yet another one of these for good measure:</p> <svg width="50" height="50" role="img" aria-label="Loading nothing, for no reason"> <use href="#spinner"></use> </svg> <hr> <p>If you enjoyed this, you may like <a href="https://briefs.video/">my videos</a> and there’s a vanishingly small chance you may also be interested in some <a href="https://webbed-briefs.teemill.com/collection/new/?sort=bestsellerOrder">web themed apparel</a>.</p> What is Utility-First CSS? https://heydonworks.com/article/what-is-utility-first-css/ 2024-02-19T00:00:00.000Z https://heydonworks.com/article/what-is-utility-first-css/ <p>You can’t really appreciate <strong>utility-first CSS</strong> until you have a decent understanding of CSS itself, so this article will principally be about that. However, paradoxically, the more you learn about CSS, the less you may appreciate utility-first CSS. You might begin to question why it should exist at all. It’s possible you’ll even start to question why <em>you</em> exist.</p> <p>I’ll try my best to explain.</p> <p>CSS is responsible for a great many things when designing for the web, including typography, layout, and animation. But it’s not just <em>what</em> it’s capable of that’s important; it’s also <em>how</em>.</p> <p>Before CSS, we had to style HTML elements on a case-by-case basis using now long obsolete presentational elements like <code>&lt;center&gt;</code> and <code>&lt;font&gt;</code> and presentational attributes like <code>bgcolor</code> and <code>face</code>. This approach to styling was a massive arse-ache and everyone hated it, but they didn’t have a choice.</p> <p>Then CSS introduced the <em>selector</em>: a pattern matching mechanism for styling multiple elements with one set of rules. It’s hard to overstate the <em>utility</em> of selectors, but that’s not what the term utility-first CSS is referring to, unfortunately.</p> <p>Instead, in the contemporary CSS vernacular, a “utility class” is specifically an HTML class, corresponding to a single CSS declaration, attached to a class selector. This is not quite an inline style like <code>bgcolor=&quot;black&quot;</code> or <code>style=&quot;background-color: black&quot;</code> but it is a <em>piecemeal</em> style, applying just one specific value to one property—and it does necessitate adorning the HTML with the class.</p> <pre><code class="language-jsx">.margin-inline-start-20 { margin-inline-start: 20px; } </code></pre> <p>Typically, the majority of your CSS would be applied using far reaching selectors (<code>:root</code>, <code>body</code>, <code>p</code>, <code>figure</code> etc) and inheritance. In fact, I believe there’s a kind of CSS 80/20 rule wherein about 80% of your styling should be done with just 20% (or less!) of your CSS.</p> <p>Where utility classes come in is they allow you to make occasional exceptions to these generalized styling rules. That’s their utility, and their only utility. They do not embody utility <em>per se</em> and they are not the most useful thing in CSS.</p> <p>Utility-<em>first</em> CSS is more radical. Utility-first CSS is <em>exception</em>-first CSS. And that’s not how exceptions work, in CSS or in general.</p> <p>Take paragraphs. Your paragraphs will almost invariably share the same <code>font-family</code>, <code>font-size</code>, <code>line-height</code>, and <code>margin</code>. Exceptions will be few. So how would you approach styling your paragraph elements? Well, the <code>font-size</code> and <code>line-height</code> are typically taken care of already, since <code>&lt;p&gt;</code> elements would inherit these values from an ancestor element, such as the <code>:root</code>. So your best course of action here is, I don’t know, make a cup of tea, go for a walk, something like that, just don’t write any code. As for the <code>margin</code>, you can style 100s, 1000s, even millions of paragraphs at once, in one place, with a single, simple declaration:</p> <pre><code class="language-css">p { margin-block: 1rem; } </code></pre> <p>In fact, placing a margin directly on any element or category of elements is somewhat a bad pattern anyway. What you should probably be employing is <em>contextual</em> <code>margin</code> via a <a href="https://every-layout.dev/layouts/stack/">Stack component</a> using a sibling selector (do not talk to <code>class</code>-centric utility-first adherents about sibling selectors).</p> <p>In any case, what utility-first CSS does is look you in the eye, wink, and say <em>this</em> approach to styling is better:</p> <pre><code class="language-jsx">&lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;And&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;on&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;and&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;on&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;and&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;on&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;and&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;on&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;etc&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;etc&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;etc&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;etc&lt;/p&gt; &lt;p class=&quot;font-sans text-base leading-6 my-16&quot;&gt;etc&lt;/p&gt; </code></pre> <p>Utility-first detractors complain a lot about how verbose this is and, consequently, how ugly. And it is indeed. But you’d forgive it that if it actually solved a problem, which it doesn’t. It is unequivocally an inferior way of making things which <em>are</em> alike <em>look</em> alike, as you should. It is and can only be useful for reproducing <em>inconsistent</em> design, wherein all those repeated values would instead differ.</p> <p>To put it another way, show me a design for an interface that <em>benefits</em> from being coded using utility-first CSS and I will show you an interface that is fundamentally <em>f**ked</em>—and long before it falls in the lap of some hapless front-end developer.</p> <p>What if your organization or client generates content using a syntax like markdown or a WYSIWYG text editor, that translates the input into arbitrary, unadorned HTML—<strong>which will be in most cases</strong>? Well, you’re kind of stuffed, aren't you? That is, unless you <a href="https://dev.to/ewatch/styling-markdown-generated-html-with-tailwind-css-and-parsedown-328d">create, say, a specialized markdown plugin</a> that combines utility styles and applies them using, say, Tailwind’s <code>@apply</code> directive, which... <strong><em>is just writing CSS but in an absurdly obfuscated way</em></strong>.</p> <pre><code class="language-js">const plugin = require('tailwindcss/plugin') module.exports = { plugins: [ plugin(function({ addBase, theme }) { addBase({ 'p': { fontSize: theme('fontSize.base'), marginBlock: '1rem', lineHeight: '1.5' }, }) }) ] } </code></pre> <p>Tailwind is a particularly slippery customer because it’s a purportedly utility-first tool but with multiple escape hatches, like <code>@apply</code>, for writing CSS that combines utility classes into the kind of semantic declaration blocks the framework initially wants you to think it eschews.</p> <pre><code class="language-css">.select2-dropdown { @apply rounded-b-lg shadow-md; } .select2-search { @apply border border-gray-300 rounded; } .select2-results__group { @apply text-lg font-bold text-gray-900; } </code></pre> <p>Tailwind even uses my 10-year-old <a href="https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/">owl selector</a> concept for applying <a href="https://tailwindcss.com/docs/space">space between</a> child elements. Which means using a dreaded <em>child selector</em>!</p> <p>So what is Tailwind really? It’s just CSS with extra steps and a brand name. Then again, you can say that about most any CSS framework.</p> <hr> <p>Why is this utility-first approach so popular at the moment? Partly because the designs we’re charged with coding often <em>are</em> f**ked and we need equally f**ked tools to wrangle them. Partly it’s because the f**ked tools we’ve adopted to write f**ked JavaScript don’t play so well with CSS or, for that matter, HTML. Mostly, it’s because developer insecurity and neophilia are easily exploited: “Have you ever written CSS you <em>weren’t quite happy with</em>? Well here’s a radical, paradigm-shifting, quasi-proprietary solution! You’ll never embarrass yourself again!”</p> <p>It turns out, people in tech are particularly bad at distinguishing between paradigm shifts and paradigm <em>sharts</em>. That’s why we have nose-diving cryptocurrencies, dust-collecting monkey JPEG portfolios, and AI-generated children’s books teaching kids about pink, two-headed dinosaurs that never existed.</p> <p>It’s not that utility-first CSS can’t be used to style things. It technically can. If you don’t understand CSS, it might be the best way for you to do so. At least if you work exclusively in JSX. And are ensconced in several months and gigabytes of tooling. If you <em>do</em> appreciate CSS, frameworks like Tailwind include features and tools that help you move away from the piecemeal, utility-first approach they encourage you to use from the outset.</p> <p>But, just as a thought experiment, imagine if CSS didn’t exist, today, in any form (including as an escape hatch inside a utility-class based framework) and your only two choices for styling were:</p> <ul> <li>1990s-vintage presentational HTML</li> <li>The class attribute and a utility class syntax (see <a href="https://nuejs.org/blog/tailwind-misinformation-engine/"><strong>Tailwind marketing and misinformation engine</strong></a> for this example):</li> </ul> <pre><code class="language-jsx">&lt;button class=&quot; [&amp;amp;&gt;[data-slot=icon]]:-mx-0.5 [&amp;amp;&gt;[data-slot=icon]]:my-0.5 [&amp;amp;&gt;[data-slot=icon]]:shrink-0 [&amp;amp;&gt;[data-slot=icon]]:size-5 [&amp;amp;&gt;[data-slot=icon]]:sm:my-1 [&amp;amp;&gt;[data-slot=icon]]:sm:size-4 [&amp;amp;&gt;[data-slot=icon]]:text-[--btn-icon] [--btn-bg:theme(colors.zinc.900)] [--btn-border:theme(colors.zinc.950/90%)] [--btn-hover-overlay:theme(colors.white/10%)] [--btn-icon:theme(colors.zinc.400)] after:-z-10 after:absolute after:data-[active]:bg-[--btn-hover-overlay] after:data-[disabled]:shadow-none after:data-[hover]:bg-[--btn-hover-overlay] after:inset-0 after:rounded-[calc(theme(borderRadius.lg)-1px)] after:shadow-[shadow:inset_0_1px_theme(colors.white/15%)] before:-z-10 before:absolute before:bg-[--btn-bg] before:data-[disabled]:shadow-none before:inset-0 before:rounded-[calc(theme(borderRadius.lg)-1px)] before:shadow bg-[--btn-border] border border-transparent dark:[--btn-bg:theme(colors.zinc.600)] dark:[--btn-hover-overlay:theme(colors.white/5%)] dark:after:-inset-px dark:after:rounded-lg dark:before:hidden dark:bg-[--btn-bg] dark:border-white/5 dark:text-white data-[active]:[--btn-icon:theme(colors.zinc.300)] data-[disabled]:opacity-50 data-[focus]:outline data-[focus]:outline-2 data-[focus]:outline-blue-500 data-[focus]:outline-offset-2 data-[hover]:[--btn-icon:theme(colors.zinc.300)] focus:outline-none font-semibold forced-colors:[--btn-icon:ButtonText] forced-colors:data-[hover]:[--btn-icon:ButtonText] gap-x-2 inline-flex isolate items-center justify-center px-[calc(theme(spacing[3.5])-1px)] py-[calc(theme(spacing[2.5])-1px)] relative rounded-lg sm:px-[calc(theme(spacing.3)-1px)] sm:py-[calc(theme(spacing[1.5])-1px)] sm:text-sm/6 text-base/6 text-white&quot;&gt; Button &lt;/button&gt; </code></pre> <p>Given this miserable scenario, the introduction of <em><strong>CSS proper</strong></em> would see the web development community, the world over, collectively drowning in their own highly caffeinated excitement wee wees. Within a month, its advent would have spawned a hundred thousand <em>“hey guys!!”</em> Youtube videos, 67 hastily written books, and 31 video courses hosted by creepy, immaculately preened white dudes. All you’d hear about day in and day out would be <em>“the selector engine”, “separations of concern”</em>, and <em>“the cascade”</em> and instead of complaining about CSS being difficult, everyone would be scrambling to master it before their peers. CSS would be embraced and loved because it would be <em>new</em>.</p> <p>But CSS isn’t new, it’s only <em>good</em>. And in this backwards, bullshit-optimized economy of garbage and nonsense, good isn’t bad enough.</p> <hr> <p>If you enjoyed this diatribe, you may like <a href="https://briefs.video/">my videos</a> and there’s a small chance you may be interested in some <a href="https://webbed-briefs.teemill.com/collection/new/?sort=bestsellerOrder">web themed apparel</a>.</p> Offloading JavaScript With Custom Properties https://heydonworks.com/article/offloading-javascript-with-custom-properties/ 2024-02-07T00:00:00.000Z https://heydonworks.com/article/offloading-javascript-with-custom-properties/ <p>Sometimes a web development client doesn’t know quite what they want. Trying to guess is difficult and <em>delivering</em> a guess is risky. Where they have a vague idea, I offer to set them up with the means to create what they want for themselves—when they work out precisely what that is.</p> <p>This was the case recently, where a client wanted some sort of scroll-driven animation, but we couldn’t settle on the exact nature of that animation. All I could advise from a creative standpoint was that it shouldn’t be too obtrusive or disorientating.</p> <p>Given <a href="https://caniuse.com/?search=scroll%20driven%20animations">CSS-based scroll-driven animations</a> are still behind various flags, I set my client up with a small <a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"><code>IntersectionObserver</code></a> script. This tiny module, called <code>CreateObserver</code>, is imported into the foot of the page and initialized with a few arguments.</p> <pre><code class="language-js">&lt;script type=&quot;module&quot;&gt; import { createObserver } from 'static/js/createObserver.js'; const observerFunction = entries =&gt; { entries.forEach(entry =&gt; { // do something each time a threshold is crossed }); } createObserver('.section', 5, observerFunction); &lt;/script&gt; </code></pre> <ul> <li><code>.section</code>: the selector representing elements whose visibility is to be observed (“entries” in <code>IntersectionObserver</code> parlance)</li> <li><code>5</code>: the number of thresholds (proportions of visibility) handled by the observer. <code>5</code> creates the array <code>[0, 0.2, 0.4, 0.8, 1]</code></li> <li><code>observerFunction</code>: The handling/callback function fired whenever a threshold is crossed</li> </ul> <p>This is pretty serviceable as a general solution, since pretty much anything can be done inside your <code>observerFunction</code> function. With this, I could equip my client with the means to start playing with scroll-based visual effects—and without them having to think much about how <code>IntersectionObserver</code> actually works.</p> <p>But, as I started writing them example implementations of the callback function, everything started to feel overly JavaScripty. From the <code>README</code>:</p> <pre><code class="language-js">const opacityFade = entries =&gt; { entries.forEach(entry =&gt; { let ratio = entry.intersectionRatio; entry.target.style.opacity = ratio; }); } </code></pre> <p>The above is <em>okay</em>, I guess, especially since the <code>opacity</code> property maps directly to the intersection ratio (<code>0.5</code> intersecting? <code>0.5</code> opacity).</p> <p>But it gets more complex (and less performant) when you have to coerce the threshold value:</p> <pre><code class="language-js">const leftOffset = entries =&gt; { entries.forEach(entry =&gt; { let ratio = entry.intersectionRatio; let max = -20; let offset = max * (1 - ratio); entry.target.style.insetInlineStart = `${offset}rem`; }); } </code></pre> <p>And this is if you only want to style the observer entry element itself. What if you really want to affect a descendant element? More DOM querying.</p> <pre><code class="language-js">const leftOffset = entries =&gt; { entries.forEach(entry =&gt; { let ratio = entry.intersectionRatio; let max = 20; let offset = max * (1 - ratio); let descendant = entry.target.querySelector('.some-descendant'); descendant.style.insetInlineStart = `${offset}rem`; }); } </code></pre> <p>When you start writing some JavaScript, it kind of lures you into its own way of thinking and it’s easy to forget other technologies are present. While <code>IntersectionObserver</code> is (currently) critical in creating these scroll-driven effects, all we really want from it is <strong>the ratio</strong>.</p> <p>It’s entirely CSS that creates the effects on top of this ratio, so it’s <em>within</em> CSS that this work should be done. Not least because someone well versed in CSS and less familiar with JavaScript would then be better able to create and adapt the effects.</p> <p>Classically—the web is now so old you can refer to “classical” eras within it—the way to offload JavaScript styling to CSS is through the management of <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/class">classes</a>. With an <code>IntersectionObserver</code> threshold value of <code>1.0</code>, visibility is considered binary (fully visible or not) and you can simply toggle a single class using the <code>isIntersecting</code> property.</p> <pre><code class="language-js">entry.target.classList.toggle('is-intersecting', entry.isIntersecting) </code></pre> <p>With a <em>set</em> of thresholds (using the array syntax), multiple classes would have to be managed. Something hideous like this:</p> <pre><code class="language-css"> .intersecting-none { transform: translateX(-20rem); } .intersecting-one-fifth { transform: translateX(-16rem); } .intersecting-two-fifths { transform: translateX(-12rem); } .intersecting-three-fifths { transform: translateX(-8rem); } .intersecting-four-fifths { transform: translateX(-4rem); } .intersecting-full { transform: translateX(0); } </code></pre> <p>(Note: to stop these being <em>hard</em> steps, you can add a <code>transition</code> for the transform property.)</p> <p>That’s a lot of CSS for one scroll-driven animation, for one element. Worse than that, if someone decides to change the number of thresholds in the JavaScript, they—or someone else—would have to rewrite all these classes in the CSS.</p> <p>Instead, we can store the intersection ratio directly in a custom property!</p> <pre><code class="language-html">style=&quot;--intersecting: 0.2&quot; </code></pre> <p>This makes the ratio available directly in the CSS and can be used in styling calculations:</p> <pre><code class="language-js">opacity: var(--intersecting); transform: translateX(calc(-20rem * (1 - var(--intersecting)))); </code></pre> <p>The number of thresholds now directly produces a <em>resolution</em> for the animation/effect: the custom property updates as many times as the JavaScript callback is told to fire. CSS is reactive to these updates by default.</p> <p>And since custom property values inherit, we only need to place/update the value on the parent entry and it becomes available to all descendant elements.</p> <pre><code class="language-js">let ratio = entry.intersectionRatio; entry.target.style.setProperty('--intersecting', ratio); </code></pre> <p>In fact, custom callback functions aren’t needed after all. With just the ratio available directly in our CSS, pretty much everything and anything else can be coded with CSS alone. Which is as it should be.</p> <p>With classes, we can send CSS <em>static</em> values but with custom properties we can send <em>dynamic</em> ones, which is a major shift in the way we can style state. This is something that has been true for some time—and is <a href="https://caniuse.com/css-variables">extremely well supported</a>—but sometimes it takes solving a small real-world problem to make you appreciate the value of it.</p> <p>Here’s the general <code>IntersectionObserver</code> solution as a module should you ever have a use for it:</p> <pre><code class="language-js">const buildThresholds = steps =&gt; { let thresholds = [0]; for (let i = 1.0; i &lt;= steps; i++) { let ratio = i / steps; thresholds.push(ratio); } return thresholds; } const createObserver = (selector, steps) =&gt; { if (!IntersectionObserver in window) { return; } let options = { root: null, rootMargin: '0px', threshold: buildThresholds(steps) }; let observer = new IntersectionObserver(entries =&gt; { entries.forEach(entry =&gt; { let ratio = entry.intersectionRatio; entry.target.style.setProperty('--intersecting', ratio); }); }, options); let nodes = [...document.querySelectorAll(selector)]; nodes.forEach(node =&gt; { observer.observe(node); }); } export { createObserver } </code></pre> <hr> <p>If you liked this post, please check out my <a href="https://briefs.video/">videos about the web</a> and maybe <a href="https://webbed-briefs.teemill.com/collection/new/?sort=bestsellerOrder">buy a T-shirt or hoodie or something</a>.</p> Transcript: What Are Accessibility Overlays? https://heydonworks.com/article/what-are-accessibility-overlays-transcript/ 2023-10-04T00:00:00.000Z https://heydonworks.com/article/what-are-accessibility-overlays-transcript/ <p><em>The following is a transcript of my Webbed Briefs video <a href="https://briefs.video/videos/what-are-accessibility-overlays/">“What Are Accessibility Overlays?”</a>.</em></p> <hr> <p>If you put a sombrero on a cat, would that cat become Mexican? In short: no. The sombrero would remain Mexican and the cat non-Mexican. But the combination of the two would be considered problematic.</p> <p>Accessibility overlays are problematic in a similar way. Or they would be if the cat had chronic constipation and the sombrero was on fire.</p> <p>An accessibility overlay is a piece of third party software that is imposed (overlayed) on a website. There are many competing overlay products with names like:</p> <ul> <li>AccessiWasp</li> <li>LoserWay</li> <li>TheMaze</li> <li>PurpleEnd</li> <li>UserFist</li> <li>AudioHogsEye</li> </ul> <p>Despite claims to the contrary, accessibility overlays do not and cannot make their underlying website accessible. Ultimately, they are just more stuff—and obstructive stuff at that. In fact, as the website <a href="http://overlayfactsheet.com/">overlayfactsheet.com</a> attests, accessibility overlays have a habit of being inaccessible themselves, and can even prevent disabled people from using an otherwise accessible site. Which is a level of irony so high, it presents as</p> <ul> <li>Fatigue</li> <li>Joint pain</li> <li>General weakness</li> <li>Unexplained weight loss</li> <li>And is the subject of Black Sabbath's 1970 proto-doom masterpiece, Iron Man</li> </ul> <p>Even accessible accessibility overlays fail, by definition, and without exception. And why is that? Because, if the site is inaccessible with the overlay switched off, there's no guarantee the user will <em>be able</em> to switch it on. A situation you could be forgiven for describing as <strong>shiiiiiiiiite</strong>.</p> <p>All successfully activated overlays provide is a perfunctory array of options for things like font size and contrast; things already provided by the <em>underlying</em> browser and operating system.</p> <p><em>“But my overlay product isn’t just a toolbar. It also fixes your site’s existing accessibility issues, automatically.”</em></p> <p>This is false.</p> <p>Overlays cannot write you good alternative text, structure your document with an appropriate use of headings, connect the right labels to the right inputs, or determine if tables should have column headers, row headers, or both. They can't, and don't, design or build accessible websites.</p> <p>Accessibility overlays are not so much snake oil as they are snake essential oil: a refinement of tech fuckery so pure and potent, they have achieved the Platonic ideal of shitty software.</p> Functional documentation https://heydonworks.com/article/functional-documentation/ 2023-04-26T00:00:00.000Z https://heydonworks.com/article/functional-documentation/ <p><em>Some collected thoughts and ideas around applying a functional approach to writing and maintaining documentation, especially for design systems.</em></p> <hr> <p>In programming, you have these things called functions. Functions are chunks of code, typically identified by name.</p> <p>How you write functions varies between programming languages but why you write them does not. Functions define code you can recall and reuse. They stop you repeating yourself.</p> <p>Any code that isn’t functional is only used in one place, at one time, under one set of conditions. Non-functional code is fleeting.</p> <p>All programming is somewhat functional but <em>functional programming</em> embraces functions. Functional programmers believe the more functional your code, the better.</p> <p>I share this view. But I wonder if programming is the only context in which you should write functionally. While programming is divided up into discrete functions, other kinds of writing remain monolithic, measured in pages and documents. We’re not equipped to reuse or remix our content.</p> <h2>The installation documentation function</h2> <p>When it comes to documentation, we sometimes want to say similar things in different places. A design system might contain lots of components, each needing to be installed in a similar way.</p> <p>Most docs sites take one of two approaches:</p> <ol> <li><strong>Write out the installation instructions for each component</strong> (what if the installation process changes? There will be a lot of editing to do...)</li> <li><strong>Maintain a general component installation guide</strong> (requires a context change and some filling in of blanks on the reader’s part)</li> </ol> <p>Instead, we can turn installation guidance into a function. Here is a simplistic example:</p> <pre><code>function install (name, path) { return ` The ${name} component is installed by running &lt;code&gt;install ${path}&lt;/code&gt;. `; } </code></pre> <p>(If you’re a content editor, you might be wincing at that passive phrasing; we’ll fix that in a minute.)</p> <h2>Similar but different</h2> <p>Functions can take parameters. In the previous example, these are <code>name</code> and <code>path</code>. Parameters let us produce different results in specific and controlled ways. It’s like Mad Libs but (even) less funny.</p> <p>The <code>name</code> might be “button” or “input” but the sentence structure will be the same.</p> <p>If you decide to change that structure, the change is propagated to all the components, via the function. Let’s give it a more active voice:</p> <pre><code>function install (name, path) { return ` Run &lt;code&gt;install ${path}&lt;/code&gt; to install the ${name} component. `; } </code></pre> <p>Chase McCoy talks about <em>transclusion</em> for documentation in their excellent piece <a href="https://chasem.co/2021/08/systems-as-knowledge-graphs">Systems as Knowledge Graphs</a>. That is, expanding pieces of content inside other pieces of content, in preference to relying on links. With function parameters you can <em>adapt</em> the transcluded content, tailoring it to the parent document.</p> <h2>Editors aren’t (always) programmers</h2> <p>It’s at this point someone will say, <em>“but you can't expect content editors to program functions.”</em> In practice, the <code>function</code> keyword, return statement, curly braces, and semicolons could all be obfuscated, along with the build process around the function.</p> <p><a href="https://www.11ty.dev/">Eleventy</a> is a static site generator. In an Eleventy project, a function might be a markdown file, with Nunjucks syntax to do the Mad Libs substitution part. Here’s <code>installation.md</code>:</p> <pre><code>## Installation Run `install {{path}}` to install the {{name}} component. </code></pre> <p>That’s just markdown with placeholders—scarcely even programming.</p> <p>In <code>component.njk</code> (a Nunjucks template), we can include this installation section using Eleventy’s render plugin:</p> <pre><code> {% renderFile &quot;./path/to/installation.md&quot;, component, 'njk,md' %} </code></pre> <p>We’re using parameters again. It’s inside the <code>component</code> parameter where <code>name</code> and <code>path</code> would be defined:</p> <pre><code>{ name: 'button', path: 'path/to/button.js' } </code></pre> <p>The further <code>'njk,md'</code> parameter tells Eleventy to render the markdown using Nunjucks to substitute the <code>{{placeholder}}</code> parts.</p> <p>A programmer would have to set this part up, I grant you, but it’s in the service of making editing a lot less time consuming.</p> <h2>Am I talking about structured content?</h2> <p>You may have heard of structured content. Structured content is content that is broken down into small pieces, to enable composition and reuse. In data terms, it might mean the difference between one <code>description</code> property and multiple <code>height</code>, <code>width</code>, <code>depth</code>, <code>price</code>, <code>release date</code>, and <code>creator</code> properties that <em>together</em> describe a product.</p> <p>When these individual properties are defined as functions, taking parameters, they can be used to define more than one instance or category of content. Functional content is dynamic structured content.</p> <h2>Composition</h2> <p>Imagine we have functions for <strong>Installation</strong>, <strong>Contribution</strong>, and <strong>Related components</strong>. These can be combined to build a documentation page for a component. But perhaps we’re not settled on the order of these sections.</p> <p>Using a simple configuration file, we can allow reordering. Here’s <code>component.yml</code>.</p> <pre><code>order: - installation - related - contribution </code></pre> <p>YAML (<code>.yml</code>) files are a popular configuration syntax because there’s little punctuation to worry about. The list defined here uses a format similar to markdown.</p> <p><strong>Related components</strong> should come before <strong>Installation</strong> because you want to make sure you have the right component before installing it. Switching these around is trivial:</p> <pre><code>order: - related - installation - contribution </code></pre> <p>In <code>component.njk</code>, we honour the order defined in <code>component.yml</code> when we execute our functions (“execute” is a weird programming term meaning to <em>use</em>).</p> <pre><code> {% for section in order %} {% renderFile `./path/to/{{section}}.md`, component, 'njk,md' %} {% endfor %} </code></pre> <p>See how <code>section</code> is now a placeholder! The first time we use <code>renderFile</code>, <code>section</code> equals “related”, the second time it equals “installation”, and the third time it equals “contribute”. We are rendering our documentation sections one after another, in the order prescribed.</p> <p>This is trivial programming stuff, but I like the idea of applying it to structuring documentation. It makes writing documentation more modular.</p> <h2>Individual component documents</h2> <p>With all these provisions in place, editors (who could be content editors by role, programmers, or anyone else) can focus on what makes that component <em>that</em> component.</p> <p>The <code>components/button.md</code> file might look like this:</p> <pre><code>--- name: button path: path/to/button.js related: - switch - link - call-to-action --- Listen, the thing you need to know is buttons and links are _different_ things, with different expected _behaviours_ and [...] </code></pre> <p>The part between the <code>---</code> lines is called <em>front matter</em>. Not a programming term, originally, but a publishing one.</p> <p>In traditional publishing, it includes meta information about the work, starting with the name/title. In less traditional publishing it’s no different. It uses the same syntax as our <code>component.yml</code> file.</p> <p>The mistake some make is to put any old data in the front matter. Only things that are specific to a single item of content should live there. The rest should be abstracted into functions and configurations for shared use. That’s the principle we’re borrowing from functional programming.</p> <p>(One of Eleventy’s conventions for sharing common data is assigning <a href="https://www.11ty.dev/docs/data-template-dir/">directory-specific data files</a>.)</p> <h2>Combining human and machine generated documentation</h2> <p>You may have heard of “self-documenting” code (and the scare quotes here are no mistake). No code is self-documenting because the code itself can only tell you what it does, not what it doesn’t do, or why it exists.</p> <p>Important parts of documentation need to be written by humans (or, theoretically, by a sufficiently advanced AI—I won’t hold my breath). But other parts <em>can</em> be gleaned directly from the code (including from code comments, which are written by humans anyway).</p> <p>Tools like <a href="https://github.com/webcomponents/custom-elements-manifest">custom-elements-manifest</a> read your code and describe it back to you in the JSON data format.</p> <pre><code>[...] &quot;members&quot;: [ { &quot;kind&quot;: &quot;field&quot;, &quot;name&quot;: &quot;disabled&quot; }, { &quot;kind&quot;: &quot;method&quot;, &quot;name&quot;: &quot;fire&quot; } ], &quot;events&quot;: [ { &quot;name&quot;: &quot;disabled-changed&quot;, &quot;type&quot;: { &quot;text&quot;: &quot;Event&quot; } } ] [...] </code></pre> <p>This data can be used to define a documentation function. For example, the documentation function <code>event</code> (describing JavaScript events emitted by the custom element) could live alongside a hand-written introduction to the component’s events, including why and when you should use them. The former is gleaned directly from the code, the latter taken from a functional documentation template.</p> <pre><code>events - preface - API </code></pre> <h2>Abstract syntax trees</h2> <p>The format of the manifest file from the last example is that of an <a href="https://www.twilio.com/blog/abstract-syntax-trees">AST</a> (abstract syntax tree).</p> <p><a href="https://www.twilio.com/blog/abstract-syntax-trees">ASTs</a> will be familiar to programmers who have worked on compilers. To compile code, you first have to break it down into its constituent parts. An AST is a tree (object) representation of those parts.</p> <p>But it’s not just for code compilation that ASTs are useful and it is not just code that can be represented as an AST. Using <a href="https://github.com/syntax-tree/mdast">mdast</a>, a paragraph of markdown can be broken down into its constituent nodes:</p> <pre><code>{ type: 'paragraph', children: [ { type: 'text', value: 'You may also be interested in the ' }, { type: 'link', url: '/components/accordion', children: [{type: 'text', value: 'Accordion'}] }, { type: 'text', value: ' component.' } ] } </code></pre> <p>Earlier, I wrote about front matter—a tool for adding meta information to a piece of content. For example, you can say which components the given component are related to:</p> <pre><code>--- related: - switch - link - call-to-action --- </code></pre> <p>This being manual makes it a maintenance burden. Instead, we could use AST representations of our writing (both programmatic and prosaic) to automatically detect related components.</p> <p>Perhaps we do something simple like look for component names in the hyperlinks of the document (the AST representation could help with that). Or maybe we analyse the component dependencies to find out what uses what.</p> <p>In any case, the goal is to restrict <em>manual</em> documentation to things <em>only</em> human beings can express.</p> <h2>Dissemination</h2> <p>With our documentation converted into tree/object data, it’s primed for consumption by different platforms and their APIs. As Amy suggests in her article <a href="https://amyhupe.co.uk/articles/modular-design-system-documentation/">Modular design system documentation</a> you should be able to have design libraries like Figma and Sketch, as well as developer tools like Github or Storybook, all draw from the same documentation source.</p> <h2>Differing presentations</h2> <p>As <a href="https://amyhupe.co.uk/articles/modular-design-system-documentation/">Amy writes</a>, <strong>documentation has variants too</strong>.</p> <p>Because functional content is structured content, you can not only use the same functions to document different things, but create different presentations of the <em>same</em> thing by combining the functions in different ways.</p> <p>For example, you could create long-form and short-form versions of component documentation.</p> <pre><code>component: longform: - related - demo - installation - usage - contribute shortform: - installation - contribute </code></pre> <p>You could also maintain different versions of the same function for different presentations.</p> <h3><strong><code>installation.short.md</code></strong></h3> <pre><code>`install {{path}}` </code></pre> <h3><strong><code>installation.long.md</code></strong></h3> <pre><code>## Installation 1. Make sure you already have the {{installVersion}} version of the **install** tool on your computer. 2. Open your terminal and run `install {{path}}` from the root of the project folder </code></pre> <p>Contextually, you might set a <code>length</code> variable (<code>short</code> or <code>long</code>) and use this to find the right template for each section. For instance:</p> <pre><code>{% set length = ('short' if someCondition else 'long') %} {% for section in order %} {% renderFile `./path/to/{{section}}.{{length}}.md`, component, 'njk,md' %} {% endfor %} </code></pre> <p>Nothing programmatically complex here; just harnessing agreed naming conventions.</p> <h2>Making a little go a long way</h2> <p>Concepts like relationships, contribution, and installation don’t just apply to components. They’re generic functions of documentation. With care, these can be defined for use across any documentation pages and any documentation projects. That’s where a functional approach to documentation is powerful.</p> <p>Let’s look again at the <code>order</code> configuration we defined earlier.</p> <pre><code>order: - related - installation - contribute </code></pre> <p>This doesn’t just define the order of the sections but which sections are included in the first place. The <code>contribute</code> part could be taken away, or a <code>demo</code> section could be included.</p> <p>With a library of generic functions at our disposal, new documentation structures can be created from vocabularies and grammars already agreed. You just have to set out the structure.</p> <p>In the following example, the component and pattern categories share many of the same functions. Why not reuse those functions across category lines?</p> <pre><code>component: - related - demo - installation - usage - contribute pattern: - related - illustration - usage - contribute </code></pre> <hr> <p>In a world of <em>“how ChatGPT can automatically write your docs / insulate your house / get you into astronaut school”</em> these ideas and proposals are modest and not entirely original. Some of you might be thinking, “I do that already!” That's okay, I’m just a fan.</p> <p>As with programming, all documentation is somewhat functional. Language itself has functional/reusable parts, like expressions and idioms. But I want to make the case for <em>functional documentation</em>, where the functional part is embraced. And I'm always looking for new ways to do that.</p> <p><a href="https://amyhupe.co.uk/articles/modular-design-system-documentation/">Amy Hupe</a> and I are currently exploring this space and are looking for engagements with organisations interested in taking an ambitious approach to their design system documentation. Together we can offer a lot of strategic and technical expertise.</p> <p>You can find <a href="https://social.design.systems/@Amy_Hupe">Amy</a> and <a href="https://front-end.social/@heydon">I</a> on Mastodon. Alternatively, you can use the emails heydon[at]heydonworks.com or amy.l.hupe[at]gmail.com.</p> How I Accidentally Killed Several UX Designers https://heydonworks.com/article/how-i-accidentally-killed-several-ux-designers/ 2022-11-18T00:00:00.000Z https://heydonworks.com/article/how-i-accidentally-killed-several-ux-designers/ <p>Recently, I perpetrated a serious tactical error that resulted in a number of User Experience Designers (UXers) being found unexpectedly dead. As a front-end developer, this has done little to buoy my professional reputation.</p> <p>I first knew there was something wrong when I was unable to reach some of my regular contacts in the company’s UX discipline. I asked around but everyone I spoke to was equally perplexed.</p> <p>One colleague made the alarming observation that <em>every single one</em> of these absentees had omitted the obligatory <em>pill</em>: the agreed symbol for sick leave on one’s Slack profile. Whatever had befallen them, it was severe enough to deprioritize the typing of emoji.</p> <p>Then is got weirder. The UX Designers I <em>could</em> reach… started becoming unreachable too. Not a pill emoji in sight. Had Elon Musk bought the company? Was this the first round of redundancies-at-random?</p> <p>The next thing that happened I’ll take to my grave (not literally). Someone—whose name I didn’t recognize from the email notification—shared their Figma project to me. This project consisted of a single image with a line of accompanying text. The image showed a person’s face, horrifically contorted in terror and seemingly drained of blood, and the text (Roboto, Thin 100, Slate Grey) used the active voice recommended by our style guide: <em>“You did this</em>.”</p> <p>What had I done? Was I really guilty of this horror? And why was this being shared to me in Figma, I thought we had agreed to stick with Sketch for the time being? It’s not like I’m team Sketch or anything, I just think the transition will put pressure on resources at a critical time?</p> <p>The next day: Another notification. Another unfamiliar name. Another Figma project. This time it contained a video (supported for files in <strong>Education</strong>, <strong>Professional</strong>, <strong>Organization</strong>, or <strong>Enterprise</strong> teams). The video showed a figure standing at a desk, in front of an open Macbook, with their head cut off. Cut off by the frame, I mean, not by an axe or something like that.</p> <p>The figure presses a few keys and there’s a pause. Suddenly, their body stiffens and they begin to shake, as if trying to escape the grasp of a demon. A burst of esoteric words and phrases cascades from their mouth. I can make out <em>“curly brace”</em>, <em>“const”</em>, and <em>“triple equals”</em>.</p> <p>With the head still out of shot, I’m spared the subject’s face going all <em>Ringu</em> and whatnot. But I am subjected to footage of their trousers falling down and their legs catching on fire, which is something that is not supposed to happen.</p> <p>It’s unclear to me why anyone would be filming this or why they wouldn’t put their phone down to help someone in such obvious discomfort (and I <em>implore</em> you not to dwell on this part too much because it might start to resemble a plot hole).</p> <p><strong>But what <em>did</em> become clear to me was my mistake</strong>. Just before the disappearances, followed by the (really quite annoying) Figma email notification noise, I had re-documented some of our components. And I had committed the <strong>cardinal sin</strong> of documenting high-level design <em>and</em> technical implementation details <strong><em>next to each other, in the same page!</em></strong></p> <p>Now, whenever a UX designer arrives at the documentation, they are <em>viscerally subjected</em> to content that is not, <em>strictly speaking</em>, intended for them, at least not in their <em>current prescribed role, preconceived as “non-technical”</em>, even though it may be somewhat <em>useful for context</em>, as apprehended <em>in whole or in part</em>.</p> <p>As I curse the human brain’s fundamental inability to either <em>automatically filter out information it doesn’t find relevant</em> (which is actually something it does all the time), process simple labels like <em>“Installation”</em> or <em>“Code example”</em>, or <em>appreciate form and function as two sides of the same coin</em> I hear my phone ring just once (because after the first ring I decide to answer it).</p> <p><em>“Fool. Don’t you know that when you become a UX designer you forfeit the ability to speak the (un)ancient tongues?”</em><br> <em>“No, I’m a developer.”</em><br> <em>“Oh I’m sorry, I didn’t mean to assume you aren’t technically minded. Anyway byeee—”</em><br> <em>“Wait, if you forfeit the ability to read code, which is what I think you were saying, just in a more insufferable way, what do you get in return?”</em><br> <em>“Ahahahaha but that is the whole curse! <strong>You get nothing</strong>.”</em><br> <em>“Yikes. I’m not sure I want the story to end this way. Now it sounds like the author is taking a stab at UX Designers when really they’re defending their ability to demarcate and/or appreciate technical information.”</em><br> <em>“Sure.”</em></p> I Can’t Breathe https://heydonworks.com/article/i-cant-breathe/ 2022-01-26T00:00:00.000Z https://heydonworks.com/article/i-cant-breathe/ <p>Facebook memes taught me that, instead of facing my fear of needles, I could instead pretend I conscientiously object to vaccination programs, now my lungs are riddled with Covid and <strong>I can’t breathe</strong>.</p> <p>Sitting in my legally parked car eating a zinger burger was such an affront to the existence of an off-duty klansman that he put his boot on my neck and now <strong>I can’t breathe</strong>.</p> <p>I wiggled my little hedgehog nose into a plastic bag because vine fucking tomatoes have to be hermetically sealed for sale or a petrochemical heir won’t be able to afford his 17th Lamborghini and now <strong>I can’t breathe</strong>.</p> <p>My employer reclassified my job as a hobby and hobbies don’t come with sick pay or medical insurance, so now I’m living in a loophole, sat in an unheated flat cultivating pneumonia and <strong>I can’t breathe</strong>.</p> <p>A couple of breeders 100km upwind thought a pyrotechnic was the best way to communicate that their newly minted child comes with its own penis, now I’m chocking down burnt tree and <strong>I can’t breathe</strong>.</p> <p>I’m reading about all this chaos and misery and greed and sickness and it feels like it’s closing in around me, getting nearer every day and it feels like my throat is closing up and <strong>I can’t breathe</strong>.</p> Libertarianism Is Not What You Think https://heydonworks.com/article/your-libertarianism-isnt-what-you-think/ 2020-08-29T00:00:00.000Z https://heydonworks.com/article/your-libertarianism-isnt-what-you-think/ <p>I meet a lot of people who describe themselves as libertarian. When they learn I have socialist inclinations, they imagine that places us at either end of some political spectrum or other. That’s not the case.</p> <p>The term <em>libertarian</em> comes from the mid 19th century and a French communist called Joseph Déjacque. It’s fair to say most self-styled libertarians are not, wittingly, taking their cues from French communists. People who, not to put too fine a point on it, are communists (egad!). And, let’s not forget, French (double egad!). So what’s going on there?</p> <p>Propaganda, mostly. In the mid 20th century, some 100 or so years later, capitalists (and their enablers) looking for a legitimating philosophical framework for their activities (read: lobbying) co-opted the term from The Left™. Now we have left-libertarianism (OG libertarianism) and the equally clumsily named right-libertarianism (rich nonce libertarianism). But they call it simply <em>libertarianism</em>, naturally.</p> <p>Right-libertarianism isn’t about the liberation of the masses any more than Christianity is about the canonization of the masses. Like left-libertarianism, right-libertarianism is anti-authoritarian <em>but</em> specifically from the perspective of someone who wants the liberty to make your children morbidly obese then sell them an array of poorly assembled assault rifles.</p> <p>So why do people subscribe to right-libertarianism, thereby doing PR for the kind of people who’d kill their children for a few bucks? Because part of right-libertarian propaganda (and it <em>is</em> propaganda if it’s getting you to support something that isn’t in your interest) is to characterize liberty as fundamentally incompatible with socialism or communism. You either have liberty, and have to accept the cruel excesses of capitalism, or you have communism and the state controlling every aspect of your life. That’s what they say. Considering Marx envisioned communism to arise from the eradication of the state, this is some weapons-grade gaslighting.</p> <p>Most libertarians I speak to are people who simply don’t want to be forced to do things they don’t want to do, by people who should have no authority over them. I’m 100% with them on that. But you have to consider the protagonists and the power dynamics involved when this sentiment comes anywhere near the realm of reality.</p> <p>Diminished government for capitalists means diminished regulation, accountability, responsibility towards society. Where capitalism looms large, <em>just</em> fighting for a small government amounts to fighting <em>for capitalists</em> and their ability to take the piss out of you and the society you are a part of. They know this, hence their colonization of your notion of ‘liberty’. To use the current vernacular, they want to count on you being a <em>useful idiot</em>.</p> <p>You are not a capitalist. If you are employed, even if you are self-employed, you are not a capitalist. Unless you are exploiting people and resources for personal gain <em>at scale</em>, you are not a capitalist. This is the first thing you need to understand.</p> <p>The second part is this: supporting capitalism, or otherwise aligning yourself with it, is not a necessary step in claiming your individual liberty. Quite the opposite. That an ideology founded on slavery and profiting from mass incarceration has been able to convince so many people this <em>is</em> the case? It just goes to show they have far too much power over us already.</p> <p>Most importantly, you have to understand that an <em>“every man for themselves”</em> idea of liberty—aside from being gender specific—is naïve. Bad actors will always fill the power vacuum left by a dismantled state. What left-libertarians (libertarian socialists; anarcho-socialists) have to consider is how we should co-operate and collaborate in such a way that we only empower each other.</p> <blockquote> <p>In order to build democratic “proletarian power,” we need to build alternative, democratic institutions that reinforce one another and, more broadly, a democratic economic base. — <a href="https://blacksocialists.us/dual-power-map"><strong>Black Socialists in America</strong></a></p> </blockquote> <p>For the time being, if you are not interested in being arrested for <em>either</em> political dissent <em>or</em> someone’s bottom line, it’s likely your libertarianism is more to the left than you might have supposed.</p> Shit yourself https://heydonworks.com/article/shit-yourself/ 2020-07-19T00:00:00.000Z https://heydonworks.com/article/shit-yourself/ <p>“Shit yourself.”</p> <p>The voice startles me, being unaccompanied by a face.</p> <p>“Go on, shit yourself.”</p> <p>I turn towards the sound, and find a man, about my age, fixing me with an insistent stare.</p> <p>“Well?”</p> <p>“I’m sorry, have you mistaken me for—”</p> <p>“No time for chat, only time for shitting yourself,” he spits.</p> <p>“I don’t want to shit myself?” I reply, the heavy absurdity of the words leaving my mouth slowing my meter.</p> <p>“Ridiculous. How do you know unless you’ve tried?”</p> <p>Somehow this gives me pause. But I’m not sure what the pause is for: forming an adequate retort, preparing to laugh, or making my excuses. It seems dangerous to laugh at a stranger imploring you to shit yourself.</p> <p>“Listen, I don’t know what sort of—”</p> <p>“Shit. Yourself. Shit yourself. It’s simple.”</p> <p>Simple? Is simplicity enough? Just because it’s easy to... wait! Why am I reasoning with this? It’s silly.</p> <p>“Look, I don’t know who you are, but it’s pretty well established that—”</p> <p>“Yeah, yeah. Everyone says <em>not</em> to shit yourself. You think I haven’t heard that one before?”</p> <p>Wait. How many people has he been telling to shit themselves? And who? And why am I still trying to grapple with this nonsense? That voice again.</p> <p>“Look, you can’t just go through life avoiding what others’ tell you to. Just because 99% of people say shitting yourself is bad, doesn’t mean it’s true does it? <em>Argumentum ad populum</em>, mate.”</p> <p>I mean... technically he is right there. There’s more to it than that, of course! But on that specific point... in terms of...</p> <p>“Well?!” His voice coarsens as the urgency increases. He’s hitting his wrist where his watch would have lived.</p> <p>“Look, it’s not that. It’s just... well... it’s just <em>obviously</em> not a good...”</p> <p>“Oh! Obvious, is it?” comes a cruel laugh. “Was the theory of special relativity just OBVIOUS? What about microcomputing? Would have just been OBVIOUS to you, I suppose.”</p> <p>“What? Microcomputing is clearly not the same as—”</p> <p>“Biased! Shit yourself.”</p> <p>“Look, babies shit—”</p> <p>“Anecdotal! Shit yourself.”</p> <p>“What? Who the hell <em>are</em> you anyw—”</p> <p>“Ad hominem! Shit yourself.”</p> <p>“Fine!” I shout, and in a confusion of defiance and compliance I make it happen. I put an end to it. And as I do so, I watch his face soften, the creases dissolving one by one.</p> <p>“Thanks, mate,” he beams, patting my shoulder. “I didn’t want to be the only one with shat trousers at this wedding. Which side are you, anyway? Bride or groom?”</p> <p>“Bride...” I hear myself say, my mind departing my head.</p> <p>“Oh, same!”</p> <p>A ghost, I join him up the steps into the chapel, arriving precisely on time.</p> Easily Use Design Tokens In Eleventy https://heydonworks.com/article/design-tokens-in-eleventy/ 2020-05-16T00:00:00.000Z https://heydonworks.com/article/design-tokens-in-eleventy/ <p>This is going to be a very short article, because it turns out working with <a href="https://24ways.org/2019/design-tokens-and-component-based-design/">design tokens</a> in <a href="https://www.11ty.dev/">Eleventy</a> is a <em>partition of urine</em> (very easy).</p> <p>Eleventy’s root <code>/_data</code> folder lets you define some <a href="https://www.11ty.dev/docs/data-global/">global (you guessed it) <em>data</em></a> that can be accessed in templates anywhere in the site/project. So, if I create a <code>tokens.json</code> file in my <code>_data</code> folder with a <code>colorLight</code> property, I can interpolate it as <code>{{ tokens.colorLight }}</code> in any of my nunjucks templates.</p> <p>Here’s <code>/_data/tokens.json</code>:</p> <pre><code>{ &quot;colorLight&quot;: &quot;#eee&quot;, &quot;colorDark&quot;: &quot;#111&quot; } </code></pre> <p>Ordinarily you would use nunjucks (<a href="https://www.11ty.dev/docs/templates/">other templating engines are available</a>) to render HTML. But Eleventy allows me to set <a href="https://www.11ty.dev/docs/permalinks/">permalinks</a> with any file extension. So getting these values into my CSS just means creating a <code>theme.njk</code> file and telling Eleventy to output it at <code>css/theme.css</code>.</p> <p>Here’s <code>/css/theme.njk</code>:</p> <pre><code>--- permalink: &quot;css/theme.css&quot; --- :root { --colorLight: {{ tokens.colorLight }}; --colorDark: {{ tokens.colorDark }}; } </code></pre> <p>These custom properties would, of course, be referenced throughout the rest of my CSS.</p> <p>You may ask, <em>“if you’re using custom properties anyway, why not just define your tokens there?”</em> One reason is that it’s simpler to reuse or generate JSON than CSS. Usually, design tokens are canonically JSON. The more pertinent reason is that the whole point of design tokens is <em>interoperability</em>; they should be usable across different kinds of files. Since I want my site/app to be a PWA (Progressive Web App) I’ll be wanting to share these same tokens to my <code>manifest.json</code> file.</p> <p>Here’s the (abridged) <code>/manifest.json</code>:</p> <pre><code>--- permalink: &quot;manifest.json&quot; --- { &quot;theme_color&quot;: &quot;{{ tokens.colorDark }}&quot;, &quot;background_color&quot;: &quot;{{ tokens.colorLight }}&quot; } </code></pre> <p>Netlify CMS allows one to alter the properties of data files directly, using the <a href="https://www.netlifycms.org/docs/collection-types/#file-collections">file collection type</a>.</p> <p>Inside Netlify CMS’s <code>config.yml</code>:</p> <pre><code>- label: &quot;Theme&quot; name: &quot;theme&quot; file: &quot;/_data/tokens.json&quot; fields: - { label: &quot;Light color&quot;, name: colorLight, widget: string } - { label: &quot;Dark color&quot;, name: colorDark, widget: string } </code></pre> <p>So there it is: an extremely simple setup for using design tokens in Eleventy, with content management support on top. And you can’t call these design tokens <em>“spicy Sass variables”</em> because I didn’t use Sass, so there.</p> From Wordpress To Eleventy With Ease https://heydonworks.com/article/wordpress-to-eleventy/ 2020-04-20T00:00:00.000Z https://heydonworks.com/article/wordpress-to-eleventy/ <p>I recently converted this site from an old Wordpress to <a href="https://www.11ty.dev/">Eleventy</a>. I then promised I’d share how I did it, because it really doesn’t have to be difficult. In fact, with the small node script to follow, you should have everything set up in about 5 minutes.</p> <h2>Step 1: Get the old Wordpress data</h2> <p>First you need to get your post content—and associated media—from Wordpress. Since I’ve obliterated the original Wordpress site now, I can’t retrace quite how I did this. I remember it being very straightforward. To get all of my Wordpress post data as JSON, I either used the core export functionality or a popular plugin. Or maybe the <a href="https://dev.to/jackedwardlyons/how-to-get-all-wordpress-posts-from-the-wp-api-with-javascript-3j48">Wordpress REST API</a>. If I could manage it, you shouldn’t have much trouble. To get all the images, I almost certainly used <a href="https://wordpress.org/plugins/export-media-library/">a plugin like this one</a>.</p> <p>In any case, you should end up with a JSON file full of stuff that looks something like this…</p> <pre><code>... &quot;post&quot;: { &quot;ID&quot;: 14, &quot;post_author&quot;: &quot;1&quot;, &quot;post_date&quot;: &quot;2014-08-01 00:00:09&quot;, &quot;post_date_gmt&quot;: &quot;2014-08-01 00:00:09&quot;, &quot;post_content&quot;: &quot;&lt;p&gt;Hi everybody! I've just done a lot of cocaine on the company expense account...&quot;, &quot;post_title&quot;: &quot;Reinventing The Hyperlink&quot;, ... </code></pre> <p>… and a directory of media with subfolders named after years, like:</p> <ul> <li>📂 2011</li> <li>📂 2012</li> <li>📂 2013</li> <li>📂 2014</li> <li>etc.</li> </ul> <p>You’ll want to unzip this exported media archive into wherever the rest of your Eleventy images go.</p> <h2>Step 2: JSON to markdown plus <a href="https://www.11ty.dev/docs/data-frontmatter/">Front Matter</a></h2> <p>This is where you can use my simple node script. Here it is in its entirety, with notes to follow:</p> <pre><code>const transformAndWriteToFile = require('json-to-frontmatter-markdown').default; const wordpressData = require(__dirname + '/wordpress.json'); const slugify = require('slugify'); const posts = wordpressData.post.posts; Object.keys(posts).forEach((p, i) =&gt; { let post = posts[p].post; transformAndWriteToFile({ frontmatterMarkdown: { frontmatter: [ { title: post.post_title }, { date: post.post_date.split(' ')[0] }, { permalink: `article/${slugify(post.post_title).toLowerCase()}/index.html` } ], body: post.post_content.replace(/http:\/\/www.heydonworks.com\/wp-content\/uploads/g, '/images') }, path: './src/posts', fileName: `${slugify(post.post_title).toLowerCase()}.md` }) }) </code></pre> <ol> <li>Take a note of the <code>require</code> lines. You will have to <code>npm install</code> (or Yarn, whatever) the <code>json-to-frontmatter-markdown</code> and <code>slugify</code> dependencies. The <code>wordpress.json</code> file is the JSON data I exported in <strong>Step 1: Get the old Wordpress data</strong>.</li> <li>The <code>frontmatter</code> part takes the properties I’m interested in from each post and converts them to front matter values. The permalink structure I happen to use starts with <code>/article</code>. By salvaging this structure from the original site, I could avoid doing rewrites/redirects.</li> <li>The <code>body</code> part writes the post content but, critically, re-paths each of the images to use the local Eleventy URL</li> <li>The <code>path</code> is where to write the file (presumably where all my non-legacy posts also reside)</li> <li>Finally, <code>fileName</code> actually names the markdown file itself, slugifying the <code>post_title</code> value as my Wordpress site was instructed to do.</li> </ol> <h2>Step 3: Run the script</h2> <p>You can set up an npm script if you really must, but since I knew I’d only run this once, I just hit <code>node wordpress.js</code> (where <code>wordpress.js</code> is the name of the script file, and it’s in the root of the directory).</p> <h2>Step 4: There is no step 4</h2> <p>This step doesn’t even exist. But it's worth noting that, on my site, I split my old Wordpress posts between <em><a href="https://heydonworks.com/archive/">archive</a></em> and <em><a href="https://heydonworks.com/best-of/">best</a></em> (my best posts) directories. Each article (including each new article) on my site has an <code>article/slug-here</code> URL structure, but belongs to one of the <em>latest</em>, <em>best</em>, or <em>archive</em> <a href="https://www.11ty.dev/docs/collections/">collections</a>.</p> <p>In Eleventy, you can set the collection per-post by adding a <code>tags</code> property to its front matter. But it’s less verbose to to add a data file to the appropriate directory instead. For example, my <em>latest</em> posts go in the <code>/latest</code> directory, which contains a <code>latest.json</code> file with the line <code>&quot;tags&quot;: &quot;latest&quot;</code>.</p> The Random Link In The Age Of Static Sites https://heydonworks.com/article/the-random-link/ 2020-04-10T00:00:00.000Z https://heydonworks.com/article/the-random-link/ <p>I just released <a href="https://github.com/Heydon/ga11ery"><strong>Ga11ery</strong></a>, a minimalist kit for sharing photos, illustrations, or your web comic. I figured a lot of folks are diving into their art right now, as a way to find purpose and peace during isolation. I wanted to make it as easy as possible to share the output.</p> <p><a href="https://github.com/Heydon/ga11ery"><strong>Ga11ery</strong></a>-spawned sites are built with <a href="https://www.11ty.dev/">Eleventy</a> and managed using <a href="https://www.netlifycms.org/">Netlify CMS</a>. Using static site generation presented an interesting challenge when it came to implementing the ubiquitous web comic “random link”.</p> <p>I love the random link, and shudder to think how many times I've pressed any one of the following iconic examples. Can you identify them all? Answers to follow.</p> <figure> <img src="https://heydonworks.com/images/randoms.png" alt="Top left is random written in small caps, on a grey blue button with a box shadow. Top right is a hand drawn random symbol using intersecting arrows. Bottom left is random written in a thick, italicized cursive. Bottom right is random in cursive, white on an orange button"> </figure> <p>(<strong>Answers:</strong> Reading from top left, <em><a href="https://xkcd.com/">xkcd</a></em>, <em><a href="http://www.poorlydrawnlines.com/">Poorly Drawn Lines</a></em>, <em><a href="http://gunshowcomic.com/">Gun Show</a></em>, <em><a href="https://www.smbc-comics.com/">Saturday Morning Breakfast Cereal</a></em>)</p> <p>Sites like <strong>xkcd</strong> use REST and a <code>/random/comic</code> endpoint. When you follow this URL, the server is told to find a random resource and return it. Actually, that's how most web comics seem to do it. But you need things like a database and a server-side language running (to do the randomization part) for that. It's very 2008, and there have to be client/server “handshakes” and all that sort of touchy-feely stuff we’ve been habituated to abhor during this time of social distancing.</p> <p>How could I achieve the same thing for a static site? And could I make it more efficient?</p> <p>For <a href="https://github.com/Heydon/ga11ery"><strong>Ga11ery</strong></a>, I was looking into Eleventy’s <a href="https://www.11ty.dev/docs/pagination/">pagination feature</a> for the previous/next/first/last navigation. Honestly, I found it a bit confusing, which was undoubtedly mostly my own issue. But then Mia Suzanne kindly stepped in with some <a href="https://twitter.com/MiriSuzanne/status/1246111798119378944?s=20">lateral thinking</a>. On her personal site, she used a <a href="https://www.11ty.dev/docs/filters/">template filter</a> to provision her previous and next links instead.</p> <p>At build time, and for each page, the filter code identifies the appropriate previous and next links based on the index of said page in the <a href="https://www.11ty.dev/docs/collections/">collection</a> array. A snippet of Mia’s code for illustration:</p> <pre><code class="language-js">if (pageIndex !== -1) { return { prev: collection[pageIndex - 1] || null, next: collection[pageIndex + 1] || null, }; } </code></pre> <p>To provide a basic random link, I just had to use a bit of <code>Math.random</code> code in there (after removing the current page from the collection, or course):</p> <pre><code class="language-js">const others = collection.filter(item =&gt; item.url !== page.url); const random = others[Math.floor(Math.random() * others.length)]; </code></pre> <p>I like this, because it does the job without relying on server logic <em>or</em> client-side JavaScript. The joy of running JavaScript at build time instead! But there is a potential issue: If <strong>page (a)</strong> “randomly” ends up pointing at <strong>page (b)</strong> and <strong>page (b)</strong> “randomly” ends up pointing at <strong>page (a)</strong>, the user gets stuck in a loop between the two pages.</p> <figure> <img src="https://heydonworks.com/images/loop.png" alt="Page a points at page b and vice versa"> </figure> <p>So, instead, what if I treated this okay-but-less-than-ideal implementation for the basic experience and used (wait for it) <em>progressive enhancement</em> to improve upon it? There’s no harm in using a little client-side JavaScript so long as…</p> <ol> <li>Things still work pretty well where it doesn’t load</li> <li>It doesn’t depend on a massive library being parsed just to do its one little job</li> </ol> <p>It didn’t take long for me to realize I could embed a comma-separated string of all the collection pages’ URLs into my built HTML (<code>allLinks</code> in the code to follow). In the browser, this string could then be converted into an array. No, this isn’t some weird ES2027 syntax; it’s just an ugly hybrid of JS and nunjucks:</p> <pre><code class="language-js"> const allLinks = '{{ allLinks }}'.split(','); const randomLink = allLinks[Math.floor(Math.random() * allLinks.length)]; </code></pre> <p>Then I thought, “oh shit”. If that collection got really large—into its thousands, say—I‘d be embedding a huge string of crap into every page of the site. Not to mention my little <code>Math.random</code> line would have to work on a large set of data. Arguably, this would still be more efficient than the whole PHP/handshake/relay/SQL rigamarole, but do I really <em>need</em> all this data just to avoid creating that infinite loop?</p> <p>No. I only need an array of two or three. I spoiled myself with five in the end. Back in the filter code:</p> <pre><code class="language-js">const shuffle = (array) =&gt; { const clone = array.slice(0); for (let i = clone.length - 1; i &gt; 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [clone[i], clone[j]] = [clone[j], clone[i]]; } return clone; } const others = collection.filter(item =&gt; item.url !== page.url); const randomFive = shuffle(others).slice(0, 5).map(other =&gt; other.url).join(','); </code></pre> <p>Probably the most intensive operation here is the <code>shuffle</code> function. But that happens at build time, so I don’t care: <strong>the user is unaffected</strong>. On the client, I just need to pick one random item from five (big deal) and enhance the random link to point to that location rather than the build-rendered one. At first, I did it like this:</p> <pre><code class="language-js"> &lt;script type=&quot;module&quot;&gt; (function() { const randomBtn = document.querySelector('.random'); const randomFive = '{{ links.randomFive }}'.split(','); const randomNew = randomFive[Math.floor(Math.random() * randomFive.length)]; randomBtn.addEventListener('click', e =&gt; { e.preventDefault(); window.location.href = randomNew; }); })(); &lt;/script&gt; </code></pre> <ul> <li><strong>The good parts:</strong> It’s a tiny, dependency free script, using <code>type=&quot;module&quot;</code> so it only executes in modern browsers. No transpilation or polyfilling required. Older browsers ignore <code>type=&quot;module&quot;</code> JavaScript and comfortably fall back to the basic, build-provisioned experience.</li> <li><strong>The bad parts:</strong> When a user hovers on the link, they'll see a location in the corner of their browser that is deceptive. The <code>window.location.href</code> line will take them somewhere else. Also, I’d really rather avoid adding an event listener if I can help it.</li> </ul> <p>The shorter, better version just replacing the link’s <code>href</code>:</p> <pre><code class="language-js"> &lt;script type=&quot;module&quot;&gt; (function() { const randomBtn = document.querySelector('.random'); const randomFive = '{{ links.randomFive }}'.split(','); const randomNew = randomFive[Math.floor(Math.random() * randomFive.length)]; randomBtn.href = randomNew; })(); &lt;/script&gt; </code></pre> <p>I’m confident this solution is more performant than using REST, PHP, and database queries (or similar) and I’m certain it’s more efficient than rendering the entire site on the client. The reason I wrote it up is because it’s a good example of the kind of problem I like to solve, and how I like to solve it. Build-rendered beats server-rendered beats client-rendered. Where you delegate the complex logic and data-lifting to the build (using a <a href="https://www.11ty.dev/docs/filters/">template filter</a>, in this case) and only <em>supplement</em> this using client-side scripts, you can begin to create engaging experiences with barely any loss of performance.</p> Marxian Alienation And Web Development https://heydonworks.com/article/marxian-alienation-and-web-development/ 2020-03-25T00:00:00.000Z https://heydonworks.com/article/marxian-alienation-and-web-development/ <p>We who work in web development are getting more comfortable with talking about burnout. This is a good thing, or it would be if we were prepared to acknowledge what burnout <em>really</em> represents.</p> <p>Burnout is not just overwork, or the ensuing exhaustion. Some of you will already know this. It is also not failing, or not getting anywhere. Because some things are worth trying—and are fulfilling to try—even if they don't succeed.</p> <p>Burnout is where your work isn't yours. It's when you give yourself, but what you give is not allowed to be you. Your energy, your passion, your <em>value</em> co-opted, corrupted, and erased.</p> <p>If you work in a capitalist organization, you will experience burnout. You may be well-paid, work with a diverse and friendly team, and feel secure. But so long as what you are doing is, ultimately, being ground down into mere profit? The burnout is coming.</p> <p>Burnout is what Marx called alienation. It's when a worker becomes estranged from their work. It sounds like a big, grand thing, but it happens every day, in small ways. As a web designer or developer burnout comes calling when you try to do <em>good</em> work, but you're not allowed.</p> <ul> <li>You want to make the app more performant; your boss wants to fill it full of third party trackers</li> <li>You want to make the app more accessible; your boss wants you to focus on the ‘able market’ instead</li> <li>You want to word the app more clearly; your boss wants to <em>trick</em> users with misleading language</li> </ul> <p>If you are a good developer, and a good person, asked to do shit work, you will burn out. You will feel yourself turning into burning shit.</p> <p>It's not a nice experience, but it's not an uncommon one. In fact, it's one of the more persistent and prevalent features of capitalism. It's simply not possible to reconcile your desire to do good, for your users, with the organization's monomaniacal desire to siphon money to shareholders, no matter the costs or consequences.</p> <p>And 100,000 ping pong tables, awards, charitable donations, and free lunches won't make up for one jot of it. If you are working for a capitalist organization, you are working for a bad one. It doesn't make <em>you</em> a capitalist, or a bad person. But it will make you vulnerable to burnout.</p> <p>If you struggle with burnout, you are not alone. It's the ones who don't struggle with it, who need no more than a big paycheck and a pat on the back, who bother me.</p> <p>But there's enough of us that we can ignore them. In threads, forums, meetups, and conferences around the world you'll find developers, people, who've had these same experiences, and felt this way. By finding each other, and working together, we can not only make a better web, but a better world. One we can be proud to have worked on.</p> <p>For now, let's just keep on talking. We have a really good, public, unproprietary, and free means of doing that.</p> <hr> <p>Side note: I have been compiling my grievances (which are many) about capitalism, and its current state, into an accessible illustrated guide, called <em><strong><a href="https://www.indiegogo.com/projects/bye-bye-billionaires/x/23096336#/">Bye Bye, Billionaires</a></strong></em>. It's up on <a href="https://www.indiegogo.com/projects/bye-bye-billionaires/x/23096336#/">Indiegogo</a>.</p> The Word User Is Fine https://heydonworks.com/article/the-word-user-is-fine/ 2020-01-09T00:00:00.000Z https://heydonworks.com/article/the-word-user-is-fine/ <p>Words are powerful things, and some wield an exclusively destructive power. Given the recent spate of aging comedians—mostly Pythons—adopting the absurd <em>alt right</em> notion that discriminatory language is a necessary component of free expression, it was a relief to <a href="https://open.spotify.com/episode/5U3LZtH4p2HzOAuH2MagS2?si=g_gx1rCRSOuy1vdk7zpL0A">hear Billy Connolly talking to Adam Buxton</a> about the N-word, and his distaste for it.</p> <p>Famed for his candid, sometimes luridly vulgar skits, Connolly is nevertheless aware that the accumulated connotations attached to this and similar words make them unbearable. He challenges anyone who claims otherwise to think of a redeemable sentence that uses the word. It’s not that you literally can’t use it; but it’s a better decision, and you’re a better person, not to.</p> <p>Unfortunately, when it comes to discrimination and discriminatory language, we are good at telling people that it’s bad, but not at explaining why that is so. If you don’t appreciate that certain words help to dehumanize people, marking them as deserving of manifest forms of discrimination, then you can be persuaded to see a moderation of language as an arbitrary infringement on your precious vocabulary. A recent uptick in (performative) racism can largely be attributed to this ideology, I would suggest. Whether you actually see certain people as inferior, or you’re just edge-lording at the expense of those people’s dignity, is the same in terms of impact.</p> <p>Some words can simply “get in the sea”, to use the vernacular, but others might be less harmful than our considerable efforts to police them would indicate.</p> <p>Take the word ’user’, as in the operator of a digital product and its interface. Some dislike this term (and, to a lesser extent, the more specific ‘end-user’) because they feel it is reductive, or even dehumanizing. The following is from <a href="http://www.iamnotauser.com/index.php/why-not-a-user/">iamnotauser.com</a>:</p> <blockquote> <p>Well, first of all let’s get rid off [sic] the word user and let’s talk about people… Because user implies something totally internal: I’m a user, I want to use this machine, so let’s use it. This is a utilitarian/task cognitive approach to interaction design, a rather medieval kind of approach.</p> </blockquote> <p>I have trouble with this, on a number of levels — not least of all: why should we consign utility to the medieval age? That seems… odd. But also, where utility—and <em>usability</em>—are virtues, how do we reconcile that with considering ‘user’ a derogatory term?</p> <p>Many cite the drug usage connotation of the term (<em>heroin user</em>) helping to paint the person using the product as passive, rather than an empowered participant. If you are creating a toxic and addictive product/interface, comparable to a drug, may I suggest you <em>stop</em> doing that, rather than fussing over removing terminology that betrays your ill intentions.</p> <p>A person who <em>uses</em> other people is the one in control, and it was because terms like ‘patient’ and ‘customer’ were deemed too passive that—ironically—we began to use the term ‘service user’ to describe people in the UK accessing mental health services and the like.</p> <p>Is user always the best term? Certainly not. Depending on the context and the nature of the product, terms like ‘poster‘, ‘team member‘, ‘contributor’, or similar might do better. But where we have to use the term <em>person</em> to remind ourselves that the <em>person</em> using our product is more than <em>just</em> a <em>user</em> of our product, that says more about the arrogance with which we approach product design than any tokenistic attempts at sounding humane can ever make up for.</p> <p>The term <em>user</em> is fine, just don’t sell meth.</p> Listen To Me And Not Google https://heydonworks.com/article/listen-to-me-not-google/ 2020-01-09T00:00:00.000Z https://heydonworks.com/article/listen-to-me-not-google/ <p>A few months ago, I was consulting an organization; helping them to make their interfaces more inclusive. I tend to be engaged because I have experience in accessible interaction design, and the implementation of technical accessibility provisions. But the advice I offer is much more comprehensive, taking in the use of language, general usability, performance, and ethics.</p> <p>One of the first things that struck me in early reviews with the designers was their approach to the visual design of their input fields. Instead of enclosing the input text in a box—as user agents do by default—they had opted to present the field as a single line <em>upon</em> which people are expected to write.</p> <p>My advice was as follows (abridged): <em>“These do not look like input fields, and are therefore unlikely to be identified and used as such. In fact, they look like horizontal rules. I advise you to adopt a more conventional input design, wherein the field takes the form of an empty box into which input is supplied.”</em> Make a mental note of this advice, because it foreshadows the conclusion of this short article.</p> <blockquote> <p>Material Design is a visual language that synthesizes the classic principles of good design with the innovation of technology and science. — Google</p> </blockquote> <p>The designers were respectful of me, and amenable to my suggestions, but there was one sticking point: Google’s <a href="https://material.io/design/introduction/#principles"><strong>Material Design</strong></a> had established this approach to input design. While not stated explicitly, the implication was that this legitimated the pattern. It was not without precedent.</p> <p>I’ve always been uneasy about <strong>Material Design</strong>. I understand why Google would want to have their own design system, and I can even appreciate why organizations like Google would want to shout about that system, and how they developed it, as a PR exercise. But <strong>Material Design</strong> is for <em>you</em> to use. It asks you to design your products as Google would; to make your design work look and feel like Google’s. Why would you want to do that? Then again this is me talking, and I’m the sort of person who refuses to wear a T-shirt with Nike™ emblazoned on it, because I think being a mobile billboard is rather a reductive mode of human existence.</p> <p>In any case, the Google citation made my case more difficult. And although the organization <em>did</em> adopt my advice in the end, in the absence of specific research data to back up my claims, it was what I said versus what Google say, which is a precarious position to be in. Not on a completely unrelated note, you should look up the <a href="https://en.wikipedia.org/wiki/Argument_from_authority">appeal to authority</a> argument, or <em>argumentum ad verecundiam</em>.</p> <p>Here’s the thing: <strong>Google are not successful because they know how to design inputs</strong>. Astonishing, I know, but Google are not the artisan purveyors of <em>fine forms</em> for which you may have mistaken them. They make their money by other means. Which brings us to the denouement…</p> <p>A little while ago, my attention was drawn to an article written in Google Design’s own gentrified ghetto of Medium, entitled <a href="https://medium.com/google-design/the-evolution-of-material-designs-text-fields-603688b3fe03"><em>The Evolution Of Material Design’s Text Fields</em></a>.</p> <p>Imagine my complete lack of surprise to find Google’s research indicated, <em>“Enclosed text fields with a rectangular (box) shape performed better than those with a line affordance”</em>. Aghast, I was.</p> <p>This stung my eyes to read, but the best was yet to come: <em>“The line affordance under the old text fields was not clear to some users. The line was confused with a divider</em>.” <strong>I screamed</strong>. This spoke <em>directly</em> to the concern I had expressed months prior. It took Google hundreds of research participants to confirm what I already knew thanks to nothing more than <em>common sense</em>.</p> <p>There are, broadly speaking, two ways to approach research-based design. Only vast, trundling corporations like Google can survive the latter.</p> <ol> <li>Challenge conventions that appear to need improvement only, and test your assumptions regarding those changes with focused user research.</li> <li>Act completely randomly, then commission a large, expensive research study at a later date, after the damage of your irresponsible but influential design practices has already taken effect.</li> </ol> <p>At first, I took exception to the use of the term <em>evolution</em> in the Medium article’s title. Design is artificial selection if anything, since it’s guided by a designer’s hand. Except, perhaps design really isn’t always auteured at Google. When everyone is committed to your products already, you can just “throw stuff out there“ and see what survives. If so, that’s Google’s prerogative, but that doesn’t mean you should take their lead. You don’t have their kind of inertia to power through the mistakes you make.</p> <hr> <p>What is the point of this post? Is it just me saying, <strong>“I TOLD YOU SO”</strong> at the top of my voice? I do find it galling when a hugely successful company swoops in to intellectualize its own folly as some sort of insight, while smaller voices of reason continue to languish in relative obscurity. But it’s more than that. We have to stop confusing the excesses of capitalism with the hallmarks of quality. Sometimes Google aren’t better, they’re just more pervasive.</p> <p>There is an old episode of South Park wherein the Cartman character finds himself the proud owner of a coveted ‘trapper keeper’; a kind of personal organizer system used for school, in this case branded after the <em>Dawson’s Creek</em> television series. The trapper keeper mysteriously evolves over time, developing new and increasingly advanced features until it barely resembles a simple organizer system at all. Eventually, it is able to assimilate Cartman in a Cronenbergian fusion of silicone and flesh, wires and neurons. It escapes me why I bring this up.</p> Ambient Burnout https://heydonworks.com/article/burnout-and-ambient-music/ 2020-01-09T00:00:00.000Z https://heydonworks.com/article/burnout-and-ambient-music/ <p>In the lead-up to the UK’s last general election, I took it upon myself to campaign with my party, Labour. Most days for a few weeks this entailed going to people’s houses, trying to navigate their Murdochian talking points, and being scolded for trying to trick them into voting in their own interest.</p> <p>I anticipated this would be a demoralizing experience, and had arranged with my wife to go together on a holiday retreat the day following the vote. If we won, we’d be celebrating, but if we lost I could rest and recuperate. Reading, walking, reflecting on the good things, hopefully these activities would help me steel myself for Christmas.</p> <p>Our holiday ‘cottage’ was a converted radar tower, used in the war to detect approaching enemy submarines. Heavy ceiling-to-floor shutters opened to reveal the flat and empty Essex countryside. Flat and empty felt right, resonant, and it was a feeling I wanted to distill. In these circumstances, I always reach for a sequencer.</p> <p>The <a href="http://www.openculture.com/2019/07/the-therapeutic-benefits-of-ambient-music.html">therapeutic benefits of listening to ambient music</a> are well documented. If you’ve not tried listening to ambient music, you might expect it to make you feel drowsy or <em>chilled out</em>. My experience is different: it brings clarity and cohesion to the clatter of the world around me, helping me to find focus.</p> <p>Making ambient music helps me further. It’s partly because I’m not good at doing nothing, because it makes me feel guilty, so I tend to rest by taking up something creative. But I think it also has something to do with reclaiming a sense of control. Ambient music becomes the sound of what I see. In the radar tower, the oscillations of sounds and arpeggiations of notes that I’m creating <em>are</em> the twitching blades of grass in the sun beyond the forecourt of the tower. The ambience I’m creating <em>is</em> the environment in which I’m sitting. I come to peace with the world as I come to peace with myself.</p> <p>There are many ways to create ambient music. Some people work exclusively with synthesizer pads; others take prerecorded audio and obliterate it. I am only able to enjoy listening to the ambient music I create if it is new to me as I play it back. Recently, this has been a case of randomizing MIDI triggers within certain parameters.</p> <p>The following piece is just one piano chord, heavily reverberated and put through Logic’s built in MIDI arpeggiator. Note order is set to random, and the octave range 4. In addition, the ESX24 sampler fluctuates the pitch bend value, giving it that wavering, woozy feel.</p> <audio controls="" preload="metadata" src="https://heydonworks.com/artifacts/bleeding_piano.mp3"> <a href="https://heydonworks.com/artifacts/bleeding_piano.mp3">ambient piano track</a> </audio> Font Hacking https://heydonworks.com/article/font-hacking/ 2013-03-30T00:00:00.000Z https://heydonworks.com/article/font-hacking/ <p>What if I told you there was a way to radically alter your web pages without using images, javascript, proprietary CSS3 or any extra markup? What if I told you you didn't have to be an experienced typographer, you could do it for little more than 6Kb and that it would work in Internet Explorer 7? For free? Welcome to <strong>Font Hacking</strong>, my primer on extracting, deconstructing, altering and replacing letterforms. The workflow I shall be outlining can be used for good or for evil; artfully resculpting typefaces or brutally defacing them. I am going to give you the ability to do either.</p> <h2>Javascript Is For Losers</h2> <p>Granular control of web type is often made the responsibility of jQuery, which can yield some interesting results but is rather unwieldy. For instance, let's imagine I wanted to switch the font family of each ampersand throughout a page's worth of flow text. Taking the javascript route, I'd have to locate ampersands in each text node, replace each instance of "&" with <code>&lt;span class="ampersand-font"&gt;&lt;/span&gt;</code> then write the manipulated string back into &hellip; <strong>I've just lost the will to live</strong>. Not only is the javascript routine cumbersome, but we could be pulling in another whole webfont &mdash; which could far exceed 100K in size &mdash; just to sate our <strong>shameful ampersand fetish</strong>.</p> <figure><img src="https://heydonworks.com/images/1_ampersand.png" alt="A beautiful ampersand" class="alignnone size-full wp-image-125054"><figcaption>An ampersand I made in Inkscape. Mmmmmm.</figcaption></figure> <h3>Unicode Ranges?</h3> <p>Forgetting javascript, one might be attracted to the <code>unicode-range</code> property. You can supply <code>unicode-range</code> to <code>@font-face</code> blocks to hand pick the characters and character ranges that should be within the font's remit. Drew McLellan of <a href="http://grabaperch.com/">Perch</a> even wrote a <a href="http://24ways.org/2011/creating-custom-font-stacks-with-unicode-range/">24 Ways</a> post on the subject.</p> <p>There are a couple of major problems with this technique. Firstly, Firefox <em>still</em> doesn't seem to support the attribute. In fact, the <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=475891">last comment at bugzilla.mozilla.org</a> simply reads, "please fix this!" Even with the bug fixed, the necessity of loading a whole webfont just to cover a few characters remains. All the more reason why &hellip;</p> <h3>Subsetting Is For Winners</h3> <p>Subsetting is the practise of making a typeface from a subset of another typeface's character set. By eliminating all but the ampersand from a comprehensive character set we can create a new font <em>hundreds of times smaller</em>. This is a good thing. However, the <em>real</em> magic happens when we combine subsetting with <strong>font stacks</strong>, like so:</p> <pre> body { font-family: Ampersand, Georgia, serif; } </pre> <p>According to the law of font stacks, all characters not supported by "Ampersand" will defer to Georgia. No spans, no classes, no flaky properties, no javascript; just effortless inheritance. In addition, because the ampersand font we're incorporating is so small, there's no reason not to embed it directly into our CSS with a <a href="http://jonraasch.com/blog/css-data-uris-in-all-browsers">data URI</a>, saving ourselves the server request. The following output is what my ampersand looks like in Base64. It engorges its parent stylesheet by approximately 2.5K. Much worse things could happen, frankly.</p> <pre> <code>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 </code></pre> <p>Below is a demonstration using this one glyph ampersand font, with the CSS applied to a <code>contenteditable</code> <code>div</code>. Try typing some prose in the box, being sure to include an "&" here and there:</p> <style>div[contenteditable="true"]:focus {outline:2px solid #222; outline-offset: 0;}</style> <div contenteditable="true" style="border:2px solid #222; padding:1em; text-align:center; font-size:2.5em; font-family:ampersand, georgia, serif; line-height:1.25; margin:0.5em 0"> Type away & you'll see what I mean. </div> <p>Superimposing subsets of analphabetic characters and symbols from one font onto another is an elegant technique to personalize or improve your typography. However, instead of simply replacing characters in the master font, wouldn't it be <strong>more fun</strong> to locate and mutate the one font's existing letterforms? In the following tutorial, I shall be showing you how to use Inkscape and some subsetting to make a <strong>stencil font</strong> using Arial Bold.</p> <h2>Arial</h2> <p>Arial, as with all fonts created after the year 1989, is named for a character in the subaquatic Disney film, <em>The Little Mermaid</em>. Although Arial is the most notorious of post 1989 typefaces, <a href="http://www.dafont.com/arista.font">Arista</a> (dedicated to the mermaid protagonist's sister) and <a href="http://www.dafont.com/sebastian-font.font">Sebastián</a> (which shares its name with the film's dubiously Carribean decapod) are also worthy of note.</p> <figure><img src="https://heydonworks.com/images/little_mermaid.jpg" alt="Still from The Little Mermaid" width="300" height="213" class="alignnone size-medium wp-image-125076"> <figcaption>Ostensibly a film about the plight of an aspirational mermaid, The Little Mermaid is actually an allegory of the history of typographic design (image: <a href="http://www.flickr.com/photos/koiart66/">koiart71</a>)</figcaption> </figure> <p>These are all lies, of course. Ariel, the mermaid, isn't even spelled "Arial". In reality, Arial was created by a team of ten designers headed by Robin Nicholas in 1982, some seven years before <em>The Little Mermaid</em> would reach cinema screens and an astonishing eighteen years before its sequel, <em>The Little Mermaid 2: Back To The Sea</em>, would find its way directly onto video cassette. Arial doesn't really have a very colorful past and it's not really a very colorful font. In fact, Nicholas himself is <a href="http://www.monotypefonts.com/PDFs/Twenty20_080705.pdf">on record</a> describing it as "a generic sans serif; almost a bland sans serif".</p> <figure><img src="http://cdn.ilovetypography.com/img/gqr.gif" alt="Arial and Helvetica compared"><figcaption>Helvetica (in red) compared with Arial. In a battle of the world's two most boring fonts, only one can emerge the victor (source: <a href="http://ilovetypography.com/2007/10/06/arial-versus-helvetica/">ilovetypography.com</a>)</figcaption> </figure> <p>For our <strong>font hacking</strong> purposes, Arial is ideal. Firstly, its deliberately insipid letterforms make for a great blank canvas. Secondly, it is available pre-installed on most operating systems, meaning I can depend on most of you having it. Lastly, Arial itself &mdash; being based on <a href="http://en.wikipedia.org/wiki/Monotype_Grotesque">Monotype Grotesque</a> and infamously similar to <a href="http://en.wikipedia.org/wiki/Helvetica">Helvetica</a> &mdash; is already something of a derivative typeface. This makes me feel a little less guilty about what we are about to do to it.</p> <h2>Hacking Arial</h2> <h3>What You Will Need</h3> <ul> <li>A text editor such as <a href="http://notepad-plus-plus.org/">Notepad++</a> <strong>(FREE!)</strong></li> <li>The SVG-based path editor, <a href="http://inkscape.org/">Inkscape</a> <strong>(FREE!)</strong></li> <li>An internet connection <strong>(ALREADY PAID FOR!)</strong></li> <li>A mischevious imagination <strong>(FREE!)</strong></li> <li>Arial Bold <strong>(CAME WITH YOUR COMPUTER!)</strong></li> </ul> <h3>What we are going to make</h3> <p>Here's a further demonstration. Try typing in the box using Arial Bold's 4000+ character set. Most of the letterforms you see will belong to Arial Bold and are served from your hard disk. The others are the stencil characters we shall be manufacturing.</p> <div contenteditable="true" style="border:2px solid #222; padding:1em; text-align:center; font-size:2.5em; font-family:'stencil', arial, droid sans, roboto sans, sans-serif; font-weight:bold; line-height:1.5; margin:0.5em 0;"> I'VE NEVER HAD MUCH TIME FOR ARIAL. </div> <p>Note: The TTF to be created will be approximately 6.5K in size and will feature A, B, D, O, P, Q, R, a, b, d, e, g, o, p, q, 4, 6, 8, 9, 0, %, $, & and @ <em>only</em>. Note #2: Of course, not all devices will have Arial available. Your best bet is to put fonts similar to Arial lower down in the stack.</p> <h3>Legal issues?</h3> <p>Make no mistake: We are creating a new font to work with Arial Bold. While we are using Arial Bold to help us make new letterforms, we shall not be producing a "hacked" version of Arial that would be fit for distribution. Our stencil "font" is not a true font because it simply doesn't have enough characters to be used independently. That is, not even <strong>A to Z</strong> or <strong>a to z</strong> are covered. Meanwhile, Arial Bold itself &mdash; which supplies the remainder of the character set &mdash; is not embedded but loaded from the end user's computer in the usual way.</p> <h3>Step 1: Locating Arial Bold</h3> <p>Windows users will no doubt recall they have a <code>C:WindowsFonts</code> folder. If pilfering our Arial Bold <abbr title="Truetype Font">TTF</abbr> were as simple as delving into this folder, I could have missed this step. It's not. Thanks to permissions issues and a variety of other counterintuitive quirks regarding this folder, we're better off doing a search for "arial". On my Windows 7 machine, this unearths another folder with the memorable label of <code>amd64_microsoft-windows-font-truetype-arial_31bf3856ad364e35_6.1.7601.17621_none_d09ba6bac4056b40</code>, found in <code>C:Windowswinsxs</code>. Okay, then.</p> <p>Open this folder and duplicate <code>arialbd.ttf</code> into a location that's within easy reach. I made a new folder called "Font Hacking" on my Desktop.</p> <h3>Step 2: Converting Arial to SVG</h3> <p>Thanks to the <a href="http://www.w3.org/TR/SVG/fonts.html">W3C specification's inclusion</a> of <abbr title="Scalable Vector Graphics">SVG</abbr> fonts, we can transform our <abbr title="Truetype Font">TTF</abbr> into an easily readable &mdash; and hackable &mdash; format.</p> <p>There are numerous options when it comes to converting between font formats. For the <abbr title="Graphical User Interface">GUI</abbr> agnostic, FontForge enables you to do these operations <a href="http://fontforge.org/scripting-tutorial.html">via the command line</a>. If, like me, you simply can't be bothered to install the massive package that is FontForge for a few simple tasks, there are online services like <a href="http://www.freefontconverter.com/">freefontconverter.com</a>. I use this particular service frequently and have experienced no bugs to speak of.</p> <p>Upload your <code>arialbd.ttf</code>, choose "svg" from the dropdown, hit the massive, overdesigned "convert" button and save <code>arialbd.svg</code> in your working directory alongside the original.</p> <img src="https://heydonworks.com/images/convert.png" alt="Convert" width="285" height="72" class="alignnone size-full wp-image-125316"> <h3>Step 3: Getting to know your SVG font</h3> <p>I don't expect you to read it from start to finish, but having the <a href="http://www.w3.org/TR/SVG/fonts.html">W3C's SVG 1.1 Fonts</a> spec' open in a browser tab will come in handy as your font subversions become more complex. For the time being you really only need to know that an SVG font defines glyphs (letters and symbols) using the <code>&lt;glyph&gt;</code> element and that each <code>&lt;glyph&gt;</code> element has certain pertinent attributes:</p> <ul> <li><code>glyph-name</code> defines a unique name for the glyph</li> <li><code>unicode</code> defines the character to which the letterform is mapped. This can be a standard character ("a", for example) or a hexadecimal encoding ("&amp;#x201c;" for left double quotation mark) where required</li> <li><code>horiz-adv-x</code> defines the width of the glyph. If not set, the value is inherited from the <code>units-per-em</code> attribute on the accompanying <code>&lt;font-face&gt;</code> element. This value is usually 2048 for Truetype derivations</li> <li><code>d</code> (data) is most important of all. It's a set of coordinates that defines the actual shape of the glyph in question</li> </ul> <h3>Step 4: Setting up a 'sandbox' Inkscape file</h3> <p>In order to change Arial's letterforms as intended, we will need to convert the <code>&lt;glyph&gt;</code>'s coordinate data into an editable Inkscape path. Fortunately, SVG's supported <code>&lt;path&gt;</code> element also takes the <code>d</code> attribute.</p> <p>In our font hacking workflow we shall be routinely converting glyphs into paths and back again, so it helps to have a "sandbox" file to drop coordinate data into. The easiest way to set up this file is to create a new Inkscape document, draw a basic shape like a circle or square on the canvas and save it. Open this file up in your text editor and you should see a single path element with various attributes:</p> <pre><code>&lt;path sodipodi:type="arc" style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none" id="path3012" sodipodi:cx="394.28571" sodipodi:cy="479.50504" sodipodi:rx="240" sodipodi:ry="227.14285" d="m 634.28571,479.50504 a 240,227.14285 0 1 1 -480,0 240,227.14285 0 1 1 480,0 z" /&gt; </code></pre> <p>For our purposes, all but the <code>id</code> and <code>d</code> attributes are cruft, so get rid of them. Now your sandbox file is ready. To create our stencil font, we shall only be required to edit characters which have fully <a href="http://en.wikipedia.org/wiki/Counter_%28typography%29">closed counters</a>. These are A, B, D, O, P, Q, R, a, b, d, e, g, o, p, q, 4, 6, 8, 9, 0, %, $, & and @. It would defy convention not to start with "A", so return to your <code>arialbd.svg</code> and search the file for <code>unicode="A"</code>. Copy the coordinate value from this glyph's <code>d</code> attribute and use it to replace the equivalent <code>d</code> value in your sandbox file's <code>&lt;path&gt;</code>.</p> <h3>Step 5: Wait &hellip; what?</h3> <p>Upon reopening your sandbox document, you'll see that famous Arial "A" and &hellip; it's upside down. Oh.</p> <img src="https://heydonworks.com/images/upside_down-300x295.png" alt="The A is upside down over the canvas" width="300" height="295" class="alignnone size-medium wp-image-125223"> <p>There is a reason for this and, according to <a href="http://batik.2283329.n4.nabble.com/Converting-Font-to-SVG-all-glyphs-are-rotated-td3596984.html#message3597795">at least one source</a>, it is the ancient Periclean Greeks and their attitudes towards coordinate systems that are to blame. Finger pointing aside, the reality is that standard SVG vectors are drawn, like most image formats, from the <strong>top left</strong>, while SVG fonts are drawn from the <strong>bottom left</strong>.</p> <p>We need to "correct" the orientation in our sandbox file without affecting the path itself. As luck would have it, we can utilize the <code>transform</code> attribute. Add <code>transform="scale(1,-1)"</code> as an attribute on the <code>&lt;path&gt;</code> in your sandbox file and reopen it in Inkscape. You should see something like this:</p> <img src="https://heydonworks.com/images/right_way_up-179x300.png" alt="A sitting on top of canvas" width="179" height="300" class="alignnone size-medium wp-image-125227"><p></p> <p>Note that the "A" now sits precisely <em>on top of</em> the canvas. Unnatural as it may at first seem, the top of our canvas can be safely treated as a guide for the <a href="http://en.wikipedia.org/wiki/Baseline_%28typography%29">baseline</a> of our font. If we were to extend the letterform's shape below this line, this portion of the letterform would indeed "hang down" much like the <a href="http://en.wikipedia.org/wiki/Descender">descender</a> of a "g" or "y". For our stencil font example, however, our path editing will be much more rudimentary.</p> <h3>Step 6: Removing the counter</h3> <p>Stencils cannot have apertures because there is nothing to connect the aperture (the counter) to the rest of the stencil. Some stencil sets get around this by incorporating little bridges to connect up the pieces, as in the spray-painted slogan below:</p> <figure><img src="https://heydonworks.com/images/graffitti-300x225.jpg" alt="reads Drink The Bleach" width="300" height="225" class="alignnone size-medium wp-image-125191"><figcaption>(Image: <a href="http://www.flickr.com/photos/salim/">Salim Virji</a>)</figcaption></figure> <p>It would be entirely possible to emulate this aesthetic now that we have the letterform in our hand. However, I don't want to get too bogged down in the finer points of Inkscape path editing. We're going to keep it simple for now and just have the counters removed altogether.</p> <p>Select the "A" path by clicking on it and hit <kbd>F2</kbd> to go into "edit path by nodes" mode. You should see some nodes marking the perimeter of the A's counter (the hole in the middle). Select and delete each of these so that the counter is <em>utterly eliminated</em>.</p> <figure><img src="https://heydonworks.com/images/nodes1-298x300.png" alt="Nodes are the diamond shapes in the corners" width="298" height="300" class="alignnone size-medium wp-image-125305"><figcaption>Nodes are the tiny diamond shapes visible in the corners</figcaption></figure> <p>Save the sandbox file and reopen it in your text editor to refesh the path data. Now simply copy the value of the path's <code>d</code> attribute back into the <code>d</code> attribute of the original glyph in your <code>arialbd.svg</code> file. Hit save. <code>Arialbd.svg</code> is now the full Arial Bold font with the "A" letterform curiously lacking a counter.</p> <h3>Step 7: Tedious Repetition</h3> <p>Do for B, D, O, P, Q, R, 4, 6, 8, 9, 0, a, b, d, e, g, o, p, q, &, $, @ and % precisely what we did for "A". The results are best with just uppercase letters and you're free to just focus on these if you want to save time. To quickly recapitulate, the workflow is this:</p> <ul> <li>Locate the candidate <code>&lt;glyph&gt;</code> by searching for the <code>unicode</code> attribute value in <code>arialbd.svg</code></li> <li>Copy the <code>&lt;glyph&gt;</code>'s <code>d</code> attribute value into the <code>d</code> attribute of the Inkscape sandbox's <code>&lt;path&gt;</code> in your text editor</li> <li>Reopen the file with the <code>&lt;path&gt;</code> in Inkscape, delete the counter nodes and save</li> <li>Refresh the text editor version of the Inkscape sandbox SVG you just edited</li> <li>Copy the new path coordinates from the <code>d</code> attribute and paste back into the <code>&lt;glyph&gt;</code>'s corresponding <code>d</code> attribute and resave <code>arialbd.svg</code></li> </ul> <h3>Step 8: Converting the SVG back to TTF</h3> <p>Now that all of the letterforms you wanted to abuse have been abused, you'll want to convert <code>arialbd.svg</code> back into a TTF file. Return to <a href="http://freefontconverter.com/">freefontconverter.com</a>, upload the SVG and choose TTF from the available options. Hit the <strong>MONOLITHIC BLUE BUTTON</strong> and save the file as <code>arialstencil.ttf</code>.</p> <img src="https://heydonworks.com/images/convert.png" alt="Convert" width="285" height="72" class="alignnone size-full wp-image-125316"> <h3>Step 9: Making A Webfont Kit</h3> <p>Those familiar with Font Squirrel's <a href="http://www.fontsquirrel.com/tools/webfont-generator">superb webfont generator</a> will already be comfortable turning this font into a kit. However, we're going to want to base64 encode our font, which we shall be trimming down to a subset as proposed earlier. Remember: we're not going to be using a hacked Arial Bold but a new font <em>based</em> on Arial Bold, with Arial Bold left intact.</p> <img src="https://heydonworks.com/images/font-squirrel-logo.png" alt="font-squirrel-logo" width="238" height="131" class="alignnone size-full wp-image-125309"> <p>Upload <code>arialstencil.ttf</code> to <a href="http://www.fontsquirrel.com/tools/webfont-generator">the generator</a> via the <strong>+ Add Fonts</strong> button, select the expert mode using the appropriate radio control and alter the following options:</p> <ul> <li><strong>Font formats:</strong> Just have TrueType and EOT compressed checked. EOT is for Internet Explorer and will be served via URL, not base64 encoded.</li> <li><strong>Subsetting:</strong> Hit the "Custom Subsetting" radio. Then enter <em>just the characters you edited</em> into the "Single Characters" field. This is important because it will make your font much smaller and allow you to fall back to Arial in your font stack</li> <li><strong>CSS</strong>: Check base64 encode</li> </ul> <p>Finally, check the agreement and download your webfont kit.</p> <h3>Step 10: Embedding Your Font</h3> <p>Nearly there. Your new kit will contain a <code>stylesheet.css</code> file and an EOT font. Wherever you use your stencil font, you'll need to include the <code>@font-face</code> rules and place the EOT font file (for IE) relative to the stylesheet.</p> <p>To make your font stack more readable, I'd rename the <code>@font-face</code> blocks' <code>font-family</code> property to something like "Stencil". Now just define your stack and include a bold <code>font-weight</code>. Put together, the CSS should look something like this:</p> <pre> <code>@font-face { font-family: 'Stencil'; src: url('stencil-webfont.eot'); /* for IE */ } @font-face { font-family: 'Stencil'; src: url(data:font/truetype;charset=utf-8;base64,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) format('truetype'); font-weight: normal; font-style: normal; } .your-selector { font-family: 'Stencil', arial, sans-serif; font-weight: bold; } </code></pre> <p>Oh go on then, add some <code>text-shadow</code>:</p> <div contenteditable="true" style="border:2px solid #222; padding:1em; text-align:center; font-size:2.5em; font-family:'stencil', arial, sans-serif; font-weight:bold; line-height:1.5; margin:0.5em 0; color:#e4126b; text-shadow:-5px -5px 20px #12e835, 5px 5px 20px #e4126b;"> IRONIC DYSTOPIAN STATEMENT </div> <h2>Ambition Is A Virtue</h2> <p>As I have already stated, the "stencil font" example is relatively basic. It doesn't really even change the letterforms' shapes as such. More ambitious permutations you could try might involve breaching the baseline (as already discussed), or narrowing/extending the glyph width (being careful to adjust the <code>horiz-adv-x</code> attribute accordingly). It should be noted that, in my experiments, converting from SVG to TTF using online tools have resulted in a loss of kerning data. However, values for kerning can be found inscribed in Arial Bold's many, many <code>h-kern</code> elements. <pre> <code>&lt;hkern u1="A" u2="y" k="76" /&gt;</code> </pre> </p><p>Arguably, the most fun is to be had making only <strong>the subtlest of changes</strong>. Popular fonts have familiar, well-established personalities so even the slightest subversion could have a potentially dramatic effect on their reception. Take <a href="https://twitter.com/typeco/status/302127912788844544/photo/1">James Grieshaber</a>'s photo of misprinted signage at Buffalo Niagara International Airport, below. The slightly misplaced counters have instilled an accidental exuberance into a previously po-faced geometric sans:</p> <img src="https://heydonworks.com/images/sign.png" alt="Not so geometric sans on airport sign" width="818" height="346" class="alignnone size-full wp-image-125322"> <h2>Conclusion</h2> <p>I've always found more creative satisfaction in deconstructing things as opposed to constructing them; more mileage in reconfiguring than configuring. I think the reason is that starting from scratch feels like starting from <em>within</em> and simply purging my private, isolated ideas into the world always felt a bit pointless. This is probably why I'm drawn to <a href="https://www.google.co.uk/search?q=dada+photomontage&hl=en&client=firefox-a&hs=1em&rls=org.mozilla:en-US:official&tbm=isch&tbo=u&source=univ&sa=X&ei=fyIzUbHxOaiw0AW_wYHICg&ved=0CEkQsAQ&biw=1366&bih=616">Dadaist photomontage</a> and why I've spent countless hours of my life obsessively <a href="http://open.spotify.com/album/69jX2ounXk2Bc1nL8N2BRk">sourcing and sequencing audio samples</a>. I enjoy being able to turn mere consumables (adverts, songs, fonts, images) into my own cultural objects. I get a kick out of transforming diktat into dialogue, engaging with what's already out there and forcing it to engage with me.</p> <p>If you share my inclinations, perhaps you'd care to outline your font hacking ideas in the comments. Alternatively, you can reach me on Twitter (<a href="http://twitter.com/heydonworks">@heydonworks</a>). Even if your subversions don't yield production-suitable typography, I hope you'll gain a better appreciation of some of the most iconic and pervasive shapes known to the worlds of design and culture.</p> <style type="text/css">@font-face { font-family: 'ampersand'; src: url('http://www.heydonworks.com/css/ampersand-webfont.eot'); }</style><style>@font-face { font-family: 'ampersand'; src: url(data:font/truetype;charset=utf-8;base64,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) format('truetype'); font-weight: normal; font-style: normal; }</style> <style type="text/css"> @font-face { font-family: 'stencil'; src: url('http://www.heydonworks.com/css/stencil-webfont.eot'); }@font-face { font-family: 'stencil'; src: url(data:application/x-font-woff;charset=utf-8;base64,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) format('woff'), url('http://www.heydonworks.com/css/stencil-webfont.ttf') format('truetype'), url('http://www.heydonworks.com/css/stencil-webfont.svg#arialboldmt') format('svg'); font-weight: normal; font-style: normal; <p>}</style><p></p> Design Clients On Famous Logotypes https://heydonworks.com/article/design-clients-on-famous-logotypes/ 2013-08-12T00:00:00.000Z https://heydonworks.com/article/design-clients-on-famous-logotypes/ <p>For this article, I took a sample of corporate and small business design clients, erased their memories (with a "mind rubber"), then asked them to critique a small selection of highly prolific and famous commercial logotypes.</p> <p>To them, this would be the first time they had seen and experienced these brands. Unaware of the massive successes of the companies behind the logos, would this unusual focus group find intrinsic merit in the designs, or would the benefit of unfamiliarity help to disclose failings? Let's see what they have to say.</p> <h2>Nike</h2> <figure><img src="https://heydonworks.com/images/nike.gif" alt="Nike logo"></figure> <p style="text-indent: 0;"> <strong>CLIENT 1:</strong> What is this? Nikey? Nicky? <strong>CLIENT 2:</strong> I think it's confusing. People won't know how to say it. <strong>CLIENT 3:</strong> It's "Nike", like the goddess, I guess. <strong>CLIENT 2:</strong> The goddess? Does anyone actually know who she is? <strong>CLIENT 1:</strong> That's too gender specific. <strong>CLIENT 2:</strong> What about the underline? <strong>CLIENT 3:</strong> The underline? <strong>CLIENT 1:</strong> It's sort of a "flash", isn't it? <strong>CLIENT 2:</strong> It's a tick, maybe. Needs to be further away from the text. <strong>CLIENT 1:</strong> Yes, it's all a bit squashed up. <strong>CLIENT 3:</strong> Ticks have a pointy shoulder. It's more of a hockey stick. <strong>CLIENT 2:</strong> Nobody plays hockey. <strong>CLIENT 4:</strong> I think it looks like a sperm. </p> <h2>Apple</h2> <figure><img src="https://heydonworks.com/images/apple.gif" alt="Apple logo"></figure> <p style="text-indent: 0;"> <strong>CLIENT 1:</strong> So, it's an apple. <strong>CLIENT 2:</strong> Apples should be green. <strong>CLIENT 1:</strong> Or red. Why's it white? <strong>CLIENT 3:</strong> It's not joined up. <strong>CLIENT 2:</strong> What? <strong>CLIENT 3:</strong> It's not joined up. The leaf part doesn't connect to the fruit part. <strong>CLIENT 1:</strong> That's an oversight. <strong>CLIENT 2:</strong> Someone's taken a bite. That's not good. <strong>CLIENT 3:</strong> Yes, I wouldn't buy a half eaten apple. <strong>CLIENT 1:</strong> I prefer oranges. <strong>CLIENT 4:</strong> It looks like a puddle of sperm. </p> <h2>Coca-cola</h2> <figure><img src="https://heydonworks.com/images/cocacola.gif" alt="Coca-cola logo"></figure> <p style="text-indent: 0"> <strong>CLIENT 1:</strong> Coca... coola? <strong>CLIENT 3:</strong> Isn't that a hotel in Rio de Janeiro? <strong>CLIENT 2:</strong> The first 'o' in "coola" is too high up. <strong>CLIENT 1:</strong> It's too squiggly. Shouldn't it be in a simpler font? <strong>CLIENT 2:</strong> There's at least 50% too many 'c's. And 'o's. <strong>CLIENT 1:</strong> And 'a's. <strong>CLIENT 3:</strong> White on red is a bit "on the nose", isn't it? <strong>CLIENT 1:</strong> Yeah, that's been done. <strong>CLIENT 4:</strong> The curly bit on the "C" looks like it's having intercourse with the loop in the "L". I'm not happy with that. <strong>CLIENT 2:</strong> Yes, and what's up with the hyphen? </p> <h2>KFC</h2> <figure><img src="https://heydonworks.com/images/kfc.gif" alt="KFC logo"></figure> <p style="text-indent: 0"> <strong>CLIENT 1:</strong> He's old. <strong>CLIENT 2:</strong> Too old, probably. <strong>CLIENT 3:</strong> He needs to be straighter. <strong>CLIENT 2:</strong> Straighter? He's too&hellip; gay? <strong>CLIENT 3:</strong> No, no, of course not. <em>Straighter</em>: He's leaning to the left. He looks drunk. <strong>CLIENT 1:</strong> His right. He's leaning to his right. <strong>CLIENT 2:</strong> Yes, that's more correct. <strong>CLIENT 3:</strong> What's wrong with his chin? <strong>CLIENT 2:</strong> It's a beard. He's got a beard. <strong>CLIENT 3:</strong> It's the same colour as his face. It looks like a growth. <strong>CLIENT 4:</strong> He looks like he could be dangerous to children. </p> <h2>Starbucks</h2> <figure><img src="https://heydonworks.com/images/starbucks.gif" alt="Starbucks logo"></figure> <p style="text-indent: 0"> <strong>CLIENT 1:</strong> Starbuck, like out of <em>Battlestar Galactica</em>? <strong>CLIENT 2:</strong> That was a good show. <strong>CLIENT 1:</strong> Who played him again? Was it Burt Reynolds? <strong>CLIENT 3:</strong> Dirk Benedict. <strong>CLIENT 2:</strong> I don't like the green. Can you get green coffee? <strong>CLIENT 3:</strong> Pistachio is green. Is that a coffee? <strong>CLIENT 2:</strong> Green means "sick". I don't want coffee that makes me sick. <strong>CLIENT 1:</strong> It's generally too round. Looks too military, like a medal. <strong>CLIENT 4:</strong> THAT MERMAID IS NAKED! </p> <h2>Conclusion</h2> <p>Oh dear. Coca-cola, Nike, Starbucks, KFC and Apple: Your logotypes are rife with stylistic mistakes, thematic inconsistencies, clichés and negative connotations. Back to the drawing board with the lot of you!</p> <p>Joking aside, it's really hard to make "good" logos and even harder to judge them. What is there to go on? One can militate against negative connotations, but only if they are willing to embrace something insipid. One can be exacting with their logos form, but at the risk of creating something regimented and lacking in personality. Some claim eBay <a href="http://www.businessinsider.com/15-alternative-designs-for-ebays-boring-new-logo-2012-10?op=1">made this mistake</a> with their "cleaner, contemporary" looking new logo. It looks less daft, but we <em>like</em> daft.</p> <p>Ultimately, designers and design clients alike worry too much about the design of their logos and too much time is spent trying to find a "correct" solution among a plethora of contrary, subjective observations. We forget that it isn't the logo which <em>sells</em> the product anyway. How can just a word or a little scribble make the necessary pitch?</p> <p>Most logos are simply identifiers. The only logos that are really able to "work harder" and "create a buzz" for a product all by themselves are the ugly ones. Nobody gossips about good taste. So, my advice on creating your next logo is to make it as poor as possible.</p> Tetris And The Power Of CSS https://heydonworks.com/article/tetris-and-the-power-of-css/ 2013-11-07T00:00:00.000Z https://heydonworks.com/article/tetris-and-the-power-of-css/ <p>To be really good at CSS, you have to learn CSS. I know this sounds like a tautology but I've become aware of a peculiar attitude that preprocessors such as <abbr title="Sexually Arousing Style Sheets">SASS</abbr> are somehow <em>successors</em> to CSS. Some SASS and <abbr title="Light Emitting Style Sheets">LESS</abbr> nerds are fond of proliferating the following aphorism. It should be noted that its author did not himself intend it as an advocation of preprocessors.</p> <blockquote> <p> The four stages of CSS: 1. I don’t know CSS 2. I know enough CSS to get by 3. I _know_ CSS 4. Fuck CSS </p> <footer><cite><a href="https://twitter.com/cackhanded/status/358721135677935616">@cackhanded</a></cite></footer> </blockquote> <p>They forget that all preprocessors do is make writing CSS easier, not qualitatively different: It's still CSS that comes out of the end. This is a shame, because vanilla CSS deserves some credit for being a powerful, rule-based language all its own and &mdash; when it comes to solving the kind of design problem I shall be exploring in this post &mdash; it doesn't matter how you "preprocess" the CSS; it's the naked CSS logic that does the heavy lifting.</p> <p>Put down your classes, ladies and gentlemen, because we're talking about <strong>dynamic content</strong> and they cannot save you now.</p> <h2>Incomplete grids</h2> <p>Let's imagine we have a three-column grid but that we don't know how many items will be <em>in</em> that grid. Perhaps items expire over time or users are able to delete them from the list. To fit a three-per-line formation, each item must be floated left and have a width of 33.333%. Okay&hellip; so let's say we arrive at the page and there are 7 active items. Visually, it's going to look like this:</p> <figure> <img style="width: 100%; max-width: 400px;" src="https://heydonworks.com/images/tetris1.png" alt="grid with an orphaned item at the bottom left"><figcaption>There's always one who just has to be different, isn't there? I call him "WHATWG"</figcaption> </figure> <p>Now, I'm the sort of designer who couldn't give a toss about "pixel perfection" so long as the page is usable and accessible. That said, this kind of blatant asymmetry is a bit jarring, even to me. What I need is a way to treat that last item &mdash; the orphan &mdash; differently. I'm sticking to the Tetris analogy, so I'd like to make that last item a full row (full width) and earn myself some points. (I know you can't change the width of blocks in Tetris; I'm just talking about making tidy rows, alright?)</p> <p>We <em>could</em> do this by adding some logic to the template and writing a <code>last</code> class to whichever item comes last. However, we all know too much template logic is <em>bad</em>, especially when it breaks with the <a href="http://www.w3.org/TR/html-design-principles/#separation-of-concerns">separation of concerns</a> rule. That is, the <code>last</code> class would only denote visual &mdash; not structural &mdash; differentiation. Not only that but, if the user deletes an item, we'll have to dynamically rewrite the DOM to replace the <code>last</code> class on a new item with javascript. Poo to that!</p> <p>The simplest and most efficient way to deal with this is to use the (very well supported) <code>:last-child</code> pseudo-class:</p> <pre><code> .grid li:last-child { float: none; width: auto; } </code></pre> <h2>We have a problem</h2> <p>So far, our technique is incomplete. Why? Because, so far we haven't incorporated any logic to determine whether our last item is, in fact, an orphan. This means that about 33.33% of the time we're going to make our grid prettier, but approximately 66.66% of the time we're actually going to make our grid <em>uglier</em>:</p> <figure> <img src="https://heydonworks.com/images/tetris2.png" alt="just using last child creates some ugly side effects"><figcaption>Grotty!</figcaption> </figure> <p>To fix this problem we need to leverage some of the CSS power you didn't learn while dicking about with SASS. Well, maybe you did, but in spite of SASS; not because of it. We're going to have to incorporate some maths, so let's consider the axioms:</p> <ul> <li>The grid is three items wide</li> <li>The grid contains any number of items</li> <li>Orphans are last items</li> <li>Orphans exist alone, on their own row</li> </ul> <p>If you look at which item numbers correspond to potential orphans (items that would be orphans if they were the last items), the first thing you'll notice is that the list begins with "1": We don't want a single item, all on its own, to appear at 33.333% width. That would be weird. Counting up, 4, 7, 10, 13, 16 follow 1 as potential orphans. The interval, you will notice, is three. In other words, if you minus 1 from each value, you're looking at the three times table. Now we're getting somewhere.</p> <figure> <img style="width: 100%; max-width: 400px" src="https://heydonworks.com/images/tetris3.png" alt="Potential orphans highlighted"><figcaption>Potential orphans</figcaption> </figure> <p>This is where CSS's spectacularly useful <code>:nth-child</code> pseudo-class comes in. Since <code>:nth-child</code> can accept algorithmic arguments, we can predict and target potential orphans ad infinitum.</p> <pre><code> li:nth-child(3n + 1) { /* Selector not complete, so no rules yet. */ } </code></pre> <p>If, like me, you're not familiar with mathematical syntax, the <code>3n</code> part just means <code>3 x n</code>. The algorithm does this for values of <code>n</code> going up in integers (0, 1, 2, 3, etc. etc. etc.). So, <code>3n + 1</code> is first equivalent to <code>3 x 0 + 1</code>, which equals <code>1</code>. Then it's equivalent to <code>3 x 1 + 1</code>, which is <code>4</code>. That's the pattern we want, but our selector isn't finished quite yet.</p> <p>(For a more detailed explanation of <code>:nth-child</code>, consult "Lord Of The Hootenanny", Chris Coyier's <a href="http://css-tricks.com/how-nth-child-works/">2010 post</a>).</p> <h2>Potential orphans and actual orphans</h2> <p>This is the part I love. This is the part where the modular logic of CSS comes into play. So far we've only identified <em>potential</em> orphans. That is, our selector <em>only</em> anticipates one of two conditions that must both be true for the targeted item to be a true orphan. The original condition that an orphan must be a <code>:last-child</code> is still true, so we must concatenate our two conditions in one selector chain like so:</p> <pre><code> li:nth-child(3n + 1):last-child { /* Now you are safe to do some orphan styling */ float: none; width: auto; } </code></pre> <figure> <img src="https://heydonworks.com/images/tetris_green.png" alt="the target element is identified"><figcaption>That's the chap</figcaption> </figure> <p>Note how the logic is similar to a more typically programmy programming language. It's a bit like saying:</p> <pre><code> foreach (items as item) { if (item.condition1() && item.condition2()) { item.adopt(); } } </code></pre> <p>Of course, making the orphan "full width" is just to satisfy my tenuous Tetris analogy. Instead, you could bring the orphan neatly into the center.</p> <pre><code> li:nth-child(3n + 1):last-child { float: none; margin-left: auto; margin-right: auto; } </code></pre> <h2>Off by one</h2> <p>What if we also want to target last items that appear in the second column (or last items in 3-column grids which have a single gap at the bottom right position)? We simply copy/paste our selector and jog the algorithm on one integer to read <code>3n + 2</code>. Now we can use the two selectors in tandem to ensure no gaps appear in our grid under any circumstances. No template logic or javascript DOM manipulation required.</p> <pre><code> li:nth-child(3n + 1):last-child { float: none; width: auto; } li:nth-child(3n + 2):last-child { width: 66.666%; } </code></pre> <img src="https://heydonworks.com/images/tetris4.png" alt="the final result: none of the 3 potential configurations leave gaps in the grid"> <p>Did you think I was actually going to recreate Tetris in CSS? Sorry, no. Nobody needs to do that.</p> <h2 id="update">Update</h2> <p>This update is dedicated to Aditya Raisinghani who left a comment with the great idea of incorporating <code>nth-last-child(2)</code> to make the last two items each 50% width.</p> <p>How are we going to do this? The logic states, "if the second last item falls in the first column, make it <strong>and the one after it</strong> 50% width to fill the row".</p> <p>In the following snippet, I am going to combine Aditya's selector with an <a href="http://reference.sitepoint.com/css/adjacentsiblingselector">adjacent sibling combinator</a> to fulfill the "<strong>one after it</strong>" part. We could, of course, use <code>3n + 2</code> again, but I prefer the way this reads.</p> <pre><code> li:nth-child(3n + 1):nth-last-child(2), li:nth-child(3n + 1):nth-last-child(2) + li { width: 50%; } </code></pre> <figure> <img src="https://heydonworks.com/images/tetris_update.png" style="max-width: 400px; width: 100%" alt="the last and second last items at 50%"> </figure> The Accessible Current Page Link Conundrum https://heydonworks.com/article/the-accessible-current-page-link-conundrum/ 2014-02-14T00:00:00.000Z https://heydonworks.com/article/the-accessible-current-page-link-conundrum/ <p>When I’m done staring with fear-induced catalepsy at the vast array of complex and overlapping app building, testing, integration and deployment tools that are quickly amassing around me, I like to take a little break and try to solve a simple problem. The “current page” link is just such a problem.</p> <h2>The current page</h2> <p>By “current page”, I mean the page you are on right now. It’s <em>this</em> page to you, or to me if I have the vanity to read this post after writing it. In our navigation schema we like to highlight the current page, indicating to the user where they are. A highlighted current page link is like a <strong>YOU ARE HERE</strong> indicator in a shopping mall floor map. I’m rarely <em>there</em>, incidentally, because I hate shopping.</p> <p>The problem with “current page” links is there’s no interoperable (read: accessible) way of communicating them. Unlike links to page fragments, which are identified as “same page link” (or similar) by popular screen readers, the mechanism by which a link points to the current location is not exposed via browsers to assistive technologies. At least, not in my experience.</p> <h2>Class confusion</h2> <p>It’s perfectly simple to add a class — either manually or dynamically — to whichever link corresponds to the current page to add our highlight. Drupal adds an <code>active</code> class to current page links. It’s a poor name because it shares terminology with the <code>:active</code> state, but it does the job.</p> <pre><code>&lt;nav role=&quot;navigation&quot;&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;/&quot; class=&quot;active&quot;&gt;Home&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/about&quot;&gt;About&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/contact&quot;&gt;Contact&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/nav&gt;</code></pre> <p>Unfortunately, this class, as all classes, will remain uninterpreted by screen readers. Screen readers do not read classes. Classes do not climb <a href="http://www.w3.org/WAI/PF/aria-implementation/#intro_treetypes">accessibility trees</a>. In order to provide an aural indication of context, we’ll need to try something else.</p> <h2>Accessible names</h2> <p>The <a href="http://www.w3.org/TR/wai-aria-1.1/roles#namecalculation">accessible name</a> of an element — its lexical content — is calculated by one of</p> <ul> <li>the element’s text node,</li> <li>the value of any associated <code>aria-label</code> or <code>aria-labelledby</code> attributes,</li> <li>the <code>alt</code> attribute if it’s an image etc.,</li> <li>the <code>title</code> attribute. Don’t leave it up to the <code>title</code> attribute. That’s flimsy as hell.</li> </ul> <p>Unavoidably, if we want to do the right thing here and communicate the current page both visually <em>and</em> aurally, using an accessible name is the key. First let’s try adding some text.</p> <h2>The span approach</h2> <pre><code>&lt;nav role=&quot;navigation&quot;&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;/&quot; class=&quot;active&quot;&gt;Home &lt;span class=”visually-hidden”&gt;current page&lt;/span&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/about&quot;&gt;About&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/contact&quot;&gt;Contact&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/nav&gt;</code></pre> <p>This is pretty good, but necessitates the hacky “hide to visual users but not to screen reader users” approach of clipping the <code>&lt;span&gt;</code> text or hiding it off screen. Because the span communicates nothing visually, we are then forced to tackle the same problem separately for visual users: We have to leave the <code>.current</code> class intact.</p> <h2>The aria-label approach</h2> <p>The <code>aria-label</code> attribute can be added to elements which are lacking a text node. Commonly, <code>&lt;button&gt;</code>s with just unicode icons or background images.</p> <pre><code> &lt;nav role=&quot;navigation&quot;&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;/&quot; class=&quot;active&quot; aria-label=&quot;current page&quot;&gt;Home&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/about&quot;&gt;About&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/contact&quot;&gt;Contact&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/nav&gt;</code></pre> <p>I prefer this to the “shove a span in there” approach for one reason above all: You can use the <code>aria-label</code> attribute in a selector. By pairing the accessible name with the style you can <strong>remove the class</strong>, tidying up the <strong>HTML</strong>. More important than tidiness, though, is the creation of a mechanism whereby the visual appearance of “current page” and the aural announcement of “current page” are paired. That is, when you move the <code>aria-label</code> between links, you are doing it for both kinds of user.</p> <pre><code>[aria-label=&quot;current page&quot;] { /* highlighted styles */ }</code></pre> <p>Roger Johansson notes <a href="https://twitter.com/rogerjohansson/status/434215633333399552">an internationalization problem</a> with this method. Should we translate the site to French, we would want to change the “current page” value of the <code>aria-label</code> to “page actuelle” or similar. This would break the above selector. You could change the selector to <code>[aria-label]</code> so it just matches the <em>presence</em> of the attribute — which would only be on our current link — but there’s a bigger problem with <code>aria-label</code> than that.</p> <h3>The problem</h3> <p>Having been testing in VoiceOver, I was fully expecting the “current page” text to be appended (or is it prepended? It doesn’t matter) to the text node — “current page home”, for example. Unfortunately, for our purposes, <strong>NVDA</strong>, <strong>JAWS</strong> and ChromeVox all <em>override</em> the text node with the label, leaving just “current page”. Irritatingly cryptic to most users, I would imagine...</p> <ul> <li>Home</li> <li>About</li> <li>Contact</li> <li>Current page</li> <li>Blog</li> </ul> <h2>The aria-describedby approach</h2> <p>Unlike <code>aria-label</code>, <code>aria-describedby</code> is actually specified to append its value to the target element’s text node. I have set up a <a href="http://codepen.io/heydon/pen/BdpEn">test case on CodePen</a> where you will note that both <strong>JAWS</strong> and <strong>NVDA</strong> both read “home link current page” when focusing the “home” navigation item. The markup looks like this:</p> <pre><code>&lt;nav role=&quot;navigation&quot;&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;/&quot; aria-describedby=&quot;current&quot;&gt;home&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/about&quot;&gt;about&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/contact&quot;&gt;contact&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;div id=&quot;current&quot;&gt;current page&lt;/div&gt; &lt;/nav&gt;</code></pre> <p>Naturally, we hide <code>#current</code> with <code>display: none</code>. This will make it invisible to all users. Now, only one item needs translating and it’s easier because it is text which appears within the document rather than an attribute value. The <code>aria-describedby</code> value need not change as it just forms a relationship with <code>#current</code>. This is the best solution I have come up with.</p> <h2>aria-current</h2> <p>You may or may not know that <strong>WAI-ARIA</strong> tab interfaces have an <code>aria-selected</code> attribute which can be used to indicate the “open” tab in such an interface. “Selected tab” (or “tab selected”) is communicated whenever the selected tab is focused.</p> <pre>&lt;a role=&quot;tab&quot; aria-selected=&quot;true&quot;&gt;My tab&lt;/a&gt;</pre> <p>Note how I have omitted the class. As in our “current page” example there’s no need for it, because the presence of the <code>aria-selected</code> attribute can do all the work. The <a href="http://www.w3.org/WAI/PF/aria-practices/20091214/#docmgt"><strong>W3C</strong> recommend</a> tying state to appearance in this way, in fact:</p> <blockquote> <p>For supporting browsers, tie CSS attribute selectors to WAI-ARIA properties to reduce script</p> </blockquote> <p>Like <code>aria-checked</code> and <code>aria-pressed</code>, <code>aria-selected</code> is intended to communicate the selected state of a control amongst other controls. It’s tempting to think <code>aria-selected</code> would be suitable for the use case I am exploring for “current” pages, but there are conceptual differences between that which is “on” or “chosen” and one’s location within a continuum. Accordingly, <a href="http://lists.w3.org/Archives/Public/public-pfwg/2013Oct/0059.html">Léonie Watson has been discussing</a> <code>aria-current</code> as a proposed standard method for indicating one’s current location within a site or step-based process. What do you think?</p> <h2>Remove the link?</h2> <p>One more approach, as suggested to me by <a href="https://twitter.com/schofeld/status/434233011237036034">Jonathan Schofield</a>, would be to remove the link for the current page altogether.</p> <pre><code>&lt;nav role=&quot;navigation&quot;&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;home&lt;/strong&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/about&quot;&gt;about&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;/contact&quot;&gt;contact&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/nav&gt;</code></pre> <p>Though perhaps a bit more of a handful styling wise, this makes sense to me. Why link to the place you’ve arrived at already? My only concern is that a <code>&lt;strong&gt;</code>, <code>&lt;span&gt;</code> or other inert element would be unfocusable, not allowing a screen reader user the context we are trying to communicate.</p> <h2>This is design</h2> <p>The next time someone asks me what web design is or categorizes me as a “visual designer”, I’m going to send them to this post. You are welcome to as well. Any other suggestions for “current page” solutions, anyone?</p> Confessions Of A CSS Expert https://heydonworks.com/article/confessions-of-a-css-expert/ 2014-03-28T00:00:00.000Z https://heydonworks.com/article/confessions-of-a-css-expert/ <p>"I guess it all started pretty innocently enough. The <abbr title="User Expert">UX</abbr> guys would be asking for a new module or something. You know the sort of thing: a search box or paginator. Whatever. So I'd give that block a class like 'search-widget' or 'paginator'; something to make my stylesheet more readable and to help me contain styles within those blocks. It really helped."</p> <p>"Then some guy told me about this thing called 'selector performance'. The idea was you could make the page <em>faster</em> by using classes more as selectors. So I would start putting classes inside these blocks, on pretty much anything. Instead of using <code>.paginator li</code>, I'd put a class of, like, <code>.page</code> on each of the list items. It was a bit time consuming 'cos I'd have to change the template logic to add the class. There was a lot of pressure to be 'perf', though, so I put the time in. I was so caught up that I never thought to check if selector performance was a real thing."</p> <p>"Before long, I'd gotten into the hard stuff. I was putting multiple classes on any one element. They weren't your normal classes either; they were those high-power 'modified' classes you get. There were hyphens all over the shop. I knew I had a problem when I was looking at an <code>input</code> element with three classes on it. I stared at it for ages, then it finally hit me: 'There's no <code>type</code> attribute!'"</p> <pre> &lt;input class="form_elem input input--email" /&gt; </pre> <p>"The thing I regret the most is how my class addiction affected my relationship with <abbr title="Hypertext Mother Lode">HTML</abbr>. I'd write blog posts about how to structure classes using whatever methodology I was on at the time and I'd provide some code snippets. I'd always use <code>&lt;div&gt;</code>s in the examples. You know, just as placeholders. But these examples started making their way into my UI prototypes after a while, which turned out to be a slippery slope. Soon enough, sites in production were using <code>&lt;div&gt;</code>s for everything: buttons, headings, checkboxes, whatever. It was like Drupal, but <em>even more obsolete</em>."</p> <p>"At the height of my addiction, I was using <abbr title="Not An Acronym">Sass</abbr> <code>for</code> loops to generate classes for elements that I wasn't sure would ever exist. It was a bitter pill to swallow, but I had to face up to the truth: I had become a <abbr title="Cascading Satire Sheets">CSS</abbr> expert."</p> <p>"These days I'm doing a lot better. It's been a long road, but I've managed to give up using classes in my CSS altogether. They said it couldn't be done but, little by little, I made the changes I needed to make. The whole experience has been a learning curve and I think I've come out the other end a much wiser person."</p> <pre> &lt;input data-style="form_elem input input--email" /&gt; </pre> Reinventing The Hyperlink https://heydonworks.com/article/reinventing-the-hyperlink/ 2014-08-01T00:00:00.000Z https://heydonworks.com/article/reinventing-the-hyperlink/ <p>Hi everybody! I've just done a lot of cocaine on the company expense account and I want to talk to you about navigational action controls called "hyperlinks" and how to design them into your enterprise-level web application portfolio. <strong>YEEEHAWWW</strong>.</p> <h2>What is a hyperlink?</h2> <p>Back in the days of websites, long before <strong>The Web App Space</strong>, a boffin called Tim Berners-Lee invented something called the "anchor", which looked like <code>&lt;a&gt;</code> and was a type of <abbr title="the stuff you stick CSS3 to">HTML</abbr> element. It was called an "anchor" because it took you to places much like a boat would. Tim Berners-Lee often sailed boats into Switzerland to visit the <abbr title="Large Heydon Collider">LHC</abbr>, you see.</p> <p>Because anchors linked to things (different web pages or parts of web pages) we took to calling them "links". The W3C added "hyper" as a prefix to increase the element's appeal to infants and simpletons. This is what traditional <em>hyperlinks</em> looked like:</p> <pre> <code> &lt;a href="http://www.yahoo.com">Yahoo master domain portal&lt;/a&gt; </code> </pre> <p>We've come a long way since then and learned many high impact, transferable lessons. The most important of these lessons has been about performance. The performance problem with the above <code>&lt;a&gt;</code> element is clear. Let me explain:</p> <p>Because the hyperlink <code>&lt;a&gt;</code> is recognized by your web browser, the browser will add styles to it, making it look like a hyperlink. This is fine for kids and amateurs, but we don't want hyperlinks to <em>look</em> like hyperlinks because then people will think we don't have any of our own, paradigm-shifting design ideas. We have to override the styles the browser has done for us (thanks, browser, but I think that's our job!) before we start adding our own.</p> <pre> <code> a { color: inherit; text-decoration: none; } a:focus { outline: none; } </code> </pre> <p>Adding these reset styles is costly in development time and, worse, results in us cruelly and irresponsibly sending dozens of additional bytes to the poor user's computer. <strong>This shall not pass!</strong> Wow, that coke really hit the spot. Right&hellip; to circumvent this bothersome necessity we need to choose an element which the browser <em>does not recognize</em>; one which it can't tamper with behind our backs. Fortunately, there is just such a template element, called <code>&lt;div&gt;</code>:</p> <pre> <code> &lt;div href="http://www.yahoo.com"&gt;Yahoo master domain portal&lt;div&gt; </code> </pre> <p>There is a minor issue here. Not just the style but the <em>behavior</em> of the traditional hyperlink is now omitted. In other words, clicking the <code>&lt;div&gt;</code> won't do anything. I don't have any data in front of me, but I'm going to go ahead and assume this is bad for <abbr title="Ultimate XXXperience">UX</abbr>.</p> <p>Confronted with this problem, some developers would cut their losses, conceding that the cons outweigh the pros, and go back to using Tim's original anchor thingy. Those developers don't do enough cocaine. If I can see through time, I can reinvent HTML! To retroactively preinstate [sic] the behaviors and semantics we just removed, we need to do a number of things. Let's go through each of these in turn.</p> <h2>1. Make the div focusable</h2> <p>Some people use keyboards to navigate websites instead of computer mice. It's not my bag at all, but whatever floats your boat. Just don't rub my face in it. No, but seriously, some of my best mates are keyboard users. That's their choice and they're entitled to it. Where was I? Oh yeah: <code>&lt;div&gt;</code>s can't be focused (selected with a keyboard) like <code>&lt;a&gt;</code>s are by default. To make them behave this way, you need to add a new attribute &mdash; <code>tabindex="0"</code>.</p> <pre> <code> &lt;div href="http://www.yahoo.com" tabindex="0"&gt;Yahoo master domain portal&lt;div&gt; </code> </pre> <p>You'll also need to create a focus style for that <code>&lt;div&gt;</code>, much like the one we were trying to avoid having to reverse engineer by making the element a <code>&lt;div&gt;</code> in the first place. This is fine, unironic and totally makes sense. Also, gzip, so shut up.</p> <h2>2. Give it a styling hook</h2> <p>Before we can do that, we need to add a styling hook to our <code>&lt;div&gt;</code>. We need to be very careful how we choose our styling hook so that it makes semantic sense to each of the other 1,700 developers working on the project that uses it. Of course, using an actual <code>&lt;a&gt;</code> would have been quite transparent, but that ship has bolted. Let's go with <code>.link</code>.</p> <p>Actually, <code>.link</code> is good but it's not very well name-spaced. What if our project and another project inexplicably get put in the same web page and start having sex with eachother? You didn't think of that, did you! Let's also add a class of <code>.our-project</code> (replace with your project name) to help discern between the two <abbr title="User Intercourse">UI</abbr> libraries after they've formed a sordid flesh-mass.</p> <pre> <code> .link.our-project:focus { outline: thin dotted; } </code> </pre> <h2>3. Create a surrogate href</h2> <p>The <code>&lt;div&gt;</code> element has a bug: When you give it an <code>href</code> attribute, the attribute doesn't do what it's supposed to &mdash; send the user to the <abbr title="Urban Renewal Location">URL</abbr> when they click the <code>&lt;div&gt;</code>. This is because browser vendors are Lazy Satanists&trade;.</p> <p>To recreate this behavior we are going to use a javascript click handler. This is perfectly reasonable because, under all circumstances, users have javascript running in their browser and there are never any errors or problems. Thank you.</p> <pre> <code> &lt;div class="link our-project" onclick="window.location.href='http://www.yahoo.com'" tabindex="0"&gt;Yahoo master domain portal&lt;div&gt; </code> </pre> <p>Excellent! We're almost there.</p> <h2>4. Adding the semantics</h2> <p>For reasons I cannot quite fathom, when you don't use an <code>&lt;a&gt;</code> element, the browser's accessibility API doesn't communicate the <code>&lt;div&gt;</code> to assistive technologies as an <code>&lt;a&gt;</code>. To do this, you need to spoof the link semantic with a WAI-ARIA role. You know Aria Stark out of <em>Game Of Thrones</em>? This has nothing to do with her. You know the motorcycle helmet manufacturer <em>Arai</em>, whose domain, believe it or not, is <a href="http://whyarai.co.uk/">whyarai.co.uk</a>? It has nothing to do with them either.</p> <pre> <code> &lt;div class="link our-project" onclick="window.location.href='http://www.yahoo.com'" tabindex="0" role="link"&gt;Yahoo master domain portal&lt;div&gt; </code> </pre> <p>Now, when a keyboard user with a screen reader running focuses the <code>&lt;div&gt;</code>, it will say "Yahoo master domain portal <em>link</em>". </p><h2>Conclusion</h2> <p>So, to summarize, we've taken an inert <code>&lt;div&gt;</code> element, made it focusable by keyboard, given it a styling hook to differentiate it from other non-link-like <code>&lt;div&gt;</code>s, given it the same <code>:focus</code> style an <code>&lt;a&gt;</code> element would have by default, approximated standard link functionality using the addition of javascript and provided link semantics in the accessibility layer for our pseudo-hyperlink using WAI-ARIA.</p> <p>But what is the outcome? We have proven that Tim Berners-Lee is no big deal and I could have him any day and my nose is bleeding and oh no I'm not right.</p> <h2>The Takeaway</h2> <p>It's Friday, so I'm getting a curry. Thanks to <a href="http://twitter.com/codepo8">@codepo8</a>, <a href="http://twitter.com/yatil">@yatil</a>, <a href="http://twitter.com/g16n">@g16n</a>, <a href="http://twitter.com/stommepoes">@stommepoes</a>, <a href="http://twitter.com/hugogiraudel">@HugoGiraudel</a>, <a href="http://twitter.com/rogerjohansson">@RogerJohansson</a>, <a href="http://twitter.com/stevefaulkner">@stevefaulkner</a> et al for inspiring this abomination. <a href="http://twitter.com/flocke">@Flocke</a> has made a <a href="https://gist.github.com/jensgro/067d50303479101783e3">gist with even more wheel reinvention involved</a>, Satan help us.</p> I Do Care About Sin https://heydonworks.com/article/i-do-care-about-sin/ 2014-08-25T00:00:00.000Z https://heydonworks.com/article/i-do-care-about-sin/ <p><strong>Note:</strong> This article is a deconstruction of a post by Paul Boag called <a href="https://medium.com/@boagworld/i-dont-care-if-homosexuality-is-a-sin-9f50ae207ba5">I don’t care if homosexuality is a sin</a>. I recommend you read it unannotated first. Paul <a href="https://twitter.com/boagworld/status/503468335510867969">"agonized over writing this post"</a>, so you owe him that.</p> <p>I feel I have a duty to address Paul's post as an atheist, not least because Paul feels that atheists are intent on convincing him he is a bigot. I cannot speak for all atheists &mdash; unlike Paul? :-) &mdash; but I have no such intention. I simply think he has a poor taste in book(s).</p> <p>By all accounts, Paul is a <em>good person</em>. But like many moderate Christians, he has to perform some mental gymnastics in order to excuse the dubious thinking of a perpetually absent interlocutor. If only <strong>God</strong> was available for comment, then perhaps he could answer for all of this:</p> <figure> <img src="https://heydonworks.com/images/2014/08/bible_tabs.png" alt="Book with coloured tabs representing the bad parts of the bible" width="573" height="377" class="alignnone size-full wp-image-166"><figcaption>The pink tabs are for murder, the purple for human or animal sacrifice, blue for rape, yellow for slavery, and green for misogyny. <a href="http://lefthemispheres.blogspot.co.uk/2012/03/good-book.html">Image found here</a>.</figcaption> </figure> <p>Alas, he is not. Never has been, whether you believe he exists or not. The trouble with this is that it falls on people like Paul to answer for him; people who, by their own admission, don't <q>really know for certain what [God] thinks about almost anything!</q></p> <p>For good people, this is bothersome and tiresome. More importantly, however, it makes life really <em>easy</em> on the bad people; Anti-Pauls, if you will. In the absence of a self-advocating God, Christianity only really has The Bible to go on. As such, it is treated as a sacred, unquestionable text by many. While Paul is not one for making "God hates fags" signs, others are and, unequivocally, there are passages in The Bible that provide a pretext for this behavior.</p> <hr> <blockquote> <p>The Bible does indeed say that homosexuality is a sin. But people seem to stop there. They don’t ask what that means. They don’t endeavour to put it in context.</p> </blockquote> <p>Perhaps <a href="http://en.wikipedia.org/wiki/The_Bible_and_homosexuality#Leviticus_18_and_20">the most famous and graphic passage</a> is found in <i>Leviticus 20</i>: <q>If a man lies with a male as with a woman, both of them have committed an abomination; they shall surely be put to death</q>. Well, I think that's fairly clear. Unless, contextually speaking, it is referring to merely <em>laying down next to another man</em> but I suspect this would be a little unrealistic, given these two factors:</p> <ul> <li>This excerpt is from the so-called <a href="https://www.enterthebible.org/resourcelink.aspx?rid=377">Holiness Code</a> which lists other forms of prohibited sexual practice such as incest</li> <li>Sharing a tent with another man on a camping trip would carry the death penalty. This means The Bible would have me serve several life sentences</li> </ul> <p>This is rarely the position a moderate Christian would take in defending the passage, however. Usually it is one of</p> <ul> <li>You are reading the wrong edition of The Bible;</li> <li>Some of the words in that chapter may have been translated badly;</li> <li>You've linked to Wikipedia, which is an unreliable source &mdash; quite unlike a collection of patently fictional stories written two thousand years ago, in one case featuring a talking snake</li> </ul> <p>Paul is too smart to fall into these traps. Unlike some Christians, who are acutely focused on scripture, he is not interested in discussing what The Bible may or may not be trying to tell us at all:</p> <blockquote> <p>I could talk about culture and context. I could give you my interpretation. But to be honest I don’t know and neither do you.</p> </blockquote> <p>This is a position often called <em>avoidance</em>, not unlike the ubiquitous "God works in mysterious ways" cop out. It is the intellectual equivalent of running away from a debate with your hands over your ears shouting "la la la la la la!" Meanwhile, The Bible in its countless millions of incarnations says homosexuals should be put to death. Very plainly. We are not supposed to edit The Bible, so inevitably, this information falls into the wrong hands.</p> <p>Take Hitler, for instance, <a href="http://www.nobeliefs.com/hitler.htm">who was a Christian</a>. Here's a picture of a Nazi belt buckle emblazoned with the words "Got Mit Uns" ("God with us"):</p> <figure> <img src="https://heydonworks.com/images/2014/08/gotmituns.jpeg" alt="Nazi belt buckle with god with us written on it" width="362" height="281" class="alignnone size-full wp-image-198"> </figure> <p>And we all know <a href="http://en.wikipedia.org/wiki/Persecution_of_homosexuals_in_Nazi_Germany_and_the_Holocaust">how Hitler felt about homosexuals</a> (hint: he put them in concentration camps and killed them much as the Bible suggests).</p> <p>Now, for those of you who are a bit slow on the uptake, I am <em>not</em> comparing Paul Boag to Adolf Hitler. Nope, not for a second. I'm not even saying that The Third Reich's distaste for homosexuals was <em>directly</em> influenced by The Bible. I am instead stating that, despite having the same taste in morally instructive books, these two men's actions have proven to be very different. So what is The Bible for?</p> <p>The point is that, while devotees of Faith are scrabbling to put words (either pro or anti homosexuality) in the mouth of God, atheists must defer to rationality: If being gay does not harm one's fellow humans, it should not be considered a bad thing. And it <em>doesn't</em>, so it's simple. Without the biblically reported God as an alibi, you have no excuse to treat people of different sexual orientations as sinners (bad people).</p> <p>Here is Paul on the existence of The Bible's controversial anti homosexuality passages:</p> <blockquote> <p>For Christians this means homosexuals are in some way evil. For atheists it just shows how irrelevant and out of date religion is. But if you dig a little deeper you discover that in fact it is a non issue.</p> </blockquote> <p>Theoretically, it is of course a non-issue. Or, at least, it should be. Sadly, it is not, because religious doctrine has been used by conservatives as a pretext to <a href="http://www.newyorker.com/news/daily-comment/arizonas-anti-gay-bill-lives-on-in-hobby-lobby">lobby against gay rights</a>. Also, if Christians <i>per se</i>, think that homosexuals are "in some way evil", does this include Paul or not? He doesn't tell us what he thinks.</p> <blockquote> <p>It is a non issue for two reasons and if you can spare me a moment, I would like to explain them.</p> </blockquote> <p>I have a bad feeling about this&hellip;</p> <blockquote> <p>Sin is a misunderstood concept. People think of sin as bad actions. Murder, rape, abuse, that kind of thing. In fact that is not right at all. According to the Bible (the same source that says homosexuality is a sin) it is rebellion against God.</p> </blockquote> <p>Okay, we're already entrenched in "what the Bible says" territory, so I think common sense and reasoning may be out of the question. I have just learnt that <strong>homosexuality is a form of rebellion against God</strong>. So, when I put another man's penis in my mouth, I am not simply pleasuring the man but undertaking a challenge to God's authority, with the ultimate aim of overthrowing him. Really?</p> <blockquote> <p>Essentially sin is a rejection of God and a failure to live, think and be like him. The Bible says “for all have sinned and fall short of the glory of God”. In other words, sin is falling short of God. Being less than God.</p> </blockquote> <blockquote> <p>The whole point was to say; it doesn’t matter what you do, you can’t reach God’s standards. But God knows that and loves us anyway.</p> </blockquote> <p>Is this the same God who pranked Abraham by telling him he had to kill his own son? Is this the same God who <a href="http://skepticsannotatedbible.com/2kg/2.html">sent bears to kill 42 children just for teasing a guy for being bald</a>? What perfect standards are these? Based on accounts of Mr. Boag who has not, to my knowledge, intimidated anyone into preparing their own son for sacrifice, I would suggest that God should be reading a book about him, rather than the other way around.</p> <p>I <em>would</em> say this though, of course, because I'm one of those militant humanists who thinks that compassion between actual, living people is more important than the reported contemplative vicissitudes of an unverified deity. Madness, I know.</p> <blockquote> <p>So from God’s perspective homosexuality is as irrelevant as getting angry at somebody or lying on your tax returns. We make up this arbitrary scale that homosexuality is worse than adultery but not as bad as murder. Sure, some ‘sin’ have bigger consequences on other people and so could be considered more serious. But on that scale homosexuality rates fairly low. The truth is that from God’s perfect perspective, none of us are any different. We are all equally far below him and yet he loves us all utterly and completely.</p> </blockquote> <p>Let's break this down:</p> <ul> <li>Homosexuality <em>is</em> a sin, but is irrelevant to God</li> <li>God considers it as being similar to evading / not paying taxes (depriving the state of necessary resources to care for the vulnerable in its population), which is also irrelevant</li> <li>The difference between homosexuality and murder is arbitrary.</li> <li><em>But</em> it is <em>just possible</em> that murder is worse than homosexuality, if you really want to get into detail and stuff</li> <li>God thinks that murderers, rapists and homosexuals are all the same</li> <li>God loves us anyway; even the rapists. They are fine.</li> </ul> <p>Do you see what a muddle we get into when trying to post-rationalize the terrible prejudices of the unquestionably perfect (or, rather, the terrible prejudices of ancients hallucinating the unquestionably perfect)? You end up saying things like "in God's perfect perspective" and claim it is "truth". Yikes.</p> <blockquote> <p>Now some will struggle with the idea of homosexuality being ‘wrong’ on any level.</p> </blockquote> <p>Homosexuals, for instance.</p> <blockquote> <p>After all it is what many have built their self identity around.</p> </blockquote> <p>Is Paul saying homosexuality is a choice here? It certainly sounds like it. This is a worrying view. You see, some folks who think homosexuality is a choice will <a href="http://www.gaystarnews.com/article/victims-gay-cure-camps-reveal-what-really-happens170114-0">pressure other folks into ridding themselves of something they can't, in fact, help</a>. This is abusive. Mind you, in God's eyes abuse is much the same as homosexuality, so maybe they cancel each other out.</p> <p>Isn't it weird how some Christians can meet homosexuals and think their sexuality is man-made, yet think God &mdash; for whom the only records are <em>reports written by men</em> &mdash; is, in fact, the creator of those men and not the other way around?</p> <blockquote> <p>My point here is that homosexuality is no different to any other part of the human condition.</p> </blockquote> <p>For example, raping people. Rape is on a level with homosexuality, in God's eyes. We are all <q>equally below him</q>.</p> <blockquote> <p>But let’s imagine for a minute that I am wrong. That homosexuality is in fact a bigger ‘no no’ than anything else. That God does care more. The truth is that it is still none of our business. People can lead their lives in any way they like.</p> </blockquote> <p>Here, Paul says that in the hypothetical situation that God thinks homosexuality is worse than, say, rape, it's none of our business. Not to worry, though, he assures us; we can go ahead and be homosexual anyway.</p> <p>That's not The Bible speaking, by the way, that's Paul. If only folks really did take Paul's word over God's reported say-so! That whole Brendan Eich / Mozilla fiasco could have been sorted in a single DM. Oh, and before you <em>even start</em>, Eich donated money towards <a href="http://en.wikipedia.org/wiki/California_Proposition_8_%282008%29">the retraction of people's rights</a>: That is <em>not</em> expressing an opinion.</p> <p>"People can lead their lives in any way they like". Really? In any way? What sort of doctrine says "do what the hell you like, I'm not bothered"? It's certainly not the one I read in The Bible. The Bible is quite particular about how we should lead our lives, actually. Either Paul disagrees with The Bible's stance on homosexuality and is not prepared to say so, or he agrees with the position but is too apathetic to intervene and save those who would commit the damnable act in question. Sorry Paul, but what other possible conclusions can be drawn?</p> <blockquote> <p>Some Christians like to throw around the phrase “love the sinner, hate the sin” but to be frank this is a thin veil to justify criticism. I don’t believe it is the place of anybody to judge any other human being. I don’t believe we understand God enough to really know for certain what he thinks about almost anything!</p> </blockquote> <p>Inevitably, we have arrived at the fundamental flaw of Christianity as a catalyst for moral veracity. Having established that we all come up short in the eyes of God, no matter what we do, what impetus is there for us to strive for social justice? What incentive is there for us to be good, honorable, compassionate human beings? What premise is there to rehabilitate transgressors? If it is really the case, as Paul argues, that not being "sinful" is futile, then The Bible is not a moral text. It offers no groundwork for moral agency.</p> <p>When I was a lot younger, I had a friend called Joe. He took a lot of magic mushrooms at a rave and thought the DJ was Jesus. His overdose lead to psychosis and I visited him in a mental health ward several times. On release he pursued his nascent interests in religion and ultimately became a "born again" Christian.</p> <p>After weeks and months of supporting him, reassuring him and trying to help him, he met with me one day and had something important he wanted to tell me. "Heydon, you are my friend. But you are filled with human pride and God cannot forgive you for that." Occasionally I still see him, preaching in the street, telling people, to use Paul's terminology, that <q>the human condition is broken</q>. What dreadful, destructive nihilism. What lack of humanity sanctioned by the notion of God.</p> <p>It almost breaks my heart.</p> <h2>Final words</h2> <blockquote> <p>Ultimately none of us have a clue what God thinks about homosexuality and we should stop pretending we do or trying to guess. Instead we should be doing what God told us to do and love one another. Let’s try that for a bit and see how things work out.</p> </blockquote> <p>It's easy to invoke the "L" word like this, but I think we can agree that "love each other" is an extremely reductionist reading of The Bible. Even lovey-dovey Jesus said <q>think not that I am come to send peace on earth: I came not to send peace, but a sword</q> (<a href="https://heydonworks.com/">Matthew 10:34</a>). And what about <a href="http://en.wikipedia.org/wiki/Stockholm_syndrome#Lima_syndrome">Stockholm Syndrome</a>? Is falling in love with the captor who has mercilessly bullied and tortured you what God wants? Or is it a phenomenon identified by professional psychologists interested in a necessarily less anodyne picture of human interaction? In order to actually understand and help people?</p> <p>In his article, Paul has fallen short of condemning The Bible's views on homosexuality. He has acknowledged them; he has bemoaned the frequency at which he is reminded of them; he has supposed that there are worse sins than homosexuality (<q>on that scale homosexuality rates fairly low</q>). He has <em>not</em> categorically condemned them.</p> <p>Instead, Paul's position is that homosexuality is <q>none of our business</q>. I am glad that there are Christians who, like Paul, contend that other people should be free to act as they wish. The problem is that this does not address the premise that homosexuality is considered a sin in The Bible and this premise is a dangerous one. It gives Christians who <em>do</em> believe in intervention a pretext to intervene. And they will.</p> <p>Even in God-mandated acts of love and as endeavors to "save" people, they will put those "lost souls" through terrible pain and turmoil, or even kill them. I'm not just talking about <a href="http://www.huffingtonpost.com/2013/04/30/gay-south-africa-conversion-deaths_n_3186820.html">Gay Cure Camps</a> and their record for abuse and suicide, but also <a href="http://www.theguardian.com/world/2014/jan/22/rockville-exorcism-women-killed-two-children">the violent "exorcism" of young children</a> &mdash; often children so young that they are unable to even conceive of a God's existence.</p> <p>I <em>do</em> care about sin. I care because it is a dubious, over-simplistic concept that is not applicable for understanding or appreciating the human condition. I care that the idea of sin can and will lead to harm. Not always harm through malice, but certainly through misunderstanding. I care that homosexuality being considered <em>bad</em> conflates it with pedophilia, <a href="http://www.huffingtonpost.com/wayne-self/boy-scouts-gays-pedophiles_b_3119530.html">encouraging some people to think their children are not safe around gay people</a>.</p> <p>This is why I'm a humanist: I believe that actually investing time into trying to understand and appreciate humans (people like you and me, including homosexuals); to invest in and believe in <em>them</em> is a lot more productive and justified than simply tolerating their alien existence in favor of a "close relationship" with an unverified Deity (whether or not that Deity is purportedly loving).</p> <p>I am proud to be a humanist, and your chosen God should be proud of me for it too. If you're interested, you can join the <a href="https://humanism.org.uk/join/">British Humanist Association</a>.</p> The Precarious X In UX https://heydonworks.com/article/the-precarious-x-in-ux/ 2015-06-11T00:00:00.000Z https://heydonworks.com/article/the-precarious-x-in-ux/ <p>I have a long-held suspicion of anything directed at me — especially anything commercial — that sells itself on its &quot;experiential&quot; qualities. I hate the word &quot;immersive&quot; in particular. &quot;Here, let me waterboard you with my new web app! You're going to love it!&quot; Basically, I'm suspicious of anything that seeks to appeal to me kinesthetically, rather than to my intellect. I want to be treated as a sentient agent; not as the passive stigma to someone's dirty sense pollen.</p> <p>It's not that I don't relish some experiences in life. It's not that I don't enjoy, well, enjoyment <i>per se</i>. It's just that if I got my jollies from using <em>a website to book train tickets</em>, I'd have to ask myself some serious fucking questions. &quot;Wow, adding that purchase to my shopping basket was just so darn delightful! Fuck it, I'll buy more, for the same day, going to the same place, just for the experience of it all! Hnnnnnnnn.&quot;</p> <p>Sorry, I'll calm down.</p> <hr> <p>The other week I attended a user testing session as the lead designer and developer for an app intended to help people find out if they're entitled to disability benefits. Predictably, and tragically, only a small proportion of the testers who'd signed up would make it to the session. Due to ill health. When the first tester finally arrived (Ian, let's call him), we waited a full 5 minutes while he sat, head in hands, catching his breath after climbing just one flight of stairs.</p> <p>Ian told me, in conversation during the session, that he had spent a decade of his life living as, essentially, a hermit; not interested in the trappings of modern, technologically mediated and socialized existence. He came equipped with a smart phone he'd acquired that week. It was a Windows phone, though he wasn't aware of that.</p> <p><em>Now</em>.</p> <p>Do you think for a moment that Ian expected or wanted to <em>experience</em> our product? For it to impress and delight him as it enveloped his consciousness? Do you think he was looking to be carried away on a flying carpet of pixel perfection and shit that swooshes around arbitrarily? Do you think he watches Apple keynotes? Do you think he's the sort who'd lean over to you and go, &quot;hey, check out this new Honda advert! <strong>IT'S SO WELL DONE</strong>.&quot; No, of course not, because he doesn't care about interfaces, or design, or technology. He wanted using the app to be straightforward and painless and to get it all over with as quickly as possible.</p> <p>That's how <em>I</em> feel too, most of the time. I'm terrible at using interfaces, and I hate interfaces which try to draw me in, making me use them more than I should have to. That's why I'm a User Experience Designer.</p> <p>So, this is probably as good a time as any to tell you that I've been nominated for Designer Of The Year in the Net Awards and you can <a href="https://thenetawards.com/vote/designer/heydon-pickering/">vote for me</a>, haha.</p> Developer Fallacies https://heydonworks.com/article/developer-fallacies/ 2016-01-12T00:00:00.000Z https://heydonworks.com/article/developer-fallacies/ <p>From time to time, web and software developers will use bad arguments to justify their choice of technologies, workflows or org structures, or to disparage others' differing choices. I see this a lot, and I may have even dropped the occassional F-bomb myself. We're particularly vulnerable to making bad arguments because we identify ourselves with being logical. How <em>very</em> wrong we often are.</p> <p>In this post, I'm going to lay out a few of the fallacies I see frequently and I invite you to submit your own. Some of my examples are hypothetical for brevity, so feel free to shout &quot;<strong>STRAW MAN</strong>&quot; at me now, if it turns you on.</p> <ul> <li><a href="#gospel">The gospel fallacy</a></li> <li><a href="#luddite">The Luddite fallacy</a></li> <li><a href="#scale">The scale fallacy</a></li> <li><a href="#chocolate-fireguard">The chocolate fireguard fallacy</a></li> <li><a href="#pull-request">The pull request fallacy</a></li> <li><a href="#made-at-facebook">The 'made at Facebook' fallacy</a></li> <li><a href="#bob-the-builder">The Bob The Builder fallacy</a></li> <li><a href="#real-world">The real world fallacy</a></li> <li><a href="#daphne-and-celeste">The Daphne & Celeste fallacy</a></li> </ul> <h2 id="gospel">The gospel fallacy</h2> <p>I'm going to start on one you've probably heard of already, perhaps under a different name. This is the &quot;we've always done it this way&quot; fallacy. Something — some so-called best practice or rule or process — is honoured, unquestioningly, simply because it was honoured in the past. This is a type of <strong>circular reasoning</strong>.</p> <p>Now, this &quot;thing&quot; may or may not be a good idea or practice, but just saying it's good <em>because</em> it has been agreed upon is not, well, <em>good enough</em>. This fallacy is named in honour of The Holy Bible, which is treated as unquestionable by some fundamentalist Christians despite some <strong>seriously sketchy advice</strong>.</p> <blockquote> <p>"Slaves, in reverent fear of God submit yourselves to your masters, not only to those who are good and considerate, but also to those who are harsh." &mdash; <strong>1 PETER 2:18</strong></p> </blockquote> <p>It's impractical to question or otherwise deconstruct everything, but be wary of accepting anything as gospel. Your software development ancestors, just like the writers of The Bible, may claim to be God-like or channeling some higher power, but this is never evident.</p> <p>Being wary of the gospel fallacy is especially prudent regarding assumptions about users, their behaviours and preferences.</p> <h2 id="luddite">The Luddite fallacy</h2> <p>The Luddite fallacy is essentially the opposite of <a href="#gospel">the gospel fallacy</a>. They are two sides of the same coin, if you like. Named for the textile workers, the Luddites, who resisted the new technologies that threatened their livelihood, it takes two forms:</p> <ul> <li>A false claim that the only reason the subject is not adopting a new technology <em>must be</em> because they are arbitrarily resistant to (or scared of) change</li> <li>The false claim that just because something is new, it must be better</li> </ul> <p>For example, you might be accused of &quot;not liking change&quot; because you resist moving a project from one technology to a new one, when really your reasoning is that the new technology is <em>wank</em>, for which you can provide justification. The fallacy will be trotted out to mask any valid arguments, making it a form of <em>ad hominem</em> attack.</p> <p>Developers have a tendency to be self-serving in their choice of technology. There is a strong urge to adopt a new technology just because it's a fun new toy to play with. Of course, they'll never admit to that openly, but they might rely on some form of the Luddite fallacy with which to bargain. Be aware.</p> <p>Here are some examples of <a href="http://theworstthingsforsale.com/">some things that have been recently conceived which are fucking terrible</a>.</p> <h2 id="scale">The scale fallacy</h2> <p>This is one I get a lot because I tend to favour simple solutions to things, in my writing about web development. The accusation takes a form akin to, &quot;that's fine for the simple thing you're doing, but it won't scale.&quot; Exactly what is meant by &quot;scaling&quot; is never made clear, nor can it be — it's too vague of a concept. In any case, the scale fallacy covers two illogical assumptions, depending on the context:</p> <ul> <li>That projects serving larger numbers of people are necessarily more complex intrinsically</li> <li>That projects serving larger quantities of content can only do so by being more complex</li> </ul> <p>Is the popularity of an application proportional to how much code it is written with? No, of course it isn't. In fact, there are any number of examples where quite the opposite is true. To claim that a convoluted codebase is the inevitable result of expanding the reach of a product is fallacious. Don't be George Lucas. Sit on your fucking hands and stop adding bullshit features.</p> <p>Equally, there's no reason why serving 10 pages of content versus serving 10000 should be any different in terms of mechanism. They often <em>are</em> different, but there's no reason, in isolation, why they should be. The number of records in a database has no relationship to the complexity of that database's overall structure.</p> <p>The clunkiness of publishing systems cannot be justified by the number of their consumers.</p> <h2 id="chocolate-fireguard">The chocolate fireguard fallacy</h2> <p>Some things are just not fit for purpose. Some things are just better not existing or being replaced by other things. You should never accept this without investigation (see <a href="#gospel">the gospel fallacy</a>) but not everything can be excused with the apologistic, &quot;so long as you use it responsibly, it's perfectly fine.&quot; A cot made out of barbed wire? Sure, so long as you're careful!</p> <p>It stands to reason that the eponymous chocolate fireguard is never likely to make a worthy substitute for a wrought iron one. Sure, you can still use a chocolate fireguard if that's how you win a bet, but you're going to make your life difficult. It would take little effort to demonstrate this. For example, you could light a fire.</p> <p>I may — and I did — assert that <a href="https://medium.com/@Heydon/things-to-avoid-when-writing-css-1a222c43c28f#.l7rgmobhn">nesting is a poor language feature of Sass</a>. My argument was that it arbitrarily increases syntactic complexity, inevitably diminishing the readability of the Sass source code for no benefit. You're perfectly welcome to dispute this, providing examples of nesting <em>increasing</em> the readability of your code where possible or by demonstrating other benefits.</p> <p>However, just saying, &quot;like anything else, it really depends on how you use it&quot; doesn't answer my claim that nesting <em>cannot</em> improve Sass code. It's just a dubious assertion that literally everything has the same value and utility.</p> <h2 id="pull-request">The pull request fallacy</h2> <p>The pull request fallacy is a kind of rhetorical diversion tactic. It claims that your grievances about the nature of a certain piece of Open Source Software are invalid because you could just send a pull request to fix it; that all OSS is, therefore, beyond reproach. Recently, I posted <a href="https://twitter.com/ericdfields/status/677677470590570496">this tweet quoting an observation about the arguably confused state of contemporary javascript syntax</a>. This was met with the suggestion that, because it's open source software, I could just go and &quot;fix it&quot;.</p> <p>I really wouldn't know where I would start with this pull request, since it would have to address a huge body of decentralised standards work and proprietary API code, culminating in the provided snippet. But that's not the point. Just because Github exists doesn't mean I don't have the right to pass comment on development culture or the dubious fruits it sometimes bears.</p> <p>It is also naïve to think that fixing some code via a pull request will inevitably fix the culture that begat it. Not everything is a discrete bug that can be reduced to a ticket/issue, anyway. Some things are fundamentally flawed in their design. See the <a href="#bob-the-builder">Bob The Builder fallacy</a>.</p> <h2 id="made-at-facebook">The 'made at Facebook' fallacy</h2> <p>This fallacy is reminiscent of the generic &quot;<a href="https://yourlogicalfallacyis.com/appeal-to-authority">appeal to authority</a>&quot; fallacy, wherein you point to an authority figure such as a scientist or published author stating that what they say must be true.</p> <p>In web development we often look to famous, successful organisations for inspiration; Google, Facebook, Microsoft. We make the mistake of attributing their success to their development practices and look to <a href="https://en.wikipedia.org/wiki/Cargo_cult">cargo cult</a> success by adopting the same behaviours. There's no reason why a successful organisation is necessarily a functional, efficient or technically capable one. Just look at the Tory party in the UK.</p> <p>Organisations like Facebook have huge development teams where communication and knowledge sharing is necessarily more problematic than in small, closely knit teams. Should development practices evolve to overcome this problem, then they are only valid <em>where the problem actually exists</em>. Aping them isn't going to help you.</p> <p>Did you know OOCSS (Object Oriented CSS) was developed to help Facebook with their woefully organised and redundant CSS? Do you know who came up with it? <a href="https://vimeo.com/72759139">An independent consultant</a>.</p> <h2 id="bob-the-builder">The Bob The Builder fallacy</h2> <p>The Bob The Builder fallacy is symptomatic of the piecemeal way we tend to approach web development. It can be summarised in one phrase: &quot;A problem with the design has been verified, therefore it <em>must</em> be fixed&quot;.</p> <p>When using ticketing systems, which describe tasks independently, it's tempting to just soldier through, tackling anything we know <em>how</em> to tackle. It's important to first ask whether a given task <em>should</em> be tackled, what its wider implications are for users, and what sacrifices would have to be made in terms of systemic simplicity or robustness.</p> <p>I provided a fictional dialog illustrating the myopic way we approach problems in my article, <a href="https://medium.com/@Heydon/things-to-avoid-when-writing-css-part-2-7639f0f6880d#.tf7v0tli2">Things To Avoid When Writing CSS (part 2)</a>:</p> <blockquote> <p> “Hey, I’ve got these three adjacent ‘calls to action’. They each have a picture, some text and a button (well, a link). The trouble is, the text is different for each, so the buttons don’t quite line up horizontally.”<br>“Okay.”<br>“Well, I mean it doesn’t look right. Is there a way you could fix it?”<br>“Well, technically I could set the same height for each call-to-action (leaving enough room for the tallest), then position each button absolutely along the bottom line of their container. But I wouldn’t&#8202;—&#8202;“<br>“That sounds great, do that!”<br>“Well, have you actually finalized the copy, because&#8202;—&#8202;“<br>“THAT SOUNDS GREAT, DO THAT!”<br>“But, when you reduce the viewport, the text will wrap and&#8202;—&#8202;“<br>“<strong class="markup--strong markup--blockquote-strong">THAT. SOUNDS. GREAT. DO. THAT.</strong>” </p> </blockquote> <p>When it comes to communication design, nothing is black or white; broken or fixed. Not everything is a bug. Some things are limitations, and some limitations benefit many more users than the few that a &quot;fix&quot; would address. This fallacy is named for the children's television show, Bob The Builder, for which the theme tune goes, &quot;Bob The Builder / Can he fix it? / Bob The Builder / YES HE CAN!&quot;</p> <p>Yes, he can, but should he?</p> <h2 id="real-world">The real world fallacy</h2> <p>The real world fallacy comes about when you express an idea for a new development practice and a member of the community disputes its veracity on the basis (for whatever reason) that their company/organisation would not want or be able to adopt it. The truly fallacious part derives from applying their specific assumption generally, making the mistake that because it wouldn't work for them, it necessarily wouldn't work anywhere else, for anyone else.</p> <p>That is, by assuming their experience is universal, they cannot imagine anyone &quot;in the real world&quot; would ever take the notion seriously.</p> <p>As an addendum, it's probably worth pointing out that &quot;the real world&quot; — the one we live in — is <em>our</em> responsibility. The real world is what we make it. Since your agency is undeniable, using &quot;this would only work in an ideal world&quot; as an excuse tells everyone you're reluctant to help change the world for the better.</p> <p>Ask yourself: Am I The Establishment?</p> <h2 id="daphne-and-celeste">The Daphne & Celeste Fallacy</h2> <p>The Daphne and Celeste fallacy erroneously puts that ugly looking code must be poor code. It is typically the domain of coddled and self-regarding developers who prioritise the readability of code by themselves over its utility to users.</p> <p>One example is the addition of WAI-ARIA attribution. Yes, it makes the code &quot;uglier&quot;, but it is there for an important reason (providing semantics to AT users). To suggest that its ugliness is, by extension, &quot;hacky&quot; or low in quality would therefore be incorrect.</p> <p>Here's an example of some CSS:</p> <pre> <code> :nth-last-child(-n+6):first-child, :nth-last-child(-n+6):first-child ~ * { /* properties here */ } </code> </pre> <p>This CSS does something useful: It styles sibling elements if there are six or more of them in quantity. It is quite difficult to read if you are not familiar with advanced CSS and it should probably follow a comment that explains what it does. It also covers a relatively obscure use case. None of this means that the code is badly written or lacking in utility.</p> <p>This developer fallacy is named after the erstwhile pop duo, Daphne &amp; Celeste, who sang &quot;U G L Y / you ain't got no alibi&quot;, which is equivalent to &quot;U G L Y / you have got an alibi&quot;.</p> Progressive Enhancement Makes Me Sad https://heydonworks.com/article/progressive-enhancement-makes-me-sad/ 2016-03-21T00:00:00.000Z https://heydonworks.com/article/progressive-enhancement-makes-me-sad/ <p>There's been a lot of talk lately in favour of progressive enhancement and 'universal' (isomorphic) applications. Apparently, server rendering increases performance, robustness, and the parsability and interoperability of content.</p> <p>I welcome these arguments because I'm magnanimous.</p> <p>But there are grave concerns regarding the adoption of progressive rendering and/or isomorphism which I feel should be addressed and apparently I'm the only one brave enough to go against the grain and address them. No need to thank me.</p> <h2>1. It's hard :(</h2> <p>Making applications which either render static content then enhance it with javascript or which run as applications on both the server and client in tandem is really, really difficult. Like <em>really</em>.</p> <p>Sure, it means that more users will be able to access content more quickly and reliably—I'm not disputing that. But who's to say there's going to <em>be</em> any users? Or any <em>content</em>, for that matter? Half the projects I work on get shelved because of company reorgs. What use is spending all that extra time on progressive enhancement complexity, then? Wise up.</p> <p>But that's not even the main problem. The main problem is that my identity is built around intellectual competency. This means that, when I find something intellectually challenging, I kind of lose it pretty badly.</p> <p>So, before you consider embarking on a universal app architecture, ask yourself: &quot;Do I really need someone to experience maddening cognitive dissonance and go postal on me?&quot;</p> <p>Probably not.*</p> <p>(*<em>This sounds kind of like a threat LOL! Soz LOL!</em>)</p> <h2>2. There are no benefits to me</h2> <p>It's true that progressive enhancement makes life easier for users in certain circumstances, like ones on high latency networks or low powered devices etc. Don't get me wrong—I'm all for writing applications for users, but aren't we forgetting someone? Since I have to build the damned app, shouldn't I get a say on how it's built?</p> <p>End users are an unknown quantity and there's not much we can do about that. On the other hand, I already know a lot about <em>me</em> because I <em>am</em> me. It's a no-brainer to be taking advantage of this insider knowledge.</p> <img src="https://heydonworks.com/images/2016/03/bell.png" alt="bell curve with target market (bell end) identified" width="522" height="397"> <p>So, what do I know about me? Well, I've got a pretty good setup for starters: Fibre, 16GB RAM. Also, I can't stand implementing progressive enhancement—<strong>gross!</strong> (see 1)</p> <p>Most of all, though, I like making new features. The less time I spend on creating a robust architecture (boring) the more time I have for creating features. And you know what they say: <strong>More features equals better UX</strong>. Everyone wins.</p> <h2>3. It encourages bad behaviour</h2> <p>If we're going out of our way (and it really is going out of our way) to make sure content can be delivered to low power devices with tiny data contracts on shitty networks, we're just giving our audience an excuse not to upgrade.</p> <p>I want you to be the best that you can be!</p> <p>Then there's trains. Urgh. So you're having trouble downloading a client-rendered, blocking-javascript-dependent web page over 2G because you're on a train? The solution's staring you in the face: <strong>Stop travelling by train.</strong> Either get a pad in the city center near your place of work or sleep under your desk. That's what I did, why can't you?</p> <p>Honestly, take some responsibility.</p> <h2>4. It's all web apps now</h2> <p>The Web was originally conceived to publish and share writing for the purposes of acquiring and corroborating knowledge. Thankfully, those dark and primitive days are behind us and we've moved onto better things, like building apps that look at photos of dogs and try to guess what age they are.</p> <p>There's no &quot;document&quot; version of an app that guesses what age your dog is. I mean, what would that even look like? A picture of someone else's dog with the text &quot;I don't know how old I am, sorry&quot; written underneath it? That's pathetic. I'd sooner just see nothing, to be perfectly frank.</p> <p>Sure, if you don't want to know how old your browser thinks your dog is, be my guest and turn off javascript or go on a train ride (see 3). You don't deserve to know how old your dog is anyway.</p> <p>Just don't come crying to me when someone close to you asks how old your dog is and you have to say, &quot;I don't know, somewhere between 5 and 8, I think&quot; instead of, &quot;I don't know, but someone shared this web app on Facebook that's quite fun. Let me show you. Hold on. Here it is. Hold on. Sorry. Hold on. Oh, never mind.&quot;</p> Writing Less Damn Code https://heydonworks.com/article/writing-less-damn-code/ 2016-08-16T00:00:00.000Z https://heydonworks.com/article/writing-less-damn-code/ <p>I'm not the most talented coder in the world. No, it's true. So I try to write as little code as possible. The less I write, the less there is to break, justify, or maintain.</p> <p>I'm also lazy, so it's all gravy. (<em>ed: maybe run with a food analogy?</em>)</p> <p>But it turns out the only surefire way to make <em>performant</em> Web Stuff is also to just write less. Minify? Okay. Compress? Well, yeah. Cache? Sounds technical. Flat out refuse to code something or include someone else's code in the first place? <strong>Now you're talking.</strong> What goes in one end has to come out the other in some form, whether it's broken down and liquified in the gastric juices of your task runner or not. (<em>ed: I've changed my mind about the food analogy</em>)</p> <p>And that's not all. Unlike aiming for 'perceived' performance gains — where you still send the same quantity of code but you chew it up first (<em>ed: seriously</em>) — you can actually make your Web Stuff <em>cheaper</em> to use. My data contract doesn't care whether you send small chunks or one large chunk; it all adds up the same.</p> <p>My <em>favorite</em> thing about aiming to have less stuff is this: you finish up with only the stuff you really need — only the stuff your <em>user</em> actually wants. Massive hero image of some dude drinking a latte? Lose it. Social media buttons which pull in a bunch of third-party code while simultaneously wrecking your page design? Give them the boot. That JavaScript thingy that hijacks the user's right mouse button to reveal a custom modal? Ice moon prison.</p> <p>It's not just about what you pull in to destroy your UX or not, though. The <em>way</em> you write your (own) code is also a big part of having less of it. Here are a few tips and ideas that might help. I've written about some of them before, but in terms of accessibility and responsive design. It just happens that a flexible, accessible Web is one we try to exert little of our own control over; one we do less to break.</p> <h2>WAI-ARIA</h2> <p>First off, WAI-ARIA != web accessibility. It's just a tool to enhance compatibility with certain assistive technologies, like screen readers, where it's needed. Hence, the <a href="https://www.w3.org/TR/aria-in-html/#first-rule-of-aria-use">first rule of ARIA use</a> is to <em>not</em> use WAI-ARIA if you don't have to.</p> <p>LOL, no:</p> <pre> <code> &lt;div role="heading" aria-level="2">Subheading&lt;/div> </code> </pre> <p>Yes:</p> <pre> <code> &lt;h2>Subheading&lt;/h2> </code> </pre> <p>The benefit of using native elements is that you often don't have to script your own behaviors either. Not only is the following checkbox implementation verbose HTML, but it needs a JavaScript dependency to control state changes and to <a href="https://twitter.com/heydonworks/status/765444886099288064">follyfill</a> standard, basic behavior regarding the <code>name</code> attribute and <code>GET</code> method. It's more code, and it's less robust. Joy!</p> <pre> <code> &lt;div role="checkbox" aria-checked="false" tabindex="0" id="checkbox1" aria-labelledby="label-for-checkbox1">&lt;/div> &lt;div class="label" id="label-for-checkbox1">My checkbox label&lt;/div> </code> </pre> <p><a href="http://wtfforms.com/">Styling? Don't worry, you're covered</a>. That's if you really need custom styles, anyway.</p> <pre> <code> &lt;input type="checkbox" id="checkbox1" name="checkbox1"> &lt;label for="checkbox1">My checkbox label&lt;/label> </code> </pre> <h2>Grids</h2> <p>Do you remember ever enjoying using/reading a website with more than two columns? I don't. Too much stuff all at once, begging for my attention. &quot;I wonder which thing that looks like navigation is the navigation I want?&quot; It's a rhetorical question: my executive functioning has seized up and I've left the site.</p> <p>Sometimes we want to put things next to things, sure. Like search results or whatever. But why pull in a whole tonne of grid framework boilerplate just for that? Flexbox can do it with no more than a couple of declaration blocks.</p> <pre> <code> .grid { display: flex; flex-flow: row wrap; } .grid > * { flex-basis: 10em; flex-grow: 1; } </code> </pre> <p>Now everything 'flexes' to be approximately <code>10em</code> wide. The number of columns depends on how many approx' <code>10em</code> cells you can fit into the viewport. Job done. Move on.</p> <p>Oh and, while we're here, we need to talk about this kind of thing:</p> <pre> <code> width: 57.98363527356473782736464546373337373737%; </code> </pre> <p>Did you know that precise measurement is calculated according to a mystical ratio? A ratio which purports to induce a state of calm and awe? No, I wasn't aware and I'm not interested. Just make the porn button big enough that I can find it.</p> <h2>Margins</h2> <p><a href="http://alistapart.com/article/axiomatic-css-and-lobotomized-owls">We've done this</a>. Share your margin definition across elements using the universal selector. Add overrides only where you need them. You won't need many.</p> <pre> <code> body * + * { margin-top: 1.5rem; } </code> </pre> <p>No, the universal selector will not kill your performance. That's bunkum.</p> <h2>Views</h2> <p>You don't need the whole of Angular or Meteor or whatever to divide a simple web page into 'views'. Views are just bits of the page you see while other bits are unseen. CSS can do this:</p> <pre> <code> .view { display: none; } .view:target { display: block; } </code> </pre> <p>&quot;But single-page apps run stuff when they load views!&quot; I hear you say. That's what the <code>onhashchange</code> event is for. No library needed, and you're using links in a standard, bookmark-able way. Which is nice. <a href="https://www.smashingmagazine.com/2015/12/reimagining-single-page-applications-progressive-enhancement/">There's more on this technique, if you're interested</a>.</p> <h2>Font sizes</h2> <p>Tweaking font sizes can really bloat out your <code>@media</code> blocks. That's why you should let CSS take care of it for you. With a single line of code.</p> <pre> <code> font-size: calc(1em + 1vw); </code> </pre> <p>Err... that's it. You even have a minimum font size in place, so no tiny fonts on handsets. Thanks to <a href="https://twitter.com/vasilis">Vasilis</a> for showing me this.</p> <h2><a href="https://a-k-apart.com/">10k Apart</a></h2> <p>Like I said, I'm not the best coder. I just know some tricks. But it is possible to do a hell of a lot, with only a little. That's the premise of the <a href="https://a-k-apart.com/">10k Apart competition</a> — to find out what can be made with just 10k or less. There are big prizes to be won and, as a judge, I look forward to kicking myself looking at all the amazing entries; ideas and implementations I wish I'd come up with myself. What will you make?</p> Aria-Controls is Poop https://heydonworks.com/article/aria-controls-is-poop/ 2016-08-21T00:00:00.000Z https://heydonworks.com/article/aria-controls-is-poop/ <p>We need to talk about <code>aria-controls</code>. It's poorly supported, does very little, and does what it does <em>when</em> it does badly. It is <em>poop</em> and we rely on it way too much. We are short-changing assistive technology users when we do.</p> <h2>What it is</h2> <p>The <code>aria-controls</code> attribute is a 'relationship attribute' which denotes which elements in a page an interactive element or set of elements has control over and affects. It's commonly used to describe a relationship between a button and the expandable region revealed by that button.</p> <pre> <code style="white-space: pre-wrap"> &lt;button aria-expanded="false" aria-controls="expandable">open / close&lt;/button> &lt;div id="expandable" hidden>content of the expandable region&lt;/div> </code> </pre> <h2>What we think it does</h2> <p>Wishfully thinking, we assume that marking up relationships with <code>aria-controls</code> means screen reader users can effortlessly flit between the moving parts of a web application, like a mechanic tinkering in a ship's engine room.</p> <p>Because we've used <code>aria-controls</code>, we don't have to worry about source order, right? We've connected up the dots explicitly, with our magic attribute! And it doesn't matter about all the elements between a controller and its subject because we've tunneled between them, right?</p> <pre> <code style="white-space: pre-wrap"> &lt;button aria-expanded="false" aria-controls="expandable"&gt;open / close&lt;/button&gt; &lt;div> &lt;!-- a load of other markup, including interactive elements in focus order --> &lt;/div> &lt;div id="expandable" hidden>content of the expandable region&lt;/div> </code> </pre> <h2>Good luck with that</h2> <p>First of all, only the JAWS screen reader supports <code>aria-controls</code>. If a user is operating NVDA or VoiceOver (or others), they would have no idea it's even there. That's reason enough not to use it.</p> <p>But, just for giggles, let's talk about <em>how</em> JAWS supports <code>aria-controls</code>. When you focus an element with the attribute included, JAWS will announce, &quot;<em>press the JAWS key plus Alt and M to move to the controlled element.</em>&quot; Verbose and clumsy. Then again, I'm not sure how else you'd go about supporting it.</p> <p>But, that's not the only problem. <strong>How in the hell do I move back?</strong> And, even if I could, how would that be communicated and how long should the option to move back remain active? No wonder the other screen reader vendors are giving this a wide berth.</p> <h2>Multiple controlled elements</h2> <p>You can create a one-to-many relationship by supplying a space separated list of <code>id</code>s, representing different, simultaneously controlled elements.</p> <pre> <code style="white-space: pre-wrap"> &lt;button aria-controls="elem1 elem2 elem3 elem4"&gt;open / close&lt;/button&gt; </code> </pre> <p>Cute! And good luck with implementing a half-decent UX there, everybody. In case you're interested, JAWS just says &quot;<em>press the JAWS key plus Alt and M to move to the controlled element</em>&quot; as normal. Genius.</p> <h2>Conclusion</h2> <p>The <em>aria-controls</em> attribute is a prime example of something we'd love to 'just work'. Trouble is, there's no clear way <em>how</em> it should work. JAWS makes a perfunctory attempt at implementation, but it's incomplete and I suspect it creates much more confusion than it provides clarity for real users.</p> <p>In the absence of a good purpose-built solution for letting folks using an interface aurally move between and around tools and their outputs, try a combination of the following:</p> <ul> <li>Same-page links to move users from one part of the interface to another</li> <li>Landmark roles to encapsulate major areas of the interface's functionality</li> <li>Expandable areas that come immediately after their <code>aria-expanded</code> controllers in the source (and in focus order)</li> </ul> <p>There's also the question of 'focus management'. In keyboard and screen reader accessibility terms, focus management usually means using the <code>focus()</code> method in JavaScript to move focus between elements. Be aware that, in almost all cases, users <strong>do not</strong> want to be moved from one place to another without their explicit say-so. Even when they <em>do</em> want to, providing a link is probably your best bet.</p> <p>I think I'll give the focus management wasps' nest a proper poke on another occasion.</p> Accessibility, The Free Market, and Punching Nazis While Sitting Down https://heydonworks.com/article/accessibility-the-free-market-and-punching-nazis-while-sitting-down/ 2017-02-06T00:00:00.000Z https://heydonworks.com/article/accessibility-the-free-market-and-punching-nazis-while-sitting-down/ <p>Before Hitler set about exterminating Jewish people, he practiced on the disabled. The <a href="https://en.wikipedia.org/wiki/Aktion_T4"><em>Aktion T4</em> programme</a> was particularly fond of administering "involuntary euthanasia" to children. Parents were tricked into relinquishing their little ones with the promise that they would be offered special care. This special care consisted of a lethal injection, and would be recorded as a tragic case of pneumonia.</p> <p>Victims included those with Down syndrome, cerebral palsy, and various localized deformities. A district judge, Lothar Kreyssig, wrote to protest against the programme. The minister of justice, Franz Gürtner, replied: "If you cannot recognize the will of the Führer as a source of law, then you cannot remain a judge."</p> <p>Kreyssig was deposed. In towns hosting killing centers, residents reported the persistent smell of burnt human hair.</p> <p>The Nazis believed disabled people were better off dead. I'll leave you to decide whether they felt it was better for the 'patients', better for the Nazi vision of society from which they were being expunged, or better for both. In any case, the Nazis saw no <em>value</em> in these people.</p> <p>So it was under German fascism. Since the 40s, fascists operating within ostensible democracies have had to find ways to obfuscate their intentions, including their disableist ones. And I don't just mean the ability to hide behind digitally transmitted pictures of cartoon frogs.</p> <p>Of course there are obvious displays of ignorance, like Donald Trump <a href="http://www.thedailybeast.com/articles/2016/10/13/donald-trump-called-deaf-apprentice-marlee-matlin-retarded.html">referring to deaf actress Marlee Matlin as "retarded"</a>, or Betsy DeVos <a href="https://www.washingtonpost.com/news/answer-sheet/wp/2017/01/18/six-astonishing-things-betsy-devos-said-and-refused-to-say-at-her-confirmation-hearing/?utm_term=.532c578530d3">having seemingly no understanding of The Individuals With Disabilities Education Act</a>. But it runs much deeper than this.</p> <p>Attorney General appointee, <a href="http://www.independent.co.uk/news/world/americas/us-elections/donald-trump-attorney-general-disabled-children-comments-jeff-sessions-schools-failing-decline-in-a7447246.html">Jeff Sessions is on record</a> saying he believes protections helping to integrate disabled children have accelerated the decline of "civility and discipline" in mainstream classrooms. The notion that groups which include disabled people are less <em>civilized</em> as a result is particularly striking for its fascistic overtones.</p> <p>That's not to say Sessions outright proposes the eradication of the disabled from society, Nazi-style. But, then again, he wouldn't have to. There's a more passive way of killing off those deemed surplus, and that's by letting them die neoliberalism-style. That's precisely what the <a href="https://www.nytimes.com/2017/01/22/us/politics/donald-trump-health-plan-medicaid.html?_r=0">slashing of Medicaid</a>, the <a href="https://www.theatlantic.com/politics/archive/2017/01/the-trump-administrations-first-blow-to-obamacare/514103/">trashing of the ACA</a>, the segregation and disenfranchisement of the disabled in education, and the diminishing of workplace rights would mean.</p> <p>Of course, to get away with this you need an alibi. And that alibi comes in the form of a particular brand of freedom. According to the <a href="https://en.wikipedia.org/wiki/Capitalism_and_Freedom">Milton Friedman school of free market economics</a>, true deregulation will lead to the eradication of discrimination. Why? Because there's money to be made by and from all types of people. Pure market forces, we're told, are "color blind". Ergo, cutting state support for the vulnerable is actually <em>good</em> for them!</p> <p>There's just one problem with this ideology: It's a trap. The rich establishment don't need intervention and support from the state. At the point that it is removed, they are placed at an increased advantage, happily able to exploit the market and those now placed at its mercy.</p> <p>The market has no mercy. That's the point. But like the <a href="https://www.autostraddle.com/i-was-trained-for-the-culture-wars-in-home-school-awaiting-someone-like-mike-pence-as-a-messiah-367057/">Christofascist</a> God for which it makes a telling analogue, it cannot be questioned. To tamper with market forces means to defy its will. Accordingly, when the Americans With Disabilities Act (ADA) was first discussed at the start of the 1990s, it was <a href="http://thehill.com/blogs/pundits-blog/healthcare/309299-disability-and-the-trump-administration-whats-next">met with opposition</a>. Business leaders argued it represented a reregulation of the labor market, which ultimately would lead to greater opportunities for discrimination.</p> <p>This was all completely disingenuous, of course. These people don't really believe in God <em>or</em> the free market. They want to be free to discriminate as they please, for greater personal gain, and for everyone else to believe they are entitled to do so guilt free. They are interested in <em>being</em> Gods.</p> <p>One way this is achieved is by erasing the meaning of being disabled. It is for good reason that <a href="http://www.autistichoya.com/2013/08/differently-abled.html">many object to the term "differently abled"</a>: Differently abled implies <em>equally</em> abled, and equally abled means you can weather the "mysterious ways" of the market just as well as me. You don't need support or special treatment.</p> <p>This works as well for mental health as for physical: As a depressive, I'm told it is my <em>choice</em> to feel that way; I'm just wallowing. There's a gleeful orgy of futility happening down at the marketplace, and I don't want to get on the bus. It's my own fault I'm missing out.</p> <p>Another way of leveraging the concept of the market to defer guilt is through the notion of niche. Friedman's model imagines greater prosperity for all, but that's not to say the market would become homogenous. There would still be sectors and segments; varieties of business and product.</p> <p>By characterizing disability as a discrete 'target' group, the aim is to excuse the creation of products and services which do not cater for disability. "Oh I'm not making things for disabled people. But I'm sure someone else is, don't worry. Such-and-such law of economics states it must be so." </p> <p>Disability does not work that way, though. It isn't a discrete community or field of interest. It is complex, multifaceted and pervades all kinds of cultural identity through race, socio-economic level, gender identity, and faith. If you create an inaccessible product or service, you are almost guaranteed to be disenfranchising someone, including your future self.</p> <p>It is because disability is such a broad category of human experience that it's so easy to neglect. Even some of those trying to combat discrimination and bigotry have trouble grappling with disability rights as civil rights. It was, after all, amid concerns that the Women's Marches did not originally include a clear statement on accessibility that the <a href="http://mashable.com/2017/01/18/disability-march-womens-march-on-washington/#xG6IuK2.zmqc">virtual march</a> was conceived.</p> <h2 id="afewthingstoremember">A few things to remember</h2> <p>Firstly, try not to snort at "armchair activists". Some don't have the choice. They'd like to march, but they simply can't.</p> <p>Secondly, be wary of people who insist on removing politics from conversation or company policy. The official position is that we live in a meritocracy, benevolently guided by market forces, so positive discrimination is not necessary. You'll find that it is only the ones who are already well represented and paid that take this stance (remember the 'trap' I described previously). </p> <p>It's more passive and less transparent to discourage political discourse than it is to outright tell someone that <em>their</em> politics is not welcome. If someone tells you to "take the politics" out of what you're doing, or to "stop making things political", it's not because anything benefits from being less political as such. It's because they don't want to make room for <em>your</em> politics in that space. That would mean taking some of theirs out. Well screw that; resist.</p> <p>Thirdly, be aware that making accessible products and interfaces under a regime that regresses on disability rights <em>is</em> resistance. It goes against the prevailing ideology. Do it loudly and help others get up to speed. This is especially important when devising protests and related resources. When you're inclusive, you reach more allies.</p> <p>Finally, whether or not you believe it is right or sensible to punch a neo-nazi, remember that not everyone who might like to punch a neo-nazi has the physical strength, the dexterity, or even the appendage to do so. And some of these people would be first in line if they did, because they know fascists are the kind of cowards that pick on them first. Accordingly, whether you aim to do it literally or figuratively, punch a neo-nazi for someone who can't.</p> HTML Is Broken https://heydonworks.com/article/html-is-broken/ 2017-03-28T00:00:00.000Z https://heydonworks.com/article/html-is-broken/ <p>Yes, HTML is broken (see title ↑). Anyone who has used HTML on a big project knows it.</p> <p>Just the other day, I went to code a submit button for a form. Should be pretty straightforward. Well how come this is what I wrote, then?</p> <pre> <code>&lt;table> &lt;td> &lt;a class="submit"> &lt;img src="submit-image.bmp"> &lt;/a> &lt;/td> &lt;/table> </code></pre> <p>I've had complaints from users saying they &quot;can't use this shit&quot; and mean developer &quot;friends&quot; have pointed and laughed at me, like it's some sort of failing on my part.</p> <p>But let's look at the facts:</p> <ol> <li>I have a degree in computer science</li> <li>I literally probably have a really high IQ. That stands to reason.</li> <li>I live in San Francisco</li> <li>That's where Silicon Valley is. <strong>Ever heard of it??</strong></li> </ol> <p>I may have majored in computer science, but I minored in rationalist scientific enquiry. I say minored; it was more of a hobby. Anyway, given the <strong>FACTS</strong> provided above, if I see myself writing shit code I can only draw one logical conclusion:</p> <blockquote><p>It's not me who's stupid, it's you. You stupidly designed the stupid thing I'm trying to use stupidly and it's all your fault. Stupid HTML standardista stupid bum faces.</p></blockquote> <p>I rest my case.</p> <p>But if that isn't enough to convince you that HTML is trying to make me look bad, wait until you see <em>just how poorly</em> HTML deals with basic arithmetic! Consider the following code example:</p> <pre> <code> &lt;p> + &lt;i> </code> </pre> <p>Which of the following do you think the above code evaluates as? The answer may surprise you.</p> <ol> <li><code>&lt;p>&lt;i></code></li> <li><code>&lt;pi></code></li> <li><code>&#x3c0;</code></li> <li><strong>IT JUST WRITES IT OUT THE SAME THEN COMPLAINS AT ME ABOUT MISSING CLOSING TAGS WHATEVER THEY ARE??1!!?1!</strong></li> </ol> <p>I can do basic arithmetic, HTML. Why can't you? Oh, you're a &quot;markup language&quot; are you? Well <em>bully for you</em>. I didn't learn about HTML in my Ivy League university of choice, so how could I know that?</p> <p>Fine, whatever. When there's an international standard for formatting and transmitting digital information available, <strong>I'LL USE IT TO FUCKING WELL LOOK UP WHAT HTML IS, HOW ABOUT THAT?</strong></p> <hr> <p>Idea for this article from <a href="https://twitter.com/petervangrieken">@petervangrieken</a>.</p> <p>If you're struggling with the finer points of writing accessible markup, I have a new blog called <a href="http://inclusive-components.club/">Inclusive Components</a> which explores the inclusive design of web interfaces.</p> Who Is Inclusive Design For? https://heydonworks.com/article/who-is-inclusive-design-for/ 2017-12-07T00:00:00.000Z https://heydonworks.com/article/who-is-inclusive-design-for/ <p>If you simultaneously</p> <ul> <li>Have perfect eyesight</li> <li>Have excellent motor control and coordination</li> <li>Speak English as a first language</li> <li>Find reading and processing complex information easy</li> <li>Never get tired</li> <li>Have as much free time as you wish</li> <li>Live somewhere with access to super fast internet</li> <li>Can afford super fast internet</li> <li>Have a top-of-the-range smartphone or computer</li> <li>Have perfect hearing</li> <li>Never suffer any injuries or illnesses, even temporarily</li> <li>Never feel the effects of pain</li> <li>Are a member of a preferred social/cultural group</li> </ul> <p>then you may not benefit from inclusive design.</p> CSS: A New Kind Of JavaScript https://heydonworks.com/article/css:-a-new-kind-of-javascript/ 2018-07-12T00:00:00.000Z https://heydonworks.com/article/css:-a-new-kind-of-javascript/ <p><em><a href="https://medium.com/@Heydon/css-a-new-kind-of-javascript-fcf730d33ce7">Originally published on Medium</a>.</em></p> <p>Those familiar with the web platform will be well-versed in its two complementary technologies: <strong>HTML</strong> for documents and their structure, and <strong>JavaScript</strong> for interaction and styling.</p> <p>For as long as anyone can remember, styling documents — affecting their appearance — has been facilitated via the JavaScript <code>style</code> property, which is exposed for any supporting DOM node.</p> <pre><code>node.style.color = 'red';</code></pre> <p>Before the advent of this styling API, HTML authors had to write style attributes into the DOM manually, impeding the editorial process.</p> <p>Combined with JavaScript’s node selection engine, we are able to style multiple elements simultaneously. In the following example, all <code>p</code> nodes are styled with the red text color.</p> <pre><code>const nodes = document.querySelectorAll('p'); Array.prototype.forEach.call(nodes, node => { node.style.color = 'red'; });</code></pre> <p>One of the great things about this selector engine is it allows one to target different elements simultaneously, by providing a comma-separated list.</p> <pre><code>const nodes = document.querySelectorAll('p, li, dd');</code></pre> <p>What’s less straightforward is attaching multiple styles to any one node. The following approach quickly becomes verbose.</p> <pre><code>node.style.color = 'red'; node.style.backgroundColor = 'black'; node.style.padding = '1rem'; // etc.</code></pre> <p>The only standardized alternative is to use the <code>cssText</code> property:</p> <pre><code>node.style.cssText = 'color: red; background-color: black; padding: 1rem;';</code></pre> <p>Managing multiple styles as a single string is problematic. It makes it difficult to update, remove, or replace individual styles at a later point in time.</p> <p>For this reason, authors have invented ways to manage styling information in objects, often by manipulating the <code>Element</code> interface’s prototype.</p> <pre><code>Element.prototype.styles = function(attrs) { Object.keys(attrs).forEach(attr => { this.style[attr] = attrs[attr]; }); }</code></pre> <p>Adding styles to a node is now possible like so:</p> <pre><code>node.styles({ 'color': 'red', 'backgroundColor': 'black', 'padding': '1rem' });</code></pre> <p>This assignment approach tends to get used <em>a lot</em> throughout an application and its lifecycle. It’s infamously difficult to know where to put all this stuff, or how to clearly separate it from the interaction scripting that is JavaScript’s other responsibility.</p> <p>But there’s another, more fundamental, problem: these style properties are not reactive. For example, let’s say I’ve set some styles for disabled buttons:</p> <pre><code>const disableds = document.querySelectorAll('[disabled]'); Array.prototype.forEach.call(disableds, disabled => { disabled.styles({ 'opacity': '0.5', 'cursor': 'not-allowed' }); });</code></pre> <p>These styles only apply to disabled buttons that are already in the DOM. Any disabled buttons added to the DOM or — more likely—buttons that acquire the disabled property/attribute, will not automatically adopt the appropriate styling.</p> <pre><code>button.disabled = true; button.style // nothing new here </code></pre> <p>It is possible to listen for the attribute change and react to it using <code>mutationObserver</code>:</p> <pre><code>const button = document.querySelector('button'); var config = { attributes: true } var callback = function(mutationsList) { for(var mutation of mutationsList) { if (mutation.type == 'attributes') { if (button.disabled) { button.styles({ 'opacity': '0.5', 'cursor': 'not-allowed' }); } } } } var observer = new MutationObserver(callback); observer.observe(button, config);</code></pre> <p>I think we can agree this is quite a lot of code, especially since it only makes one instance of one type of element reactive to one type of attribute change. It also only changes the styling in one direction: we’d have to handle reverting the styles when the disabled property is removed. Not easy, since we don’t know the initial values for <code>opacity</code> or <code>cursor</code>.</p> <p>As much as I like JavaScript, I don’t think it’s very well designed when it comes to styling tasks. It is, after all, a procedural and event-based language, whereas style is just something you have or you don’t.</p> <p>We waste far too much time writing and maintaining styles with JavaScript, and I think it’s time for a change. Which is why it’s my pleasure to announce an emerging web standard called <strong>CSS</strong>.</p> <h2>CSS</h2> <p>CSS is a declarative subset of JavaScript, optimized for styling tasks. A CSS file takes the <code>.css</code> extension and, importantly, is parsed completely separately to standard JavaScript files. With CSS it’s finally possible to separate style from behavior. You can brand your applications without having to touch your business logic!</p> <h3>Syntactic sugar</h3> <p>One of the first things you’ll notice is the cleaner syntax, which fans of CoffeeScript will appreciate:</p> <pre><code>[disabled] { opacity: 0.5; cursor: not-allowed; }</code></pre> <p>The object-like structure remains, but you no longer have to explicitly call upon <code>querySelectorAll</code> to iterate over DOM nodes. The iteration is taken care of internally instead, making it more performant too.</p> <p>The above example affects all DOM nodes with the <code>disabled</code> attribute automatically. Better yet: any new buttons adopting the disabled property will immediately adopt the associated styles. Reactive out of the box!</p> <h3>The cascade</h3> <p>CSS stands for <strong>Cascading Style Sheets</strong>. The cascading part is perhaps its best feature. Consider the following CSS.</p> <pre><code>button { background-color: blue; cursor: pointer; } [disabled] { cursor: not-allowed; }</code></pre> <p>The styles for the <code>[disabled]</code> ‘block’ come after the <code>button</code> block in the style sheet. Any styles declared in the <code>[disabled]</code> block with the same keys (property names) as those in the preceding <code>button</code> block become overrides. The upshot is that adding the <code>disabled</code> attribute/property to a button only updates pertinent styles. In the above example, <code>cursor</code> is updated but <code>background-color</code> remains the same. It’s a kind of filtering system.</p> <p>In addition, where the <code>disabled</code> attribute/property is removed, the default styles are automatically reinstated — because now the node only matches the <code>button</code> block further up the cascade. No need to ‘remember’ which styles have been applied and under which conditions.</p> <h3>Resilience</h3> <p>When styling with JavaScript, any unrecognized style properties or syntax mistakes will cease the parsing of the script. Any ensuing styles or interactions will simply be dropped en masse and your whole application will fall over.</p> <p>CSS is more robust. In most cases, an unrecognized property or a syntax mistake will only cause the single, erroneous declaration (property/value pair) to be dropped.</p> <p>This innovation acknowledges that different browsers support different styling properties, and that individual styles are not mission critical. The resilience of CSS means more users get access to a functional interface.</p> <h2>Conclusion</h2> <p>A good sign that a technology is not fit for purpose is how much we have to rely on workarounds and best practices to get by. Another sign is just how much code we have to write in order to get simple things done. When it comes to styling, JavaScript is that technology.</p> <p>CSS solves JavaScript’s styling problems, and elegantly. The question is: are you willing to embrace the change, or are you married to an inferior methodology?</p> <p>For more information on CSS and tips on getting up and running, <a href="https://en.wikipedia.org/wiki/Campus_SuperStar">read this primer</a>.</p> Reluctant Gatekeeping: The Problem With Full Stack https://heydonworks.com/article/reluctant-gatekeeping:-the-problem-with-full-stack/ 2018-12-03T00:00:00.000Z https://heydonworks.com/article/reluctant-gatekeeping:-the-problem-with-full-stack/ <p>Much of my career as a web designer has been spent, quite happily, working alongside programmers, engineers, people with computer science degrees. In this symbiotic relationship, each party has a secure job with a well-defined role, and gets to work on the thing they are best at and enjoy the most.</p> <p>It’s not that the computer scientists get to do all the code; it’s that they get to do architecture while I do communication, form, and interaction. We all code, because we work on the web, but we code in different ways to achieve different and complementary ends.</p> <p>But that’s not so obvious to someone who doesn’t code at all: it’s easy to think coders are people who do <em>all</em> the code you’re <em>not</em> doing — because, to the untrained eye, all code is the same.</p> <p>This misconception has unfortunate consequences, exacerbated by the non-coder often being the one who gets to choose and hire technical staff. The doctrine of capitalism dictates you should squeeze the most value out of the fewest resources. That’s how you make a profit. If you can find wage slaves willing to do All The Codez™, then you can significantly diminish your biggest overhead: <em>people</em>.</p> <p>And so the Full Stack Developer emerges in the market, like an Uruk-hai emerging from its grimy placenta: stronger, better, problematic.</p> <p>Problematic how? Well, HTML, CSS, JavaScript, Python, C#, and SQL may all be code, but they’re really quite different kinds of code and are suited to different kinds of people. Just taking the frontend technologies: HTML, a metalanguage, is closely associated with language, narrative and meaning: the realm of the writer. CSS codifies form, the purview of the typographer and graphic artist, while JavaScript (client-side in this case, but the real™ programming language to a computer scientist) deals in things like data transmission and events.</p> <p>This is all to say that, if you put someone in charge of all of these things, it’s highly likely they are going to be much weaker in some areas than others (I’m identifying a trend here; there’s no need to comment with “but I can do all the things”, thank you). Worse: they’ll tend to have little interest in improving in areas with which they don’t identify or for which they aren't rewarded. In my experience, men especially earn kudos for their knowledge of JavaScript, but little from CSS skills. CSS, which makes things look ‘pretty’, is considered feminine (don’t tell that to a peacock).</p> <p>By assuming the role of the Full Stack Developer (which is, in practice, a computer scientist who also writes HTML and CSS), one takes responsibility for all the code, in spite of its radical variance in syntax and purpose, and becomes the gatekeeper of at least some kinds of code <strong>one simply doesn’t care about writing well</strong>. This has two adverse effects:</p> <ol> <li>Poor quality code</li> <li>A bunch of people who can (and would enjoy!) expertly writing that code, standing unemployed on the sidelines muttering “WTF”</li> </ol> <p>As an inclusive design consultant, one of the most glaring issues with making Full Stack Developers the gatekeepers of all-things-code is the pitiful quality of the HTML output. Most come from a computer science background, and document structure is simply not taught alongside control structure. It’s not their competency, but we still make it their job.</p> <p>To a ‘classical’ computer scientist, CSS can be quite elusive. Features like the cascade just don’t <em>feel</em> right. To make CSS easier to write and manage, it becomes subsumed by something more familiar, hence CSS-in-JS.</p> <p>CSS-in-JS is often characterized as a solution (by practitioners) or a problem (by naysayers) in technical terms. I don’t think it makes the actual CSS intrinsically any better or worse — it’s just a different way to write it. But that’s not to say it doesn’t pose a grave cultural issue:</p> <p>Put CSS in JS and anyone who wishes to write CSS now has to know JavaScript. Not just JavaScript, but —most likely—the specific ‘flavor’ of JavaScript called React. That’s gatekeeping, first of all, but the worst part is the JavaScript aficionado didn’t want CSS on their plate in the first place.</p> <p>I recently worked with an organization where there were dozens of Full Stack Developers and no Frontend Developers. We had a website to build and nobody understood Flexbox, except me. Of course I was happy to help, but I had to learn React on the job to put the work in place. Fortunately I picked it up quite quickly, but the next CSS expert may not have done. The value you want from a CSS expert is their CSS, not their JavaScript, so it's absurd to make JavaScript a requirement.</p> <hr> <p name="f604" id="f604" class="graf graf--p graf--leading">To conclude, here are a few things I think we need to address:</p><ol class="postList"><li name="2080" id="2080" class="graf graf--li graf-after--p">We need to identify exploitation. While there are some gleeful Full Stack Developers, many are computer scientists given too many responsibilities, and over things for which they are not willing or qualified to be held accountable.</li><li name="02fd" id="02fd" class="graf graf--li graf-after--li">We need to address the undervaluing of HTML and CSS for what it is: gender bias. Even though we wouldn’t have computer science without pioneering women, interloping men have claimed it for themselves. Anything less than ‘real programming’ is now considered trivial, silly, artsy, female. That attitude needs to eat a poisoned ass.</li><li name="3d43" id="3d43" class="graf graf--li graf-after--li">We need to revisit the separation of concerns principle. We simple can’t afford for people to have to <em class="markup--em markup--li-em">know everything</em> just to <em class="markup--em markup--li-em">do something</em>. It’s good that we conceptualize designs in terms of self-contained components now, but that can be a mental model without being a technology-specific land-grab.</li><li name="b01f" id="b01f" class="graf graf--li graf-after--li graf--trailing">Most of all, we need to educate people who don’t code at all just how many different things different types of code can do, and how different each is to understand and write. Hopefully, this way, more of us will be writing the kind of code that suits us best, and not spending our time anxious and demoralized because we don’t know what we’re doing. That’s not to say that if you <em class="markup--em markup--li-em">do</em> take to JS, CSS, HTML, SQL, and C# you shouldn’t be writing all of them if you‘d like to and you have enough time!</li></ol> The Flexbox Holy Albatross https://heydonworks.com/article/the-flexbox-holy-albatross/ 2019-01-13T00:00:00.000Z https://heydonworks.com/article/the-flexbox-holy-albatross/ <p>For the last 6 or so months, I've been engaged in a number of activities including (but not limited to):</p> <ul> <li>Scratching my head</li> <li>Staring out of the window</li> <li>Laying in bed and staring at the ceiling</li> <li>Screaming into a pillow</li> <li>Rolling around on the floor sweating feverishly while muttering archaic and forbidden incantations</li> </ul> <p>Coincidentally, I've been spending this same time period trying to solve a particularly vexing CSS layout problem. You might say the problem has become both my albatross and my Holy Grail; my Holy Albatross, if you will.</p> <p>At 5am this morning, through the fug of a Tiny Rebel Stay Puft Marshmallow Porter™ hangover, the solution struck me. And now I'm going to share it with you.</p> <h2>The problem</h2> <p>With Flexbox you can combine <em>wrapping</em> (<code>flex-wrap: wrap</code>) and <em>growing</em> (<code>flex-grow: 1</code>) to ensure all flex items fall into their rightful place across different viewport widths. Flexbox can create an effortlessly responsive layout with no collisions or unseemly gaps in sight.</p> <p>The trouble is, sometimes you want your items to wrap in a very particular way. For instance, when you have three items, you'll be happy with the three-abreast layout and accepting of the single-column configuration. But you might like to avoid the intermediary part where you get a pair of elements on one line followed by a longer element underneath.</p> <div><img src="https://heydonworks.com/images/2019/01/flex1.png" alt="The three in a row layout bypasses the 2 followed by 1 layout straight to the one per row layout" width="799" height="118" class="alignnone size-full wp-image-676"></div> <p>Why? Well, when you have a set of three equivalent items and one is displayed differently it looks deliberate — like you consider the third item special and want the user to perceive it that way. It's bigger; does that mean it's better? Or more important?</p> <p>But never mind the whys and wherefores. How do we skip this intermediary layout state and switch directly from a horizontal to vertical triptych? What's the solution?</p> <h2>Use a media query, silly</h2> <p>No, I don't want to. In fact, <strong>I outright refuse to</strong>. And it's not just because I'm self-conscious about writing the cleanest and cleverest code. It's because <strong><code>@media</code> breakpoints are anathema to design systems</strong>. My component, defined outside of context, could be instantiated within a container/parent element of any width. Context is variable, but all <code>@media</code> queries can do is adjust things according to the constant that is the viewport.</p> <div><img src="https://heydonworks.com/images/2019/01/flex2.png" alt="In a wide viewport the elements are on one row. On a narrow viewport they are on three rows. Unfortunately, in a narrow context inside a wide viewport its one row." width="901" height="316" class="alignnone size-full wp-image-677"></div> <p>Useless, actually. And that's why so many people have been writing and fighting and conspiring for <a href="https://css-tricks.com/container-query-discussion/">container queries</a>: breakpoints that correspond to the immediate container element instead of the viewport.</p> <p>The trouble is, container queries ask a lot from browsers and nobody's come up with a native CSS solution that would be acceptably performant. Soooooo… JavaScript?</p> <h2>JavaScript all the things</h2> <p>Using <code>ResizeObserver</code> you can spawn element/container queries with very little code. I spun this little module up earlier this morning; you can have it.</p> <pre><code>export default function markBreak(elem, width) { if (ResizeObserver) { const test = document.createElement('div'); test.classList.add('test'); test.style.width = width; elem.appendChild(test); let br = test.offsetWidth; elem.removeChild(test); const ro = new ResizeObserver( entries => { for (let entry of entries) { const cr = entry.contentRect; const q = cr.width &lt;= br; entry.target.classList.toggle('lt-' + width, q); entry.target.classList.toggle('gte-' + width, !q); } }); ro.observe(elem); } }</code></pre> <p>(There's a great <a href="https://developers.google.com/web/updates/2016/10/resizeobserver">intro to ResizeObserver by Surma</a>.)</p> <p>If I wanted my triptych to become a vertical column from <code>40rem</code>, I'd just execute <code>markBreak(container, '40rem')</code> and write this CSS:</p> <pre><code>.container > * { width: 100%; } .container.gte-40rem > * { width: 33%; } </code></pre> <p>Not bad because:</p> <ol> <li><code>ResizeObserver</code> is optimized for efficiency. Much less janky than using <code>onresize</code> or some such horror</li> <li>It's a progressive enhancement: if JavaScript doesn't run, or <code>ResizeObserver</code> isn't supported, the user gets a perfectly adequate single column configuration regardless of the container width.</li> <li>The <code>test</code> element lets you choose a breakpoint using any unit. '20em' would be accurate because the relative dimension is translated to pixels <em>for the current context</em> (20rem could mean something else entirely elsewhere in the page).</li> </ol> <p>But actually it's quite bad because:</p> <ol> <li>JavaScript may well not run, and is always relatively intensive when it does. And it makes you bleed profusely from your anus.</li> <li><code>ResizeObserver</code> is currently only supported in Chrome and *checks notes* Opera for desktop.</li> </ol> <p>So is there a CSS-only solution? Yes, there is (well, HTML and CSS to be honest). I hope you like custom properties and the <code>calc()</code> function.</p> <h2>Solved with CSS</h2> <p><strong>HOLD YOUR HORSES!</strong> <em>I now have a MUCH SMARTER solution using just <code>flex-basis</code>, meaning any number of horizontal elements can be switched to a vertical configuration. This will probably suit you better. See <a href="http://www.heydonworks.com/article/the-flexbox-holy-albatross-reincarnated">The Flexbox Holy Albatross Reincarnated</a>.</em></p> <p>Let's break this down. I want my component to be flexible; to grow and shrink. However, I only want the items to take up <em>either</em> 33% or 100% of the container/parent element's width. The easy part is ensuring the elements never take up <em>less</em> than 33% or <em>more</em> than 100%:</p> <pre><code>.container > * { min-width: 33%; max-width: 100%; flex-grow: 1; }</code></pre> <p>(The <code>flex-grow</code> part is really just because I can't be bothered to write out 33.33333333333%. It makes sure each column distributes to take up exactly one third of the space.)</p> <p>The <code>flex-basis</code> property sets the basic/initial width for any item. Items can still grow and shrink from the <code>flex-basis</code> value where there's room. Critically, <code>min-width</code> and <code>max-width</code> override <code>flex-basis</code>. So if the <code>flex-basis</code> value is absurdly high, like 999rem, the width will fall back to 100%. If it's absurdly low, like -999rem, it'll default to 33% (or 33.333333333333% thanks to <code>flex-grow</code>).</p> <div><img src="https://heydonworks.com/images/2019/01/flex4.png" alt="Diagram shows how the absurdly low and high flex-basis values pull the width to the minimum and maximum points of 33% and 100% respectively" width="900" height="165" class="alignnone size-full wp-image-688"></div> <p>The key is making this switch at the desired point. For argument's sake, this point will be 40rem. At below 40rem, the items will be on one row. At 40rem and above, they'll each have their own row.</p> <p>On the container, I set a custom property, <code>--multiplier</code>:</p> <pre><code>.container { display: flex; flex-wrap: wrap; --multiplier: calc(40rem - 100%); }</code></pre> <p>That's right: the calculated value will be negative if the container is 40rem or more and positive if it's narrower than 40rem. On the flex items we use this as a multiplier, setting our absurdly high or absurdly low <code>flex-basis</code> value. 999 is customary in these situations.</p> <pre><code>.container > * { min-width: 33%; max-width: 100%; flex-grow: 1; flex-basis: calc(var(--multiplier) * 999); }</code></pre> <div><img src="https://heydonworks.com/images/2019/01/flex3.png" alt="In a wide viewport the elements are on one row. On a narrow viewport they are on three rows. Now, in a narrow context inside a wide viewport the items are one per row as desired" width="901" height="316" class="alignnone size-full wp-image-678"></div> <p>And that is that.</p> <p><strong>Edit:</strong> <em>As Snook points out in his <a href="https://snook.ca/archives/html_and_css/understanding-the-flexbox-albatross">follow-up post</a>, the custom property isn't needed. I should have explained you can just include the value as part of the child element's calc. Why? Because <code>100%</code> is the same for the parent and the child. However, I like to name and set this value with the container, for readability. It's also neat how dynamic custom property values are automatically inherited. There might be more wild things can be done with that.</em></p> <p>Unless you want margins. You can use the negative margin hack (as <a href="https://youtu.be/qOUtkN6M52M?t=269">demonstrated in my video</a>) to keep things flush, but you need to remove the margin from the <code>min-width</code> value to make sure things still 'switch' where they're supposed to:</p> <pre><code>.container { display: flex; flex-wrap: wrap; --margin: 1rem; --multiplier: calc(40rem - 100%); margin: calc(var(--margin) * -1); /* excess margin removed */ } .container > * { min-width: calc(33% - (var(--margin) * 2)); /* remove from both sides */ max-width: 100%; flex-grow: 1; flex-basis: calc(var(--multiplier) * 999); margin: var(--margin); }</code></pre> <p>(This will become redundant when the <code>gap</code> property is more widely supported. Think <code>grid-gap</code> but for Grid, Flexbox, and other contexts.)</p> <p>It can also work with different numbers of elements and elements of different widths. For example, given four elements, you may want the odd ones to be 20% and the even ones 30% above 60rem. Here's Flexbox, custom properties, <code>calc()</code>, and <code>nth-child</code> all working nicely together:</p> <pre><code>.container { display: flex; flex-wrap: wrap; --margin: 1rem; --multiplier: calc(60rem - 100%); margin: calc(var(--margin) * -1); } .container > * { max-width: 100%; flex-grow: 1; flex-basis: calc(var(--multiplier) * 999); margin: var(--margin); } .container > :nth-child(2n - 1) { min-width: calc(20% - (var(--margin) * 2)); } .container > :nth-child(2n) { min-width: calc(30% - (var(--margin) * 2)); </code></pre> <p>(Note the use of <code>*</code> and the cascade here, so not to redundantly repeat shared declarations. The older CSS stuff still pulls its weight!)</p> <p><a href="https://codepen.io/heydon/pen/ebQyYV">Here is a demo of the basic version in CodePen</a>. If you want to learn more about algorithmic layouts for the web, <a href="https://www.youtube.com/watch?v=qOUtkN6M52M">I have a video you might like</a>. See also <a href="https://medium.freecodecamp.org/the-fab-four-technique-to-create-responsive-emails-without-media-queries-baf11fdfa848">The Fab Four technique</a> which, as was pointed out to me, arrives at a very similar solution, except with <code>width</code> in place of <code>flex-basis</code>.</p> The Flexbox Holy Albatross Reincarnated https://heydonworks.com/article/the-flexbox-holy-albatross-reincarnated/ 2019-01-14T00:00:00.000Z https://heydonworks.com/article/the-flexbox-holy-albatross-reincarnated/ <p>You may want to read the original <a href="http://www.heydonworks.com/article/the-flexbox-holy-albatross">Flexbox Holy Albatross post</a> but basically, I missed a step (I was hungover): You can switch between horizontal (multi-column) to vertical (single column) Flexbox layouts just using <code>flex-basis</code>. No <code>min-width</code> or <code>max-width</code> needed — in fact, they just restrict Flexbox from doing its beautiful Flexbox thing.</p> <p>This way, <em>any</em> number of horizontal elements can become vertical elements at a 'container query' breakpoint (<code>40rem</code> in the below example).</p> <p><a href="https://codepen.io/heydon/pen/JwwZaX">Here's a CodePen</a>.</p> <h2>The code</h2> <pre><code>.container { display: flex; flex-wrap: wrap; --margin: 1rem; --modifier: calc(40rem - 100%); margin: calc(var(--margin) * -1); } .container > * { flex-grow: 1; flex-basis: calc(var(--modifier) * 999); margin: var(--margin); }</code></pre> <p>Also: <a href="https://twitter.com/heydonworks/status/1084856193795919874">You can set different individual item widths with <code>flex-grow</code> still</a>.</p> <h2>The Holy Albatross with a Quantity Query</h2> <p>What if you wanted to display the items horizontally above a certain container width <em>only</em> if there are fewer than a certain number of items. <a href="https://codepen.io/heydon/pen/RvZQXR">This CodePen</a> does just that. It also removes the custom properties (which are just for readability, really) so it works in Internet Explorer!</p> Web Accessibility Is Out To Get You And Make You Feel Sad https://heydonworks.com/article/web-accessibility-is-out-to-get-you-and-make-you-feel-sad/ 2019-10-21T00:00:00.000Z https://heydonworks.com/article/web-accessibility-is-out-to-get-you-and-make-you-feel-sad/ <p>Since the <a href="https://arstechnica.com/tech-policy/2019/10/accessibility-the-future-and-why-dominos-matters/">landmark Domino's case</a>, I've been having some conversations about web accessibility with people who wouldn't ordinarily take an interest. Some of these conversations have been productive; others have not. The following is a dramatization based on true events.</p> <hr> <p>DEVELOPER: Alright, lads? So what's this accessibility thing all about then? Something about pizzas? Love a pizza, me. But no pineapples, haha <strong>TRIGGERED</strong>. But seriously, it sounds like I might be illegal or something. I don't want to get fined and lose my second car. What's the deal?</p> <p>PATIENT ACCESSIBILITY ADVOCATE: Hi there. Accessibility is one of the fundamental—</p> <p>DEVELOPER: Fucking hell, love, <strong>speak English much??</strong> This sounds complicated as fuck, <strong>Jesus</strong>. I'm only one man, I can't do it all, much as I'd like to.</p> <p>PATIENT ACCESSIBILITY ADVOCATE: Well, erm, no. It's really fairly rudimentary, if you just—</p> <p>DEVELOPER: <strong>TAGS! FUCKING TAGS EVERYWHERE!</strong> Fucking mess, it is, with all these tags.</p> <p>PATIENT ACCESSIBILITY ADVOCATE: Wait, you mean HTML tags?</p> <p>DEVELOPER: There were all these tags, right, and then HTML5 comes along. <strong>Jesus fuck</strong>. And then there were like… <strong>16 MORE FUCKIN TAGS</strong>. I can't remember all that shit. Bad design it is, HTML. Can't be helped. Would love to, but can't.</p> <p>PATIENT ACCESSIBILITY ADVOCATE #2: Hang on. I'm sure if you can learn things like asynchronous programming and the JavaScript event loop, you can easily manage to—</p> <p>DEVELOPER: <em>SIGH</em> Tried, I really did. Gave it my best, but these standards people, these jokers and their tags. Makes it impossible for people like me who'd really really love to just make a <strong>GOD DANG accessible website</strong> once in a while, you know?</p> <p>PATIENT ACCESSIBILITY ADVOCATE: But, wait, a minute ago you didn't seem to know what accessibility even is? In any case, the Domino's case sets a legal precedent whereby—</p> <p>DEVELOPER: <strong>LAWS.</strong> Do we even need them? <strong>Fucked if I know.</strong> Take away the laws, and what do you get? Freedom, <em>that's what</em>. Give me the <strong>FREEDOM</strong> to make my websites accessible, that's what I say.</p> <p>PATIENT ACCESSIBILITY ADVOCATE #2: You already have the freedom to—</p> <p>DEVELOPER: Make all my websites just with <code>&lt;div&gt;</code>s. That's what I'll do. That'll teach the standards bastards to make me not make my websites accessible. Tough love, someone's gotta do it.</p> <p>ME: First of all, that doesn't make sense. Secondly, you're being an asshole. Just take the time to—</p> <p>DEVELOPER: <strong>GAH!!!! ARRGGHHHHH!!!! NO!! NONONONO!!! PLEASE NO!!! STOP!!!!</strong></p> <p>PATIENT ACCESSIBILITY ADVOCATE: What's happening?</p> <p>ME: I'm not sure.</p> <p>DEVELOPER: That word. That word you used on me. <strong>That &quot;a&quot; word</strong>. I… I've never… never in my life have I…oh God</p> <p>ME: You can't be seri—</p> <p>DEVELOPER: I was just asking questions, that's all, <em>sob</em>. And you just… <strong>went for me</strong>. Like I was <em>nothing</em> to you. Can't you see I'm just a poor wee baby, with pink marshmallows for limbs, and a candy floss heart? Just asking questions, I was. <em>Just asking</em>.</p> <p>SYCOPHANT #1: <strong>GOOD LORD, HEYDON</strong> what have you <em>done</em>? <strong>He's dying</strong>. You monster, you coward, you husk-of-a-man.</p> <p>SYCOPHANT #2: And Heydon has <strong>&quot;INCLUSIVE DESIGNER&quot;</strong> written right there in his bio. And that wasn't inclusive behavior at all! <strong>THE IRONY.</strong></p> <p>SYCOPHANT #1: Yes, quite, <em>the irony</em>.</p> <p>SYCOPHANT #14: The irony.</p> <p>SYCOPHANT #187: The irony.</p> <p>SYCOPHANT #432: The irony.</p> <p>SYCOPHANT #43451: Sorry I'm late, I was having a wank. The irony.</p> <p>SYCOPHANT #199: The irony.</p> <p>ME: OK, I get that you felt I was being a bit insulting. In any case, accessibility is a civil right and—</p> <p>DEVELOPER: <strong>A BIT INSULTING??</strong></p> <p>SYCOPHANT #432: <strong>YEAH A BIT INSULTING?? (please notice me)</strong></p> <p>DEVELOPER: You <strong>deliberately</strong> (and with <strong>deliberation</strong>, don't forget) <strong>FIRED</strong> that word, that <strong>seed of evil</strong>, into my ear. You, and by extension everyone who has ever worked in web accessibility, is a foul demon sent to torment me, probably. Let's go with that for now, I might back-pedal a bit later.</p> <p>ME: Wait, just because I used a bit of strong language doesn't mean everyone is—</p> <p>SYCOPHANT #14: These accessibility people are always <strong>hating on us</strong> and using <strong>no-no words</strong>! And they think they're the good guys! <strong>You couldn't make it up!</strong></p> <p>SYCOPHANT #432: The irony.</p> <p>SYCOPHANT #199: Indeed, the irony.</p> <p>SYCOPHANT #1647: Irn Bru.</p> <p>SYCOPHANT #7384: Shut up, Kyle.</p> <p>SYCOPHANT #111: The irony.</p> <p>SYCOPHANT #76: The irony.</p> <p>SYCOPHANT #88: The irony.</p> <p>DEVELOPER: All I <strong>EVER</strong> wanted to do, since I first slid out of my mother and planted my feet into the rich, fertile soil of my homeland, was to make the web (which technically wasn't invented yet) <strong>accessible</strong>, so help me God.</p> <p>ME: …</p> <p>DEVELOPER: But then YOU came along. You and <strong>YOUR WORD</strong>. And now I'm in hospital, on a drip. Do you want to know what's in that drip, Heydon? <strong>Do you?</strong> Go on, ask me. <strong>Ask me what's in the fucking drip, Heydon</strong>. It'll <strong>fuck with your head.</strong></p> <p>ME: Well, IV fluid is usually a dilute saline solution with—</p> <p>DEVELOPER: <strong>IT'S MY TEARS, HEYDON. MY FUCKING TEARS.</strong> How am I supposed to make the web accessible now, Heydon? <strong>How?</strong> While I'm in hospital, <strong>with my own tears getting pumped into my fucking wrist?</strong></p> <p>SYCOPHANT #432: <strong>FUCKING HELL, HEYDON! BY BEING RUDE THIS ONE TIME TO THIS ONE DUDE WHO CLEARLY HAS AN EARNEST AND LONG-HELD DESIRE TO MAKE THE WEB ACCESSIBLE, YOU HAVE FUCKED EVERYTHING UP.</strong></p> <p>SYCOPHANT #111: The web is inaccessible, <strong>and it's all Heydon's fault!</strong></p> <p>SYCOPHANT #88: And he claims he <strong>LIKES</strong> web accessibility. The irony!</p> <p>SYCOPHANT #7116: The irony.</p> <p>SYCOPHANT #6: The irony.</p> <p>SYCOPHANT #1957: Fallacy or something.</p> <p>SYCOPHANT #677: No, I think it's irony this time.</p> <p>SYCOPHANT #8836: The irony.</p> <hr> <p><em>A couple of hours later, in my DMs:</em></p> <p>FOLLOWER ABOUT TO UNFOLLOW ME: Hi Heydon. I just wanted to say: I bought and enjoyed all of your books on web accessibility. They taught me so much. But then you called that one guy a no-no word, and I am forced to conclude that you are a shit demon, sent from shitty hell, and covered in shit and stuff. Also, I think you probably catapult dogs into the sea. Good day, sir.</p> Pseudo-class Deception https://heydonworks.com/article/pseudo-class-deception/ 2011-05-08T00:00:00.000Z https://heydonworks.com/article/pseudo-class-deception/ <p>Those who are new to using <strong>pseudo-classes</strong> in their <abbr title="Cascading Style Sheets">CSS</abbr> may experience more than a little confusion, and I hope that I can relieve a few headaches. For those who use them frequently, I hope they find a few interesting observations ahead.</p> <p>I attribute much of the confusion surrounding pseudo-classes to the misunderstanding of the prefix 'pseudo'. As with <a href="http://en.wikipedia.org/wiki/Pseudoscience">pseudoscience</a>, the prefix does not indicate a partial relationship ('quasi' would be more suitable) but a <em>false</em> one. Why the CSS specification should include items seemingly <strong>designed to confound the user</strong> is anyone's guess but, just as pseudoscience should never be likened to real science, pseudo-classes have <strong>nothing in common with classes</strong>.</p> <h2>Classes and pseudo-classes</h2> <p>As the name suggests, classes are a way to group elements (to <em>classify them</em>) together. Users create their own classes (and use their own <a href="http://en.wikipedia.org/wiki/Naming_convention_%28programming%29">naming conventions</a>) to organise the styling of their elements, before adding them as attributes like so: <pre> <code>&lt;div class="my-block-class"&gt;&lt;/div&gt;</code> </pre> </p><p>Defining the purpose of pseudo-classes is a little more difficult, but it is clear that pseudo-classes do not have the same organisational capacity, especially since coders cannot create or name their own.</p> <p>Essentially, pseudo-classes are a means to access elements in the <abbr title="Document Object Model">DOM</abbr> <em>more specifically</em>. Whether you are using <code>li:last-child</code> to specify only the last item in a list or <code>a:hover</code> to access the 'hover state' of anchors, you enjoy increased granular control of your document's appearance <em>without relying on a classification system</em> or having to edit the markup itself.</p> <p>Furthermore, pseudo-classes do not depend on classes to work. Both of the following uses of <code>:hover</code> are legitimate:</p> <pre> <code>.link-class:hover { color:#ff0; } a:hover { color:#ff0; } </code> </pre> <h2>The :active pseudo-class</h2> <p>Of all the different pseudo-classes available to the coder (many more since <a href="http://www.css3.info/">CSS3</a> has become more widely supported) the <code>:active</code> pseudo-class is perhaps the most perplexing and - unlike its popular stable mate <code>:hover</code> - it is rarely called upon to affect appearance any differently than <strong>browser defaults</strong> dictate.</p> <p>The <code>:active</code> pseudo-class is the last of the pseudo-classes associated with anchors (hyperlinks), preceded by <code>:link</code>, <code>:visited</code> and <code>:hover</code>. You may (as I first did) expect the <code>:active</code> pseudo-class to relate to links with an <strong>href attribute</strong> identical to the current page. That is, you might expect it to help indicate the user's 'active' location. This would indeed be very handy and the misconception is given credence by frameworks such as <a href="http://drupal.org.uk/">Drupal</a> which add an 'active' class (that's right - <em>class</em>, not pseudo-class) to the menu item referring to the page/<abbr title="Uniform Resource Locator">URL</abbr> that you are looking at.</p> <pre> <code>a:visited { /* This tells you where you've been */ } a:active { /* so why doesn't this tell you where you _are_? */ } a.active { /* This could help, though. */ } </code></pre> <p>In reality, the <code>:active</code> pseudo-class <em>activates</em> on links that are currently being pressed. Like <code>:hover</code>, it adds tactility and, therefore, usability to a page's <a href="http://www.smashingmagazine.com/2009/10/13/call-to-action-buttons-examples-and-best-practices/">calls to action</a> and can be thought of as the <em>depressed state</em> of a button. It can indeed be used to enhance a button-like link style.</p> <h2>Away with defaults</h2> <p>The standard in most browsers is to style links in their active state with a dotted outline. Not all designers like this, however, because it marks a box around their links and <strong>not all link designs are box-shaped</strong>. You can easily remove this effect with the following:</p> <pre> <code>a:active { outline:none; } </code></pre> <p>It's not a good idea to forego styling the <strong>active state</strong> altogether, though. Not only does it offer the elusive 'tactility' that we discussed, but it is also important for <strong>accessibility</strong>. You see, <abbr title="Firefox, Safari, Opera">GOOD</abbr> browsers employ another pseudo-class (<code>:focus</code>) to help users traverse the page using the TAB key. The <code>:focus</code> pseudo highlights the link that has been 'tabbed onto' indicating that it can be used (via the ENTER key). Versions of Internet Explorer do not support <code>:focus</code> but <em>misuse</em> <code>:active</code> for the same end result. For this reason, all elements deserving of <code>:focus</code> should also carry <code>:active</code>. <pre> <code>a:focus, a:active, input:focus, input:active { outline:1px solid #999; } </code> </pre> </p><h2>Putting it together</h2> <p>Forgetting <code>:visited</code> for now (which I rarely use), the anchor-related pseudo-classes all describe <strong>states of interaction</strong> and, since they must happen in order, I reckon good anchor styling should be about describing this <em>chain of events</em> as a whole.</p> <p>I have attempted this on <a href="http://www.heydonworks.com/">HeydonWorks</a> by using increasingly pronounced styling from each state to the next, <a href="#">like so</a>. The intention is to show levels of commitment. 'Commitment' isn't necessarily the <em>best</em> metaphor, but it works for me!</p> <pre> <code>a:link { border-bottom:1px dotted; /* A feint line indicates availablility only; zero commitment */ } a:hover { border-bottom:1px dashed; /* Stronger line shows willingness to commit */ } a:active { border-bottom:2px solid; /* Strong, thick line; a commitment between the user and link has been made */ } </code> </pre> Bobby Howitzer https://heydonworks.com/article/bobby-howitzer/ 2011-05-09T00:00:00.000Z https://heydonworks.com/article/bobby-howitzer/ <p>Some time ago, my alter ego 'Bobby Howitzer' made a set of dirty rock 'n' roll mashups entitled <cite>New Rock and Roll is the New Rock and Roll</cite>. The original tunes were repurposed as the backing tracks for Bobby's <strong>high impact kareoke</strong> performances.</p> <figure> <img src="https://heydonworks.com/images/bobby_howitzer_cover.png" alt="Bobby Howitzers New Rock and Roll Is The New Rock And Roll EP"> </figure> <p>The live collision of blues howling, plundered beats and chopped up riffs was popular but the original compositions were never made commercially available &hellip; until now. Via the excellent <a href="http://www.cdbaby.com/cd/bobbyhowitzer">CD baby</a>, you can now <a href="http://www.cdbaby.com/cd/bobbyhowitzer">download</a> the complete <strong>8 track mini-album</strong>; 20 minutes (approx') of action-packed <a href="http://en.wikipedia.org/wiki/Plunderphonics">plunderphonic</a> punk (with the vox samples intact, in case you were wondering).</p> <p><a href="http://www.heydonworks.com/sounds/wrecked.mp3">Wrecked (mp3)</a></p> <p>Included above as a taster is the track 'Wrecked', which you are welcome to download for free. In this example, each of the traditional parts are played by different bands: <strong>Swig</strong> provide the rhythm guitar, <strong>The Riverboat Gamblers</strong> provide the lead part, <strong>The Cramps</strong> provide drums, and <strong>The Flaming Sideburns</strong> contribute the main vocal. These are by no means the only samples (<a href="http://en.wikipedia.org/wiki/Death_metal">death metal</a> band <strong>Entombed</strong>'s vocalist L.G. Petrov sings the "I'm a wreck!" refrain, for a start) but they are the core elements in a sample-based tune that is oddly traditional in its structure, I think. </p> A Minute Of Listening https://heydonworks.com/article/a-minute-of-listening/ 2011-05-11T00:00:00.000Z https://heydonworks.com/article/a-minute-of-listening/ <p>I recently had the privilege of working on a project promoting <strong>listening skills</strong> amongst primary school children, conceived and curated by <a href="http://www.soundandmusic.org/">Sound &amp; Music</a> and called <em>A Minute of Listening</em>. The project required a <strong>desktop application</strong> (to be built by <a href="http://www.neontribe.co.uk/">NeonTribe</a>) that would be run by a teacher, in front of a class, which played a different 'mystery sound' each time it was powered up. A discussion about the sound would ensue, followed by a reveal (on a further screen) about the sound's origin and recordist/composer. Read a full description on the Sound &amp; Music <a href="http://www.soundandmusic.org/projects/minute-listening">website</a> or - better still - take a look at the official <a href="http://vimeo.com/23904357">promo video</a> (I held the <a href="http://en.wikipedia.org/wiki/Boom_operator_%28media%29">boom mic</a> for some of it!).</p> <p>Although I was involved in coding the <strong>interface design</strong> (which required some <em>unusual</em> CSS and javascript hacks which I may discuss in another post) it is my work on the artwork and the <strong>overall aesthetic</strong> of the application that'd I'd like to talk about here.</p> <p>To begin with, I chose to avoid colour because I was concerned it would prejudice the way the sounds were heard. However, this led to some pretty <em>dry</em> initial designs. As the project progressed, we decided that the actual <em>listening</em> part of the classroom ritual would be fulfilled with the children's eyes closed and I set about making a bold design incorporating <strong>flourescent colours</strong> and thick, uneven black lines - like the sort made by a <strong>marker pen</strong>. This resulted in the winning design and the following logo, made with the fantastic <a href="http://www.fontsquirrel.com/fonts/Folk">Folk</a> font:</p> <img src="https://heydonworks.com/images/amol_logo.gif" alt="A Minute of Listening logo"> <p>I had the most fun creating the following <strong>instructive messages</strong>. These appear in order once the teacher has pressed the <strong>big play button</strong> and are intended to settle and prepare the class for the exercise. It should be noted that I originally 'forgot' to include the sitting character's ears (<em>stylised them into nonexistence</em>, to be more exact) which was a <strong>pretty stupid error</strong> given the subject matter. I think I overcompensated by making the ears unnaturally large in the final iteration...</p> <img src="https://heydonworks.com/images/aminuteoflistening_prep.gif" alt="A Minute Of Listening Preparation"> Dilapidated https://heydonworks.com/article/dilapidated/ 2011-05-11T00:00:00.000Z https://heydonworks.com/article/dilapidated/ <p>For this experiment, I put my <strong>resonator</strong> through <a href="http://line6.com/toneportux2/guitar.html">Gearbox</a>'s extraordinary 'Bronze Master' effect and bathed the resulting signal in expansive reverb.</p> <p>Due to the Bronze Master's perculiar ability to help you create <strong>unusual harmonics</strong> and the resonator's sensitivity to <strong>soft plucking</strong>, a broad range of murky, eroded sounds can be achieved. At low velocities the sound is <strong>distant and muffled</strong>; at high velocities it's lively and sharp.</p> <p><a href="http://www.heydonworks.com/sounds/dilapidated.mp3">Dilapidated (mp3)</a></p> <p>Notes tend to crackle and disintegrate prematurely, adding some atonal texture. Having opted for a mournful <a href="http://en.wikipedia.org/wiki/Chord_progression">chord progression</a> - cycled extremely slowly - I think the overall effect is reminiscent of an instrumental to be found on a (somewhat progressive) <a href="http://en.wikipedia.org/wiki/Black_metal">black metal</a> record. Enjoy!</p> <p><strong>Note:</strong> The track is nearly <em>seven minutes</em> long so you may have to wait some time for it to load, depending on your connection speed.</p> Using The Cascade https://heydonworks.com/article/using-the-cascade/ 2011-05-13T00:00:00.000Z https://heydonworks.com/article/using-the-cascade/ <p>In this post, I am going to explain the benefit of exploiting the 'cascading' part of <acronym title="Cascading Style Sheets">CSS</acronym> to solve everyday styling problems more efficiently and effectively. The example problem I have chosen is that of <strong>clearing content after floats</strong>. For those not familiar with the problem that necessitates clearing, it effects elements that appear directly after floated elements in the markup. These elements are pulled up the page to rest <em>behind</em> the floated element(s), obscuring their content and generally making a mess of the page.</p> <p>The problem is easily solved by applying the <code>clear:both</code> declaration to the obscured element. This <strong>forces the element down the page</strong> so that it appears below (not behind) the content preceeding it:</p> <pre> <code>.get-down-damn-you { clear:both; } </code></pre> <p>However, a problem occurs when your layouts begin to evolve and new content is created or elements are moved around: You have to keep checking that the right elements have <code>clear:both</code> applied. Worse still, a content manager not familiar with the problem might replace the content under a float with different content which lacks the <code>get-down-damn-you</code> class and panic because they have <strong>no idea why the page has gone awry</strong>.</p> <h2>A solution</h2> <p>You could make use of the 'cascade' (read: Cascading Style Sheets) and declare <em>all</em> relevant elements to carry the <code>clear:both</code> property as a default. For example:</p> <pre> <code>div { clear:both; } </code></pre> <p> This is a safe provision since <code>clear:both</code> does not have any noticeable effect on elements in regular circumstances. In fact, the only elements it <em>adversely</em> affects are the floated elements themselves. Not to worry, we can use <code>clear:none</code> to override this &hellip; </p> <pre> <code>#floated-thing { float:left; clear:none; } </code></pre> <h2>Conclusion</h2> <p>By making use of '<strong>the cascade</strong>' we can place ourselves in a position where we only have to <strong>address the exceptions</strong> and, since we have to write out the <acronym title="Cascading Style Sheets">CSS</acronym> for each of our floated elements anyway, what's the bother with throwing in just one more property?</p> <p>Using <a href="http://lesscss.org/">less.js</a> we could take our forward planning one step further. First we would make two classes - one for a left float and one for a right float:</p> <pre> <code>.floated-left { float:left; clear:none; } <p>.floated-right { float:right; clear:none; } </p></code></pre><p></p> <p>When we define our new element's styles, we can use a '<a href="http://lesscss.org/#-mixins">mixin</a>' to include the properties from one of our classes in one line of <acronym title="Cascading Style Sheets">CSS</acronym>:</p> <pre> <code>.white-on-black { width:200px; background-color:#000; color:#fff; .floated-left; /* the 'mixin' */ } </code></pre> <p>Now that we have binded our 'float' and 'clear' properties together, we no longer need to remember that one requires the other.</p> London Book Fair https://heydonworks.com/article/london-book-fair/ 2011-05-14T00:00:00.000Z https://heydonworks.com/article/london-book-fair/ <p>Anyone who knows me knows that I'm fascinated by <strong>sea life</strong> - especially <strong>crabs</strong>. I keep two pet hermit crabs called <em>Ian</em> and <em>Phillip</em> and I have written and designed a picture book called <em>Crabs Are Odd</em>. You've probably seen the little ad spot for it floating around on HeydonWorks but there's more information &mdash; and a showcase of some of the different crab species featured in the book &mdash; on the <a href="http://www.crabsareodd.com/">dedicated site</a>.</p> <p>Although I've self-published it, I thought it might be interesting to go to the <a href="http://www.londonbookfair.co.uk/">London Book Fair</a> and talk to representatives of the larger publishing and distribution firms. Since the majority of delegates at the London Book Fair are there in a <a href="http://en.wikipedia.org/wiki/Business-to-business">business to business</a> role, I didn't feel there would be much to gain from approaching them as an author with a new title, so I went with a second, backup agenda: Try to get as many people as possible to <strong>pose in photographs</strong> clutching a <strong>large, pink hermit crab</strong>. I include a few of the better photo's here &hellip;</p> <img src="https://heydonworks.com/images/book_fair_crab_bw.jpg" alt="Crab at the London Book Fair 2011" title="book_fair_crab_bw" width="630" height="200" class="alignnone size-full wp-image-168"> <p>Thanks to everyone for being such good sports and for all the helpful advice I was offered. <em>Crabs are Odd</em> is available from <a href="http://www.lulu.com/product/paperback/crabs-are-odd/14255166">lulu.com</a> in a 19cm x 19cm perfect bound format.</p> Can't Touch Me https://heydonworks.com/article/can't-touch-me/ 2011-05-30T00:00:00.000Z https://heydonworks.com/article/can't-touch-me/ <p>Not to be confused with <em>U Can't Touch This</em> by <a href="http://en.wikipedia.org/wiki/MC_Hammer_discography">MC Hammer</a>, this is a grinding piece of punk blues co-created - through correspondence - with my good friend <a href="http://www.mickeyfordola.co.uk/">Mickey Fordola</a> for a project (currently on hiatus) called <strong>The Hemotions</strong>.</p> <p>The techy stuff: The backing track features my <a href="http://www.gordonsmithguitars.com/about.php">Gordon-Smith</a> SG, drop-tuned to C, in the right channel and my battered 'Encore' Fender style bass in the left. Despite costing somewhere in the region of £150 <em>new</em>, I've never used another bass that makes such a <strong>satisfying sound</strong>; partly due to the strong signal not produced by daintier, more expensive instruments. The <strong>horn section</strong> is culled from a sample library with added gain and some <strong>cheap reverb</strong> to make it sound less clinical and sit better over the guitars. I can't remember where the drum sounds came from but I manually added a bunch of hits into <a href="http://www.native-instruments.com/#/en/products/producer/battery-3/">Battery</a>.</p> <a href="http://www.heydonworks.com/sounds/cant_touch_me.mp3">Can't Touch Me (mp3)</a> <p>More often to be found <strong>charismatically crooning</strong> as a wedding singer, Mickey proves his versatility with a thin, slightly pained vocal that is a perfect foil to the heavy, churning guitars (and a marked contrast to my slightly <a href="http://www.urbandictionary.com/define.php?term=Waitsian">Waitsian</a> <em>gurgling</em> in the chorus). To hear Mickey in Rat Pack mode or to book him for a wedding, take a look at his <a href="http://www.mickeyfordola.co.uk/">website</a>...</p> Display: None Issues https://heydonworks.com/article/display:-none-issues/ 2011-06-06T00:00:00.000Z https://heydonworks.com/article/display:-none-issues/ <p>The <code>display:none</code> property is common and has may uses, as well as misuses. It's not always obvious what effect its use has on <abbr title="Search Engine Optimisation">SEO</abbr> and its impact on <a href="http://en.wikipedia.org/wiki/Web_accessibility">accessibility</a> can be problematic. I hope this post helps to clarify the situation.</p> <h2>Types of invisibility</h2> <p><strong>'Display none'</strong> means exactly that. It removes the element (and its child elements) from the display. Unlike <code>visibility:hidden</code>, which makes elements invisible but maintains their <em>shape</em> in the layout (much like setting their opacity to zero), <code>display:none</code> leaves no trace at all. Bearing this in mind, it's tempting to use <code>display:none</code> as a <strong>substitute for actually removing elements</strong> from the markup. The question is this: what is the hidden content getting up to behind my back?</p> <h2>SEO concerns</h2> <p>Very few people understand precisely how <a href="http://en.wikipedia.org/wiki/Web_crawler">search bots</a> work or what algorithms to which they are conforming. If someone tells you they are party to that information, there's a good chance they are a charlatan. This being the case, we must rely on our own <em>common sense</em> when it comes to constructing and styling our content. So, in the case of <code>display:none</code>, what should we suppose? My best guess is this:</p> <p>Given that Google's <strong>bots</strong> are surely designed to retrieve content as accurately as possible, and given that <code>display:none</code> is commonly used as part of javascript-enhanced navigation schema, surely the bot cannot afford to ignore content set (on page load) to <code>display:none</code>. This would mean it was foregoing content that the user can access with the simple click of a tab, for example. Remember: the poor bots are just trying to find the same stuff that the humans are after. That said, you could say there is <strong>no 'display none issue'</strong> regarding <abbr title="Search Engine Optimisation">SEO</abbr>.</p> <p>However, if you are not persuaded by this argument, one safety measure would be to set 'display:none' on the content that requires it <em>via javascript</em> so that the <code>display:none</code> property only takes effect in the generated markup (the markup after javascript has run in the browser) because google's bots pay this manipulated content <a href="http://www.google.com/support/customsearch/bin/answer.py?answer=72366">little attention</a>. This practise is arguably rather drastic since most believe that Google will ignore your <abbr title="Cascading Style Sheets">CSS</abbr> file (where you would otherwise write your <code>display:none</code> code) anyway. Regardless, the code to do it simply in <a href="http://jquery.com/">jQuery</a> would be as follows:</p> <pre> <code>$(document).ready(function() { $('.thing-to-hide').hide(); }); // which is equivalent to... $(document).ready(function() { $('.thing-to-hide').css('display', 'none'); }); </code></pre> <h2>Accessibility and hidden content</h2> <p>A good search bot, like a good archiver, will attempt to store <strong>all the information</strong> available in a document or documents. A screen reader's task is quite different. It is designed to emulate the experience of traversing a document <em>visually</em>. As Wikipedia puts it:</p> <blockquote><p>A screen reader is a software application that attempts to identify and interpret what is being displayed on the screen</p> <footer> <cite><a href="http://en.wikipedia.org/wiki/Screen_reader">Wikipedia</a></cite> </footer> </blockquote> <p>In order to achieve this end, most screen readers will 'step over' content that they are aware has been hidden from view. This is sound logic; if the average sighted viewer can't see it then surely it is <strong>not intended for viewing</strong>. As I noted, not <em>all</em> screen readers conform to this convention. Well, not all browsers conform to the same standards, but we know which ones are right and which are wrong, don't we? Ignoring content that has been set to <code>display:none</code> is a standard amongst screen readers so - except in special circumstances - we should cater for the majority and only use <code>display:none</code> on content we do not need <strong>visually impaired users</strong> to read.</p> <h2>Conclusion</h2> <p>To summarise, 'don't worry'. Unless you are doing something counterintuitive, you should not expect to encounter a <strong><code>display:none</code> issue</strong>. This is unless you are the sort of 'webmaster' who likes to use <a href="http://en.wikipedia.org/wiki/White_or_black_hat">black hat SEO</a> practices and stuff lots of hidden keywords into your antiquated web pages. Even then, it will be the <em>repetition of content</em> that gets you penalised - not the <code>display:none</code> declaration used to hide it.</p> <p>Perhaps the only scenario where the use of <code>display:none</code> becomes seriously contentious relates to <strong>text replacement</strong> and I shall write my <a href="http://www.heydonworks.com/accessible-text-replacement">next coding post</a> on this subject.</p> Sickly Headache https://heydonworks.com/article/sickly-headache/ 2011-07-01T00:00:00.000Z https://heydonworks.com/article/sickly-headache/ <p>It occurs to me that some people looking for information on an ailment using the search term <strong>Sickly Headache</strong> might chance upon this <a href="http://www.heydonworks.com/category/music">music</a> post. If you are one of these people, I recommend you <strong>DO NOT</strong> play the post's associated <strong>audio track</strong>. The title of the post (and track) refers to the woozy, <strong>uneasy</strong> sensation that the music evokes, making it somewhat difficult listening even for those who <em>are not</em> currently suffering from a migraine or the like.</p> <p>Before you listen, make sure the volume of your audio is set at a normal level. <strong>Do not adjust</strong>: The track is supposed to start barely audibly.</p> <a href="http://www.heydonworks.com/sounds/sickly_headache.mp3">Sickly Headache (mp3)</a> <p>The piece is created with just one <a href="http://www.soundonsound.com/sos/dec00/articles/vst.asp">VST instrument</a> - the Minimogue - which is a software emulation of the classic 1970 '<a href="http://en.wikipedia.org/wiki/Minimoog">Minimoog</a>' analogue synthesiser. I sculpted the queasy sound from a basic preset before applying it to a very simple, <strong>repeated pattern</strong>. Whilst this pattern is played out, I gently <strong>raise the velocity curve</strong> so that the track slowly increases in intensity over its several-minute duration. At certain points, the bass notes sort of <em>retrigger</em> for some reason and I like the corrective, plunging glissando that this creates.</p> <p>I'm a great admirer of the composer <a href="http://www.schott-music.com/shop/persons/featured/14696/index.html">Penderecki</a> and I think the gathering dissonance is somewhat reminiscent of his string sections (in a cheap sort of way). I've already likened the sound to a <strong>sickly headache</strong>; one of those migraine-like headaches you get which make you feel like throwing up. Perhaps you think it's evokative of something totally different?</p> <p style="text-indent:0;"><strong>Note:</strong> Due to the length of the track, I've <em>slightly</em> reduced the sound quality so that it loads a little faster on slow connections.</p> Accessible Text Replacement https://heydonworks.com/article/accessible-text-replacement/ 2011-07-11T00:00:00.000Z https://heydonworks.com/article/accessible-text-replacement/ <p>Following <a href="http://www.heydonworks.com/article/displaynone-issues">my post</a> regarding the <abbr title="Search Engine Optimisation">SEO</abbr> and accessibility issues invoked when using <code>display:none</code>, I am now going to address the <strong>text replacement</strong> scenario, since I believe this is the only situation where one would legitimately want to hide text from the unassisted visitor (reading <em>visually</em>) but not from a screen reader or search bot.</p> <p>I am aware that this issue has been discussed at length elsewhere (see <a href="http://www.456bereastreet.com/archive/200712/choose_an_accessible_image_replacement_method/">Mr. Johansson's article</a> and related posts) but I wanted to focus particularly on <strong>text replacement</strong> in titles (<code>h1</code>, <code>h2</code> etc.) and to offer advice on maintaining <a href="http://en.wikipedia.org/wiki/Semantic_HTML">semantic</a> <abbr title="Hypertext Markup Language">HTML</abbr> and <em>responsiveness</em> to layout. I am also aware that, after the dawn of the <a href="http://www.google.com/webfonts">web font</a> (and with the help of some <code>text-shadow</code> or other such CSS3 enhancements), you have the option of achieving a variety of attractive typographic effects that do not require images and are <em>implicity</em> accessible methods.</p> <h2>What is text replacement?</h2> <p>Text replacement is the substitution of 'real text' for a <strong>visual approximation</strong> of it. By 'real text', I mean text that appears in the markup as a 'text node' within an element &hellip;</p> <pre> <code>&lt;h1&gt;I am an important text node&lt;/h1&gt;</code> </pre> <p>...and by 'visual approximation', I mean an image that <strong>visually emulates the characters</strong> that make up the intended word or phrase.</p> <p>Since screen readers and search engine bots have trouble interpreting the intended <a href="http://dictionary.reference.com/browse/lexical">lexical</a> content of images, it is considered wise to also provide some 'real' text in order to satisfy the requirements of these technologies. This is particularly important regarding headings because they carry so much <strong>semantic weight</strong>. We would like to hide this additional text from the display because the typical user would otherwise see the same wording twice. The question is: <em>how</em>?</p> <p>I shall now present different text replacement methods compared against their output in the <a href="https://addons.mozilla.org/en-US/firefox/addon/fangs-screen-reader-emulator/">Fangs</a> screen reader emulator for Firefox. I have tried to order these methods from 'awful' to 'better'.</p> <h3>Method 1: A span set to <code>display:none</code></h3> <pre> <code>&lt;h2&gt; &lt;img src="heading_text.jpg" /&gt; &lt;span style="display:none"&gt;Heading Text&lt;/span&gt; &lt;/h2&gt; &lt;p&gt;The paragraph starts here...&lt;/p&gt;</code> </pre> <figure> <img src="https://heydonworks.com/images/method1.gif" alt="Heading level two, The paragraph starts here..."> <figcaption>Fangs screenshot</figcaption> </figure> <p><strong>Verdict:</strong> As my <a href="http://www.heydonworks.com/displaynone-issues">previous post</a> states, screen readers will usually ignore content that has been styled with <code>display:none</code> because their job is to emulate the experience of reading visually and one cannot read what one cannot see. The <a href="https://addons.mozilla.org/en-US/firefox/addon/fangs-screen-reader-emulator/">Fangs</a> output foregoes the heading text so this method is <em>absolutely useless</em>.</p> <h3>Method 2: The 'alt' attribute</h3> <pre> <code>&lt;h2&gt; &lt;img src="heading_text.jpg" alt="Heading Text" /&gt; &lt;/h2&gt; &lt;p&gt;The paragraph starts here...&lt;/p&gt;</code> </pre> <figure> <img src="https://heydonworks.com/images/method2.gif" alt="Heading level two, Graphic: Heading Text, The paragraph starts here..."> <figcaption>Fangs screenshot</figcaption> </figure> <p><strong>Verdict:</strong> The heading text is clearly present via the <strong>alt attribute</strong> but is preceded by the 'graphic' flag. We don't want users who <em>see</em> the image to apprehend it as one so we certainly don't want this secret read aloud to the visually impaired. Text in a heading derived from an alt attribute is inadequate and <strong>semantically incorrect</strong>. As the Firefox Accessibility Extension warns:</p> <blockquote> <p>"Each subheading (h2 &hellip; h6) should have text content exclusive of the alt text of any img element it contains"</p> <footer>Firefox Accessibility Extension</footer> </blockquote> <h3>Method 3: The span which has no height</h3> <pre> <code>&lt;h2&gt; &lt;img src="heading_text.jpg" /&gt; &lt;span style="display:block; height:0; overflow:hidden"&gt;Heading Text&lt;/span&gt; &lt;/h2&gt; &lt;p&gt;The paragraph starts here...&lt;/p&gt;</code> </pre> <figure> <img src="https://heydonworks.com/images/method3.gif" alt="Heading level two, Heading Text, The paragraph starts here..."> <figcaption>Fangs screenshot</figcaption> </figure> <p><strong>Verdict:</strong> The empty alt attribute suppresses <strong>validation errors</strong> as well as removing the 'graphic' flag. At the same time, the <em>esoteric</em> method for hiding the span element is undetected by the Fangs emulator and the heading text is present. Unlike the image's alt attribute, the span is a legitimate child of the heading and, because it is semantically <em>inert</em>, there is no cause for it to be flagged by the reader.</p> <h3>Method 4: The Phark Method Without CSS images</h3> <pre> <code>&lt;h2 style="text-indent:-99999px"&gt; Heading Text &lt;img src="heading_text.jpg" alt="" /&gt; &lt;/h2&gt; &lt;p&gt;The paragraph starts here...&lt;p&gt;</code> </pre> <figure> <img src="https://heydonworks.com/images/method3.gif" alt="Heading level two, Heading Text, The paragraph starts here..."> <figcaption>Fangs screenshot</figcaption> </figure> <p><strong>Verdict:</strong> Identical to the Fangs output of Method 3 but dispenses with the extraneous span. This method differs from <em>typical</em> implementations of the <strong>Phark Method</strong> (mentioned in <a href="http://css-tricks.com/630-css-image-replacement/">this</a> excellent round-up) in that it does not rely on a <strong>background image</strong>. Although removing the image tag makes for simpler markup, using a background image makes <a href="http://www.netmagazine.com/features/responsive-web-design">responsive design</a> more difficult:</p> <p>Whilst real text will wrap at smaller screen sizes and images can be set to <code>width:100%</code> (allowing them to scale according their parent element's width), background images are simply not malleable, necessitating headings with fixed, pixel-based dimensions to accomodate the image. This caveat applies to the <a href="#">Leahy and Langridge</a> method too.</p> <p>It might be possible to create <a href="http://www.alistapart.com/articles/sprites">CSS sprites</a> containing versions of the heading at different sizes and change the <code>background-position</code> according to media queries. I did this once, then the client changed their mind about the wording &hellip;</p> <p><strong>Update:</strong> The Phark Method works by drawing a giant box to the left of the content's origin. This is said to be detrimental to performance. For this reason, you could deem Method 3 preferable.</p> <h2>CSS on, images off</h2> <p>I have not mentioned the thorny issue of browsing with CSS on but images off and the 'Phark without CSS images' method certainly fails to display the heading text in this scenario. Whilst this is a <strong>bandwidth</strong> before it's an <strong>accessibility</strong> concern, it <em>is</em> possible to fix it.</p> <p>One can use javascript to detect whether the context allows images or not and only apply the <code>text-indent</code> if images are present, making it applicable. <a href="http://v3.thewatchmakerproject.com/journal/53/images-offcss-on-image-replacement">This article</a> offers just such a solution. It is rather old and you should be wary of the '<code>document.write</code>', but it doesn't require the jQuery library which saves us a hefty <a href="http://djce.org.uk/dumprequest">http response</a>. If your connection is likely to struggle with images, it will have a hard time loading large javascript libraries as well.</p> Centennial By Agonyst https://heydonworks.com/article/centennial-by-agonyst/ 2011-07-11T00:00:00.000Z https://heydonworks.com/article/centennial-by-agonyst/ <p><a href="http://en.wikipedia.org/wiki/Death_metal">Death</a> and <a href="http://en.wikipedia.org/wiki/Extreme_metal">Extreme Metal</a> musicians account for a large proportion of the most accomplished, technically skilled musicians in the world. Although the music <em>is</em> typically dense, fast and <strong>heavily distorted</strong>, it is also precise and carefully arranged. The accusations (made in ignorance) that it is a musically <strong>meritless cacophany</strong> would be more accurately levelled at some of the indulgent excesses of <a href="http://en.wikipedia.org/wiki/Hardcore_punk">hardcore punk</a>, garage rock or a myriad of luridly asinine types of dance music. The real problem with death metal (and there is a problem with a lot of these bands, I think) is contrary to conventional wisdom: It is often <em>too</em> formalist; <em>too</em> restrained; <em>too</em> conservative.</p> <p><a href="http://www.facebook.com/Agonyst">Agonyst</a> are an unusual proposition because you get the best of both worlds. On the one hand, they satisfy the aficionado's desire for <strong>complex arrangements</strong> and challenging time signatures. They also showcase <strong>lead parts</strong> and <strong>drum patterns</strong> which - by themselves - are bound to earn them respect and admiration among the proportionately high number of <strong>Death Metal</strong> fans who are musicians in their own right.</p> <p>On the other hand - and this is where they differ from all but a very few - there's genuine <em>fun</em> to be had. The songwriting is not merely rigorous but <strong>impishly inventive</strong>. The lyrics aren't po-faced but filled with <strong>sardonic wit</strong>. Death Metal production is often too polished and even but theirs is dynamic, <strong>live-sounding</strong> and raw. Even the artwork is playfully unusual.</p> <figure> <img src="https://heydonworks.com/images/centennial.jpg" alt="Centennial by Agonyst" title="Centennial"> <figcaption><a href="http://agonyst.bigcartel.com/product/centennial">Centennial LP</a></figcaption> </figure> <p>The qualitative difference is clearest in the live context. In person, the average aspiring death metal act is all too often petulant and nerdy, unable to communicate with the crowd and <strong>unwilling to extrapolate</strong> the recorded versions of their output. The live set of an inferior act is predictable and workmanlike to the point of being <em>pandering</em>; an approach that - paradoxically - leaves you feeling short-changed.</p> <p>Then there's Agonyst: I've seen them arrive on stage to the theme from <a href="https://www.youtube.com/watch?v=gyZDZCGQJf8">Curb Your Enthusiasm</a>, perform covered from head to toe in shaving foam, engage in nonconsensual frottaging with a male promoter, inject silences with perculiar jingles, <a href="https://heydonworks.com/">defame 'Frederick Mercury from Queen'</a>, hum in unison, have their hair cut mid-song (no really), proclaim themselves "<strong>the gayest death metal band in the universe</strong>", screw the odd bit up with enough charisma to see them through, and enjoy themselves.</p> <p>If you want to hear a good (and original) Death Metal album, buy Agonyst's <a href="http://agonyst.bigcartel.com/category/cds">Centennial</a>. If you want to see a good <em>rock and roll</em> band, then go and watch them play. I should declare at this point that I have known these guys for a long time, making me a less than disinterested party. However, our friendships have always been fostered by a mutual interest in good music and in playing it. If they had ever, in the ten years or more that I've known them, created anything vaguely half-baked, I would have disowned them by now. The awkwardness would have been too much to bear.</p> <p>You can hear <a href="http://www.facebook.com/Agonyst?sk=app_4949752878">example tracks from the album</a> for yourself on their facebook <a href="http://www.facebook.com/Agonyst?sk=wall">fan page</a>. <strong>Centennial</strong> is on <a href="http://itunes.apple.com/gb/album/centennial/id417987464">iTunes</a> and the CD version - as well as Callum Weaver's hilarious T-shirt design - is also available for <a href="http://agonyst.bigcartel.com/product/centennial">purchase</a>.</p> An Open Data Logo https://heydonworks.com/article/an-open-data-logo/ 2011-07-23T00:00:00.000Z https://heydonworks.com/article/an-open-data-logo/ <p>I was recently asked to design a <strong>logo</strong> for the <strong>Open Data Cookbook</strong>; a marvellous organisation commited to helping us make use of all the <strong>open data</strong> (partcularly government data) that has become available. Their <a href="http://www.opendatacookbook.net/wiki/">excellent wiki</a> provides 'recipes' for sourcing, preparing, fusing and visualising data and is really worth a look.</p> <p>In the interest (and on the <em>theme</em>) of openness - I thought I'd describe the design process that led to the logo itself. Since the remainder of this article will address <strong>graphic design</strong> and <strong>typography</strong>, there may be little of interest for data wranglers and/or evangelists. If you are one of these people, I would quite understand if you wanted to work on your <a href="http://www.opendatacookbook.net/wiki/creating_a_recipe">recipes</a> instead.</p> <figure> <img src="https://heydonworks.com/images/open_data_cookbook.png" alt="Open Data Cookbook"> <figcaption>The finished logo</figcaption> </figure> <p>Marrying the concepts of 'data' and 'cooking' seemed fun - and fairly straightforward - at first, but logo design is more about avoiding negative connotations than confirming positive ones. Unwisely, my first iteration involved <strong>knives</strong>. It's always risky to put knives in a logo (even for a <em>butcher</em>) but I was keen on the idea of 'incisiveness'.</p> <blockquote> <p style="text-align:center">knives&hellip; incisions&hellip; incisiveness&hellip; clarity&hellip; clarity of data</p> </blockquote> <p>So went the train of thought. Also, I thought I could line up differently sized knives like bars in a bar chart. However, the violence that a knife can't help but signify &mdash; as well as many more complex negative notions such as the <strong>tyrannical chef</strong> &mdash; make it unweildy at best.</p> <p>My second (and last) iteration derived from the simple fortune that the shape of a <a href="http://en.wikipedia.org/wiki/Pie_chart">pie chart</a> and the shape of a frying pan are similarly <em>round</em>. Disregarding the typography, the logo is essentially a pie chart with a pan handle. The flesh-coloured 'sector' is supposed to represent the pertinent data (the <em>meaty</em> part) that might be interesting to scrutinise.</p> <p>Meat, pies etc. to one side, I think it is the <a href="http://en.wikipedia.org/wiki/Typeface">typeface</a> that really makes the design work. The font is called '<strong>Lobster</strong>' and it is available - suitably - in the <strong>Open Type Format</strong>. Not only does it boast <em>seventy nine</em> <a href="http://en.wikipedia.org/wiki/Typographic_ligature">ligatures</a> (making it one of the most convincing 'script' fonts available) but it is one of the best <em>named</em> fonts, having the perculiar ability to evoke the typography you might expect on a <strong>friendly seafood restaurant's menu</strong>. That is not to say that the font isn't versatile; it would be my first choice for retro <strong>poster designs</strong> for a start.</p> <p>The foundry (headed by Paulo Impallari) has a <a href="http://www.impallari.com/lobster/">web page</a> dedicated to the font and it is also available as an <a href="http://sixrevisions.com/css/font-face-guide/">@font-face</a> kit from <a href="https://heydonworks.com/">Font Squirrel</a>. The Impallari page is superior because it has a picture of a man in a lobster suit. I hope the foundry doesn't mind me reproducing this image below:</p> <p>[removed]</p> Using Icon Web Fonts https://heydonworks.com/article/using-icon-web-fonts/ 2011-09-06T00:00:00.000Z https://heydonworks.com/article/using-icon-web-fonts/ <p><strong>Update:</strong> Since writing this post, I was finally able to create a web font to my liking. You can read about it and download it in <a href="http://www.heydonworks.com/article/a-free-icon-web-font">this subsequent article</a>.</p> <p>Prefixing (or occasionally suffixing) hyperlinks with little icons can be helpful for qualifying the <em>type</em> of action the link offers the user. A classic example is the deployment of the instantly recognisable (in <em>most</em> of its various permutations) <abbr title="Rich Site Summary">RSS</abbr> icon. At a glance, items bearing this icon are clearly links that will direct the user to either some raw RSS or a <strong>feed subscription</strong> prompt (unless, that is, the site's developer is nefariously trying to exploit this convention).</p> <p>These icons are typically manifested as either a <strong>CSS background image</strong> or an <strong>image tag</strong> inserted before the link element's text node. However, after the advent of broad <code>@font-face</code> support, it is now possible to embed a font that contains the various icons required by your <abbr title="User Interface">UI</abbr>. This approach offers the following advantages:</p> <ul> <li>The 'icon' is inserted and treated as text, making scaling for different zoom levels an implementary non-issue</li> <li>Scaling is not just easy but does not result in the visual degredation expected when using images</li> <li>Recolouring the icon is as trivial as recolouring text. Making your basic RSS-signifying character suitably orange is as simple as applying <code>color:orange</code></li> <li>Does not require the creation and uploading of a large number of images and image sprites or a proliferation of <code>background-position</code> declarations</li> <li>Requires just <em>one</em> http request for the <strong>all-encompassing icon library</strong> that is the font itself</li> </ul> <h2>A problem</h2> <p>The main disadvantage with this technique regards <strong>semantics</strong>. Much has been said about Google's algorithms tending to frown upon bad grammar and spelling these days and a bunch of single, <strong>stray</strong> characters appearing in the markup is likely to invite disdain on the part of the crawling bot. This could have a <strong>negative impact</strong> on the listing of pages belonging to your site.</p> <h2>Icon fonts and semantics</h2> <p>When it comes to affecting semantic <abbr title="Hypertext Markup Language">HTML</abbr>, you either want to have a positive impact on the document or no impact at all. The 'no impact' approach to embedding icons is easy enough and the result is akin to using a background image. The icon is inserted via the <code>:before</code> pseudo-class like so:</p> <pre> <code>a.rss-link:before { content: 'r'; /* the character corresponding with the rss icon */ font-family: 'My Icon Font'; color: orange; }</code> </pre> <p>This is all well and good (and is recommended by the makers of the '<a href="http://pictos.drewwilson.com/">Pictos</a>' icon font) because the <strong>pseudo content</strong> is not present in the document. However, what if we wanted to capitalise on the existence of our 'stray' character? If we had opted to use an image tag as an icon, we could have written 'RSS' in the <strong>title attribute</strong>, exposing a textual alternative to the visual signifier on hover.</p> <p>Using an <strong>icon web font</strong>, perhaps we could wrap the character in an <code>abbr</code> tag. This is semantically superior to using an <code>img</code> because the character and the icon it invokes are equivalent as shorthands (textual and visual shorthands, respectively). As with the <code>img</code>, the associated title attribute affords the user a fuller description of the abbreviated prefix.</p> <pre> <code>&lt;a href="feed.rss" type="application/rss+xml"&gt; &lt;abbr title="RSS"&gt;r&lt;/abbr&gt; Latest news stories &lt;/a&gt;</code> </pre> <h2>An icon web font deficit</h2> <p>Much as I like the '<a href="http://pictos.drewwilson.com/">Pictos</a>' font mentioned earlier, it is a commercial font. I have yet to find any good (or comprehensive) free icon fonts available for embedding and attempts using <a href="http://fontstruct.com/">Fontstruct</a> to create my own variation have so far proven futile. If anyone is aware of a good, <em>free</em> web icon font that includes RSS, social bookmarking and <abbr title="What You See Is What You Get (but not really because of all the empty tags it leaves hidden in the output)">WYSIWYG</abbr> style icons, please leave a comment.</p> <p><strong>Note:</strong> My <code>abbr</code> technique would be better if screen readers supported title attribute vocalization as a default, which many don't.</p> Lowered Expectations https://heydonworks.com/article/lowered-expectations/ 2011-09-13T00:00:00.000Z https://heydonworks.com/article/lowered-expectations/ <p>Benny (<a href="http://twitter.com/rattegg">@rattegg</a>) and I have been rehearsing and recording for our <strong>Wet Face</strong> project for some time now and &mdash; provided that the venue staff don't get cold feet &mdash; our first performance is imminent.</p> <p>Having 'mastered' (for 'mastered' read 'bathed in distortion and given a <strong>perfunctory mid-range spike</strong>') a few tracks in the last week, I thought I'd put one up here. Please feel free to download it, retag it as a <a href="https://www.youtube.com/watch?v=tiSfo9yGMHI">Madonna</a> track and seed it with your favourite <strong>file sharing software</strong>.</p> <h2>Wet Face</h2> <p><strong>Wet Face</strong> are a duo much like <a href="http://en.wikipedia.org/wiki/The_Ting_Tings">The Ting Tings</a>, except entirely dissimilar in both form and content and obnoxious by <em>intent</em> rather than misfortune. Benny plays the drums (backwards, with the snare next to his right knee) and I sing (well, <em>howl</em>) and play guitar.</p> <p>The writing and overall ideology are indebted to <a href="http://en.wikipedia.org/wiki/Punk_blues">punk blues</a> acts such as <strong>The Oblivians</strong> and <strong>Bantam Rooster</strong> (another duo), but the low tuning (<a href="http://en.wikipedia.org/wiki/Dropped_A_tuning">dropped A</a>) and the misanthropic theme are borrowed from <a href="http://en.wikipedia.org/wiki/Sludge_metal">Sludge Metal</a> and Noise Rock bands like <strong>EyeHateGod</strong>, <strong>Unsane</strong> and <strong>Todd</strong>.</p> <h2>Production</h2> <p>Producing a band like <strong>Wet Face</strong> is maddeningly paradoxical: It wants to sound unhinged, unbalanced and unnecessary in <em>just the right way</em>. For the sake of balance, I've tried to make it unhinged, unbalanced and unnecessary in equal measure. In one channel is a guitar which buzzes too loudly and in the other channel is a guitar which <em>crunches</em> too loudly. In the middle are some drums that have been <a href="http://en.wikipedia.org/wiki/Dynamic_range_compression">compressed to buggery</a> and the vocals are overgained just enough to compete with the guitars. That's <em>it</em>.</p> <p><strong>Lowered Expectations</strong> <del>will be</del> is the openning track on our <abbr title="Extended Player">EP</abbr>. <del>This will be made available soon so 'watch this space' (or subscribe to the damned <a href="http://www.heydonworks.com/rss.php">RSS</a> so you don't have to bother)</del> <a href="https://play.spotify.com/album/4I9CsCzTgdPXzeZj2C3OFi">Check the EP out on Spotify</a>.</p> A Free Icon Web Font https://heydonworks.com/article/a-free-icon-web-font/ 2011-10-18T00:00:00.000Z https://heydonworks.com/article/a-free-icon-web-font/ <p>In a <a href="http://www.heydonworks.com/article/using-icon-web-fonts">previous article</a>, I addressed the many advantages of using a <strong>web font</strong> (in place of images) to render icons into your <abbr title="User Interface">UI</abbr> design. In the same article I mentioned a frustrating deficit of high quality, <em>free</em> icon web fonts available for embedding and conceded my own failure at building one with <a href="http://fontstruct.com/">Fontstruct</a> (less a font design tool than a mental health risk).</p> <p>After continued experimentation, I found a satisfactory way to create a <abbr title="True Type Font">TTF</abbr> and I'm now able to offer you <strong>Heydings Icons</strong>. It's a fairly modest collection of <del>50</del> <del>57</del> 60 glyphs specifically intended for the accessorization and classification of <strong>textual cues</strong> such as hyperlinks, navigation elements and buttons. You can, of course, use the set much more expressively as well. Also, there's no requirement to embed; you may just want to use it as a desktop/print font.</p> <h2>The icon web font in action</h2> <p>As I said, the font is best used to enhance text-based content. Probably the best way of achieving this is via the <code>:before</code> and <code>:after</code> pseudo-classes, since this requires no changes to the markup. In the following example, I am using two icons to help classify a link that connects to an <abbr title="Really Simple Syndication">RSS</abbr> resource served from an external location.</p> <h3>The code</h3> <pre> <code>a:before, a:after { font-family:'Heydings'; } <p>a[href*=&quot;rss&quot;]:before { color:#c03f29; content:'R'; }</p> <p>a[href*=&quot;rss&quot;]:after { vertical-align:super; font-size:16px; content:'e'; } </p></code></pre><p></p> Vintage Tobacco Advertising https://heydonworks.com/article/vintage-tobacco-advertising/ 2011-12-29T00:00:00.000Z https://heydonworks.com/article/vintage-tobacco-advertising/ <p><strong>Rock and roll</strong> has always been a contrary form of music. At once 'the devil's music' and the soundtrack to the <a href="http://www.americansc.org.uk/Online/American_Dream.htm">American Dream</a>, it has leant itself to as much commercial dogma as rebellious transgression. Rock and roll is both savage and servile. It's sexual awakenings and automobile sales. This moral and ideological duplicity is what makes the genre so interesting and it's something that I don't think is acknowledged frequently enough.</p> <p>Whilst researching footage for <strong>Wet Face</strong>'s <a href="http://www.amazon.co.uk/Lowered-Expectations/dp/B005O2W5DY/ref=sr_1_1?ie=UTF8&qid=1325152204&sr=8-1">Lowered Expectations</a>, I came across a collection of old tobacco advertising curated by the <a href="http://www.archive.org/details/movies">internet archive</a>. Aesthetically speaking, the degraded analogue footage complemented the band's lo-fi sound. The 50s and 60s vintage was also apt, since it came from a golden age of <a href="http://en.wikipedia.org/wiki/Garage_rock">garage rock</a> and <a href="http://www.tittyshakers.com/jukejoint3.htm">tittyshakers</a>. More importantly, however, I felt that the <strong>tobacco advertising</strong> theme could make a pretty servicable allegory for the duplicity I have been trying to describe.</p> <p style="text-indent:0; text-align: center"><iframe src="https://www.youtube.com/embed/LClWngjsAis?fs=1&#038;feature=oembed" width="400" height="300" frameborder="0" allowfullscreen=""></iframe></p> <p>Tobacco is (and especially was) big business. It's what <a href="http://www.urbandictionary.com/define.php?term=the%20man">The Man</a> would have you take up. To no lesser extent &ndash; and quite without irony &ndash; tobacco smoking has traditionally been the accessory of <a href="http://blog.georgetownvoice.com/wp-content/uploads/2009/07/6601_rebel_without_a_cause_jigsaw_puzzle_lg.jpg">rebellion</a>. It's what you <em>shouldn't</em> be doing behind the bike shed.</p> <p>Aside from the Warholian girl dancer (who acts as a sort of visual throughline for the piece) all the remaining footage consists of defunct tobacco advertising, injected in short, quasi-subliminal bursts. Given that many music video channels now have a policy against <a href="http://www.wordmagazine.co.uk/content/ridiculous-censorship">depicting the consumption of tobacco</a>, this content has an oddly illicit flavour. At least, it <em>would</em> have if any of the advertised products were still actually available to purchase or if they weren't the produce of some of the most established organisations in the history of <strong>Corporate America</strong>.</p> <p>Incidentally, <strong>Wet Face</strong>'s 5-track Lowered Expectations <acronym title="Exrended Player">EP</acronym> is available to purchase from iTunes or <a href="http://www.amazon.co.uk/Lowered-Expectations-EP-Explicit/dp/B005O2W58E/ref=sr_shvl_album_1?ie=UTF8&qid=1325156497&sr=301-1">Amazon mp3</a>&hellip;</p> A Perch XML Sitemap https://heydonworks.com/article/a-perch-xml-sitemap/ 2012-04-19T00:00:00.000Z https://heydonworks.com/article/a-perch-xml-sitemap/ <p>One of the best things about the <a href="http://grabaperch.com/">Perch</a> CMS is its lack of <a href="http://html5boilerplate.com/">boilerplate</a>. In fact, Perch creator Rachel Andrew is <a href="http://www.rachelandrew.co.uk/archives/2012/03/21/stop-solving-problems-you-dont-yet-have/">quite opposed</a> to such bloated, polyfill-ridden framework code. Why include a mass of default code you've yet to decide you even need? The performance hit is just not tolerable.</p> <p>The trade-off (if you can call 'having tremendous fun authoring your own code' a trade-off) is that there are a number of features that are simply not supported by default. At the time of writing, a dynamic <abbr title="Extensible Markup Language">XML</abbr> sitemap for Perch's blog extension is one such feature. In Wordpress, you'd simply install a plugin, click a few buttons in the admin <abbr title="Graphical User Interface">GUI</abbr> and assume that the 4.5 star community rating means it is dependable. In Perch, you have to be a <em>real</em> developer and do it mostly from scratch. The basic steps are as follows:</p> <ul> <li>Create a sitemap.php page</li> <li>Create a sitemap-item.html template</li> <li>Configure perch_blog_custom() in sitemap.php to use the template</li> <li>Manage extensions in the .htaccess file</li> <li>Refer to the sitemap location in your robots.txt</li> </ul> <h2>Create Sitemap.php</h2> <p>Sitemap.php is set up almost exactly like any other Perch-enabled page on your server, except that the perch runtime include should appear <em>after</em> the content type header that defines the document as XML:</p> <pre> <code>&lt;?php header ("Content-Type:text/xml"); include('perch/runtime.php'); ?&gt; &lt;urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&gt; &lt;!-- ENTRIES HERE --&gt; &lt;/urlset&gt; </code></pre> <p>With that taken care of, the next thing you ought to do is include all the static and category pages. Nothing fancy; just code them in manually using the following format:</p> <pre> <code>&lt;url&gt; &lt;loc>http://www.your-site.com/your-url&lt;/loc&gt; &lt;changefreq>monthly&lt;/changefreq&gt; &lt;priority>0.2&lt;/priority&gt; &lt;/url></code> </pre> <p><strong>Priority:</strong> The <a href="http://groups.google.com/a/googleproductforums.com/forum/#!category-topic/webmasters/sitemaps/JbZqJq9npas">priority tag</a> is used to tell search engines which pages should be paid the most attention when there are a number of site-wide updates to your content. "1.0" is highest and is typically attributed to the homepage. On a blog that lists excerpts of recent articles on the home page (like HeydonWorks), this pattern seems logical.</p> <h2>Sitemap-item.html</h2> <p>Our next task is to create a template for our post entries so that we can inject them amongst the hand-coded <code>&lt;url&gt;</code>s we devised in the last section. Take a single <code>&lt;url&gt;</code> snippet like the one described above and place it in a new file, saving it in <code>templates/blog</code> as 'sitemap-item.html'. After you've inserted your <a href="http://support.grabaperch.com/index.php?pg=kb.page&id=13">Perch content</a> template tags, the code should look something similar to this:</p> <pre> <code>&lt;url&gt; &lt;loc&gt;http://www.your-site.com/article/&lt;perch:blog id="postSlug" /&gt;&lt;/loc&gt; &lt;changefreq>monthly&lt;/changefreq&gt; &lt;priority>0.2&lt;/priority&gt; &lt;/url&gt;</code> </pre> <p>Next, we need to call the post URL information via our template in sitemap.php. This is a perfect case for the <a href="http://support.grabaperch.com/index.php?pg=kb.page&id=93"><code>perch_blog_custom()</code></a> function, configured as follows.</p> <pre> <code>$opts = array( 'template'=&gt;'blog/sitemap-item.html', 'sort'=&gt;'postDateTime', 'sort-order'=&gt;'DESC' ); perch_blog_custom($opts);</code> </pre> <p>We've already told the sitemap.php to render as XML, but the .php extension remains. Google will be looking for 'sitemap.xml' so we'll need to make a rule in our <a href="http://en.wikipedia.org/wiki/Htaccess">htaccess</a> file to serve 'sitemap.php' when 'sitemap.xml' is requested. Add the following to your htaccess:</p> <pre> <code>RewriteRule (.*).xml(.*) $1.php$2 [nocase]</code> </pre> <p>As well as submitting your XML sitemap to Google via <a href="http://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDgQFjAA&url=http%3A%2F%2Fwww.google.com%2Fwebmasters%2Ftools%2F&ei=7DqQT4bjG9DA8QPDxvjCBA&usg=AFQjCNHzw4v7cHMZ9WeuuM4BZp6bSIyNlw">Google Webmaster Tools</a>, it's also a good idea to place a reference in <code>robots.txt</code>:</p> <pre> <code>Sitemap: http://www.your-site.com/sitemap.xml</code> </pre> <p>That should be everything you need.</p> Types Of Web Developer https://heydonworks.com/article/types-of-web-developer/ 2012-05-01T00:00:00.000Z https://heydonworks.com/article/types-of-web-developer/ <p>To say one is a Web Developer is similar to saying one is an engineer. Without further clarification, the label means very little. To help with apprehending the various specialisms within the field, I have created this transparently cynical piece of <a href="http://en.wikipedia.org/wiki/Link_bait">link bait</a>. My list is by no means comprehensive and I invite you to offer additions via the Twitter comments (#devtypes) or by email (<a href="mailto:heydon@heydonworks.com">heydon@heydonworks.com</a>) if you wish to submit a fuller description. Compelling suggestions will be included with attribution.<br><br> <strong>Warning:</strong> Some bad language to follow.</p> <h2>1. Rockstar</h2> <p>The so-called <strong>Rockstar</strong> developer has no relationship with either music or &mdash; since his or her talents have such a narrow appeal &mdash; stardom. They <em>do</em> enjoy the attention of groupies, but such a following is typically constituted by heterosexual members of the same sex.</p> <p>Rockstar programmers are prized for their impressive ability to quickly adopt and master new tehnologies and techniques. All too often, this enviable aptitude is employed to find solutions for problems that don't fucking exist.</p> <h2>2. Bricklayer</h2> <p><strong>Bricklayers</strong> avoid authoring code. Instead, they prefer to rely on the third party modules, plugins, extensions, libraries and widgets that form the building blocks of their application.</p> <p>If it all goes wrong, try to resist the temptation to shout "JENGA!" as their <a href="http://en.wikipedia.org/wiki/Tower_of_Babel">Tower Of Babel</a> collapses under its own payload. Fortunately, in this eventuality, there are a number of anonymous parties to blame.</p> <h2>3. Hacker</h2> <p>An extremely talented Bricklayer but with more maps, less <abbr title="Structured Query Language">SQL</abbr> and an obliquely political agenda.</p> <h2>4. Personal Shopper</h2> <p>The <strong>Personal Shopper</strong> is a henchman who belongs to the Client's inner circle. With a limited understanding of <abbr title="Hypertext Markup Language">HTML</abbr>, <abbr title="Cascading Style Sheets">CSS</abbr>, The English Language or basic design principles, the Personal Shopper is charged with 'designing' the website using Adobe's photo editor, <a href="http://37signals.com/svn/posts/1061-why-we-skip-photoshop">Photoshop</a>.</p> <p>The Client and his Personal Shopper are often equally oblivious to the sheer tedium and futility that consequently ensues.</p> <h2>5. Shoplifter</h2> <p>The <strong>Shoplifter</strong> is the one whose job it is to translate the Personal Shopper's picture of a website into code. For the sake of <a href="http://en.wikipedia.org/wiki/Web_accessibility">accessibility</a> and <a href="http://html5doctor.com/outlines/">good document structure</a>, this usually requires many a conjuring trick.</p> <p>Anxiety sets in when the Shoplifter realises that their friends have forgotten to think about functionality again and that a new set of designs <em>failing to address this issue</em> will soon arrive in the post.</p> <h2>6. DOManipulator</h2> <p>From <abbr title="Document Object Model">DOM</abbr> plus Manipulator; essentially a code-literate <abbr title="User Interface">UI</abbr>/<abbr title="User Experience">UX</abbr> designer.</p> <p>Whilst they are particularly adept at arranging and rearranging the data presented to the user, just don't ask the <strong>DOManipulator</strong> how the data got there, where it came from or how it was modelled. According to the DOManipulator, there is an events-based extension for CSS. This extension is called javascript.</p> <h2>7. Pedant</h2> <p>The <strong>Pedant</strong> is a developer whose expertise in <a href="http://en.wikipedia.org/wiki/Semantic_HTML">semantic HTML</a> is expressed entirely by pointing out the errors, no matter how small, in other developers' code grammar.</p> <p>If you've ever shown a fellow developer a rough proof of concept and he's rolled his eyes at the less than optimal nesting of heading elements, you've probably encountered a pedant.</p> <p>Pedants' portfolios are usually extremely scant, either because they take forever to build perfect websites or because their many inevitably imperfect creations are omitted (fearing accusations of hypocrisy).</p> <h2>8. Brogrammer</h2> <p>From the fraternity moniker 'bro' plus 'programmer'. The <strong>Brogrammer</strong> is a programmer who identifies coding with hangovers. Having discovered that doing a day of programming is a particularly curative post-binge-drinking activity, he has forged a strong association whereby he can no longer even <em>contemplate</em> writing code without being depleted of electrolytes, vitamins and sleep.</p> <p>His ambition as a programmer is inevitably superceded by alcohol's own '<a href="http://www.theperspectivesofnietzsche.com/nietzsche/nwill.html">will to power</a>', resulting in shitty work. Either that, or he has largely fictionalised his 'brogrammer' status as a compensatory front, which is almost always the case.</p> <h2>9. Non-developer</h2> <p>Not all protagonists in development agencies are always developers and, by way of contrast, the <strong>Non-developer</strong> is certainly worthy of a mention.</p> <p>The typical Non-developer is the Project Manager for the 'home team'. He or she may spend most of their time pitching or communing with clients, but the title 'Non-developer' does not suggest that they are unable to develop at all; just that this is not their <em>prescribed</em> role.</p> <p>Inevitably, Non-developers are looked down upon for not being 'experts'. However, by being able to see the wood despite the trees, they have a startling knack for pointing out embarrassing misconceptions on the part of their more entrenched colleagues. So don't get too cocky&hellip;</p> <h2>10. Sampler</h2> <p><strong>Added by Greg Simon in the comments.</strong></p> <p>"The sampler has an understanding of the basic fundamentals of HTML/CSS/Javascript and visits sites that contain code snippets showing off developed code. The sampler will attempt to use the code snippet by copying the demo and seeing if it works out the box. The sampler will spend a minimum amount of time back-engineering the developed code to suite their purpose, if the code snippet is too difficult or cumbersome to implement, they will promptly abandon the sampled script in pursuit of a different, often more simplistic, approach that they can use"</p> <p>The sampler's motto: "it's not about the journey, it's about the destination".</p> An App Icon Font https://heydonworks.com/article/an-app-icon-font/ 2012-05-15T00:00:00.000Z https://heydonworks.com/article/an-app-icon-font/ <p>My 'Heydings Icons' font has been doing the rounds for some time now, and I am proud to have been one of the early innovators to release a completely free, embeddable icon font for web <abbr title="User Interface">UI</abbr> designers. However, until now I have singularly failed to promote the availability of Heydings Icons' companion font, 'Heydings Controls'. This is despite the fact that it has been available from <a href="http://www.dafont.com/heydings-controls.font">Dafont</a> and <a href="http://www.fontsquirrel.com/foundry/Heydon-Pickering">Font Squirrel</a> for some months.</p> <p>As I wrote in my original article for <strong>Heydings Icons</strong>, this set was intended specifically to decorate textual cues: I deliberately omitted the kind of application-like control symbols that are included in many other icon web fonts. I believed that symbols relating to <em>interactions</em> were sufficiently different from explanatory decorators to be treated separately.</p> <p><strong>Heydings Controls</strong> was designed as a sort of 'expansion pack' for <strong>Heydings Icons</strong> and covers a number of interactive controls ommitted from the original. It might be useful to view the two fonts as styles within the same family. The <a href="http://en.wikipedia.org/wiki/Rule_of_thumb">rule of thumb</a> is that the <strong>Heydings Controls</strong> icons are ones you might use within an area of your document encapsulated by a <code>&lt;div&gt;</code> with an <abbr title="Accessible Rich Internet Applications">ARIA</abbr> role of 'application'. The icons in this newer set are illustrated alongside the original icons below.</p> <figure> <img src="https://heydonworks.com/images/heydings_controls.gif" alt="Heydings Icons and Heydings Controls combined"><figcaption>Heydings Controls icons are coloured gold.</figcaption> </figure> <p>You can download both sets of icons from my <a href="http://www.fontsquirrel.com/foundry/Heydon-Pickering">Font Squirrel</a> page.</p> <p><a class="button-shaped" href="http://www.fontsquirrel.com/foundry/Heydon-Pickering">Heydings Icons on Font Squirrel</a></p> CSS Is Not Simple https://heydonworks.com/article/css-is-not-simple/ 2012-05-20T00:00:00.000Z https://heydonworks.com/article/css-is-not-simple/ <p>In <abbr title="Cascading Style Sheets">CSS</abbr>, there are four ways to visually position <abbr title="Hypertext Markup Language">HTML</abbr> elements within your web page. These are <strong>static</strong>, <strong>relative</strong>, <strong>absolute</strong> and <strong>fixed</strong>. There can be a great deal of confusion when it comes to discerning between these values, so I'd like to help clear things up. </p><p style="text-indent:0;">Or perhaps not &hellip;</p> <h2>Absolutely relative</h2> <p>Relatively positioned elements are positioned relative to where they <em>would</em> appear if they weren't set to <code>position:relative</code>; a positional value which makes them relative to themselves. In other words, their position (like any other measurable position) is 'absolute', but only in terms of a relative &mdash; and, in this case, <em>reflexive</em> &mdash; trajectory. Elements that are positioned absolutely, on the other hand, are positioned relative to their parent elements. In other words, absolutely positioned elements have an absolute position relative to their parental relative.</p> <p>Let me expand further. If I were to give an element the positional value of 'relative', then this would allow any of its decendant relatives positioned with 'absolute' to adopt an absolute position <em>relative</em> to the 'relative' parental relative. Descendant relatives that are positioned relatively, however, remain relative to themselves and not to their parental relatives. If the parental relative does not have a position of 'relative', then absolutely positioned descendant relatives are positioned relative to the ancestoral <code>&lt;body&gt</code> relative, which has a position of 'static'.</p> <h2>Statically unfixed</h2> <p>'Static' elements <em>do not have a position</em>. If you do not want to position your element at all, you must choose <code>position:static</code>. Elements that are 'static' are called so because they are immobile, which allows them to move towards or away from you when using the scrollbar. Their position is fixed in one place in the document; a position to which the viewport is relative. Elements with a 'fixed' position are completely different. Unlike static elements that are fixed in one place, 'fixed' elements are free to follow you wherever you go. 'Fixed' elements are static relative to the viewport, but <em>absolutely disregard</em> the viewport's position relative to the document.</p> <p>I hope that is all absolutely clear (relatively speaking). If you need more information on positioning in CSS, please refer to these additional resources:</p> <ul> <li><a href="http://www.w3schools.com/cssref/pr_class_position.asp">W3Schools' opinion</a> on the position property</li> <li><a href="http://reference.sitepoint.com/css/position">Sitepoint</a> try their best to explain it</li> <li><a href="https://heydonworks.com/">DJ Thierry K</a> has a go (with some demo's)</li> <li><q>The box is a normal box</q> and other wisdom from the <a href="http://www.w3.org/TR/CSS21/visuren.html#choose-position">specification</a></li> </ul> <p>For a <a href="http://en.wikipedia.org/wiki/Style_sheet_language">programming language</a> that isn't really even a programming language, <abbr title="Cascading Style Sheets">CSS</abbr> is <em>not</em> simple.</p> Pingomatic For Perch https://heydonworks.com/article/pingomatic-for-perch/ 2012-08-28T00:00:00.000Z https://heydonworks.com/article/pingomatic-for-perch/ <p>I love the <a href="http://grabaperch.com/">Perch <abbr title="Content Management System">CMS</abbr></a>. It isn't crammed with features and plugins to placate each and every type of developer; it just does the Content Management task really well. Nonetheless, every so often I look for a little tool that Wordpress-derived muscle memory tells me should be present, and I'm left wanting.</p> <figure> <img src="https://heydonworks.com/images/send_pings.png" alt="The Perch admin navigation"> <figcaption>The 'Send Pings!' button</figcaption> </figure> <p>One such feature was <abbr title="Extensible Markup Language">XML</abbr> sitemap support, which I covered in my article <a href="http://www.heydonworks.com/article/a-perch-xml-sitemap"><em>A Perch XML Sitemap</em></a>. In this post, I'm going to help Perch bloggers incorporate <a href="http://pingomatic.com/">Ping-o-matic</a>.</p> <h2>What is Ping-o-matic?</h2> <p>Ping-o-matic is a service that allows you to 'ping' various blog-specific search engines and notify them that your blog's content has been updated. In turn, these search engines will find a way to notify their readership that you've made new content available, driving traffic to your site. Clearly, this is advantageous &mdash; which is why Wordpress automatically sends 'pings' via ping-o-matic whenever you publish an article.</p> <p>It would be possible to send pings automatically in Perch, but we're not going to build anything <em>quite</em> so intrusive. Instead, I have written a little bit of code which allows you to ping Ping-o-matic's roster at the touch of a button. Because Ping-o-matic's webform uses the <strong>GET method</strong>, this task is made very easy. To add the functional button to your admin navigation, simply open <code>perch/inc/top.php</code> and paste the code to follow in at <strong>line 140</strong> (approx), just before <code>echo '&lt;ul&gt;';</code>. When you click the button, a new tab is openned detailing which pings were sent where.</p> <pre>echo '&lt;li&gt;&lt;a style="background:#7bc142;" id="send-pings" href="http://pingomatic.com/ping/?title='.$_SERVER['SERVER_NAME'].'&blogurl=http%3A%2F%2F'.$_SERVER['SERVER_NAME'].'&chk_weblogscom=on&chk_blogs=on&chk_feedburner=on&chk_newsgator=on&chk_myyahoo=on&chk_pubsubcom=on&chk_blogdigger=on&chk_weblogalot=on&chk_newsisfree=on&chk_topicexchange=on&chk_google=on&chk_tailrank=on&chk_postrank=on&chk_skygrid=on&chk_collecta=on&chk_superfeedr=on" target="_blank">Send Pings!&lt;/a&gt;&lt;/li&gt;';</pre> <h2>Customising the code</h2> <p>You'll notice that I've used <code>$_SERVER['SERVER_NAME']</code> for both the 'title' and 'blogurl' parameters. If you wish to send a different title, just replace my variable. If there are certain services you do not wish to ping, simply remove the associated parameter. For example, if you don't want Feedburner users to sully your content with their mere gaze, remove <code>&chk_feedburner=on</code> from the query string.</p> <p>Lastly, Ping-o-matic also allows you to provide your master <abbr title="Really Simple Syndication">RSS</abbr> location. I haven't included this because I've no idea where you keep your RSS, but you can use the <code>rssurl</code> parameter something like this:</p> <pre>&rssurl=http%3A%2F%2Fwww.your-blog.com%2Frss.php</pre> <p>That's it. If anyone has any ideas on improving this little hack, please get in touch. I'm <a href="http://twitter.com/heydonworks">@heydonworks</a>.</p> Accessible Buttons Jquery Plugin https://heydonworks.com/article/accessible-buttons-jquery-plugin/ 2013-05-10T00:00:00.000Z https://heydonworks.com/article/accessible-buttons-jquery-plugin/ <div role="note"> <p><strong>Please note:</strong> The following should be considered an experiment. There is rarely a good reason not to use a <code>&lt;button&gt;</code> element for button-like controls, especially if it means loading a javascript resource just to polfill the behaviors that <code>&lt;button&gt;</code> already offers.</p> </div> <p style="margin-bottom: 1.5em; text-indent: 0;">How many of the elements that users can <em>click on</em> in your web pages and applications are actually <code> &lt;button&gt;</code>s?</p> <p>As outlined in <a href="http://www.marcozehe.de/">Marco Zehe's post</a>, <cite>Making Clickables Accessible</cite>, it is possible, with the help of attribution specified in <abbr title="Web Accessibility Initiative - Accessible Rich Internet Applications">WAI-ARIA</abbr>, to make interactively functional, clearly defined buttons using just about any element. This is especially useful in situations when an extra element (a <code>&lt;button&gt;</code>) would otherwise have to be shoe-horned into your slim, semantic markup.</p> <p>There's no reason at all in javascript-click-binding-expand-event-thingy terms, but managing accessibility is not so trivial. For a start, assistive technologies (AT) won't be aware of the element's role as a button unless we make it explicit. Neither do some elements &mdash; unlike buttons and links &mdash; receive <em>focus</em> without deliberate intervention. Even if they <em>were</em> focusable, they're not rigged to the key events (ENTER or SPACE) that are necessary to press the button via the keyboard. Balls!</p> <p>To collectively solve these problems, I've created a tiny (just under 1K minified) jQuery plugin called <strong>buttonlike.js</strong>. The plugin &hellip;</p> <ul> <li>Defines elements as buttons with <code>role="button"</code></li> <li>Gives them <code>tabindex="0"</code> so they are focusable</li> <li>While focused, triggers the faux buttons' click events on ENTER and SPACE keydown events</li> <li>Allows you to optionally define relationships between the "button" and the element(s) it affects using <code>aria-controls</code></li> <li>Allows you to optionally make the button a "toggle" using <code>aria-pressed</code> (true / false)</li> </ul> <h2>Example 1:</h2> <p>Buttonlike.js is perhaps at its most helpful just used without any of the options, applied to any elements in the page that have <code>role="button"</code> already. It's an easy way to ensure these "buttons" are screenreader and keyboard accessible.</p> <pre> <code>$('[role="button"]').buttonlike(); </code></pre> <h2>Example 2:</h2> <p>Here is an example using a button-like <code>h3#toggle</code> that toggles the state of a <code>div#summary</code>:</p> <pre> <code>$('h3').buttonlike({controls: 'summary', pressed: false}); </code></pre> <h3>The markup</h3> <pre> <code>&lt;h3&gt; &lt;span role="button" aria-controls="summary" tabindex="0" aria-pressed="false"&gt;Heading&lt;/span&gt; &lt;/h3&gt; &lt;div id="summary"&gt; ...content... &lt;/div&gt; </code></pre> <p><strong>Notes:</strong> Because we wish the heading level to be announced, we must preserve the heading "as is" and attach our button functionality to a child <code>&lt;span&gt;</code>, which is dynamically injected. Why not inject a true <code>&lt;button&gt;</code> in this case? Just because a span is much more malleable in terms of styling. In most cases, a <code>&lt;span&gt;</code> will simply inherit the styles of the heading. You can then build on this baseline.</p> <p>In addition, the option of <strong>pressed</strong> is set to "false". This means <code>aria-pressed</code> is used, with an initial value of "false". This value toggles between true and false according to click events triggered directly or via the keyboard.</p> <h2>Example 3:</h2> <p>This button affects multiple elements simultaneously. The <strong>pressed</strong> option is not applicable, so it defaults to "null" and the <code>aria-pressed</code> attribute is not used:</p> <pre> <code>$('button#delete').buttonlike({controls: 'summary body'}); </code></pre> <p><strong>Notes:</strong> In this example, we've made a button "button-like"! This is fine, if you are using a <code>&lt;button&gt;</code> anyway but want to take advantage of the plugin's other features. Instead of <code>role="button"</code>, the <code>&lt;button&gt;</code> will be given <code>type="button"</code>. This is important because it prevents some user agents from considering the button a <em>submit</em> button when within a form. Also, note the space separated IDs for the <strong>controls</strong> option. A space separated list is perfectly legal for <code>aria-controls</code>.</p> <pre> <code>&lt;button id="delete" type="button" aria-controls="summary body"&gt;Delete&lt;/button&gt; &lt;div id="summary"&gt; ...content... &lt;/div&gt; &lt;div id="body"&gt; ...content... &lt;/div&gt; </code></pre> <h2>Download</h2> <p>Perhaps rarely, <strong>buttonlike.js</strong> isn't a jQuery plugin that lets you do anything amazing with the <abbr title="Document Object Model">DOM</abbr>. What it does instead is help you make the many amazing things that you might choose to do a bit more sensical to AT users. If that's the sort of thing you think's a good idea, include the tiny script before all your <code>click(function()</code> stuff in the document. Download below and <em>please</em> suggest any improvements (or point out any errors) in the comments.</p> <p><a href="https://github.com/Heydon/buttonlike" class="button-shaped">DOWNLOAD<br> on Github</a></p> <p><strong>Important Note:</strong> As Steve "Smart Arse" Faulkner correctly points out in the comments, placing the button role on semantically specific elements breaks with <a href="https://dvcs.w3.org/hg/aria-unofficial/raw-file/tip/index.html#second-rule-of-aria-use">The Second Rule Of Aria Use</a>. I have changed the plugin accordingly: For headings and other elements that must retain their semantic status for AT, a child span element is inserted and the button functionality is placed on the <code>&lt;span&gt;</code> instead. Also, certain "grouping" elements (eg. <code>&lt;ul&gt;</code> and <code>&lt;tr&gt;</code>) will refuse to become "button-like". An error note is written to the console. Cheers.</p> Shrinking Button Outlines https://heydonworks.com/article/shrinking-button-outlines/ 2013-11-30T00:00:00.000Z https://heydonworks.com/article/shrinking-button-outlines/ <style type="text/css"> .test-button, .test-button-2 { cursor: pointer; border: 0; font-family: inherit; display: inline-block; margin: 1.5em auto; font-size: 1.5em; border-radius: 0; background-color: #802626; padding: 0.25em 1em; color: #fff; outline: 2px solid transparent; outline-offset: 50px; -webkit-transition: 1s ease all; -moz-transition: 1s ease all; -ms-transition: 1s ease all; -o-transition: 1s ease all; transition: 1s ease all; } .test-button:focus { outline: 2px solid #222; outline-offset: 0; } .test-button-2 { outline: 50px solid transparent; outline-offset: 0; } .test-button-2:focus { outline: 2px solid #222; } button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } button:active { -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none; transition: none; } </style> <p>I've always been a bit concerned about <code>:focus</code> styles for buttons. Some browsers barely do anything by default, making things less than obvious, whereas Firefox's insistence on including an inner outline (<code>-moz-focus-inner</code>) is ugly. That is, ugly if you spot it at all.</p> <p>I'm on board with <a href="https://twitter.com/rogerjohansson/status/382531860686848000">Roger Johansson</a>'s approach of pairing <code>:focus</code> styles with <code>:hover</code> styles. In my own CSS, this usually means a change in background or font colour. However, I'm in the market for a technique which is better still at drawing the eye towards the focused "target" that is the button.</p> <p>A little while back, Nikita Vasilyev came up with a <a href="http://n12v.com/focus-transition/">really interesting solution</a> which animated focus rings between elements as focus moved from one to another. Great stuff.</p> <p>The only problem was, this is a javascript solution to a problem that really isn't in the realm of javascript. Not in my opinion, anyway. If every accessibility improvement required 5k of javascript, well&hellip; the performance issue would make the product inaccessible. It was this inspiring post, nonetheless, which I recalled when I starting playing with the <code>outline-offset</code> property.</p> <p>Outlines don't stand out well when wrapped around rectangular buttons. At least, not the weedy <code>1px dotted</code> outlines we use as standard on links. By using <code>outline-offset</code>, it's easy to move the outline away from the edge, making it clearer.</p> <pre> button:focus { outline: 1px dotted; outline-offset: 3px; } </pre> <p>Then, I thought "what about animating the outline offset?" It turns out the <code>outline-offset</code> property can be animated using a simple CSS transition and the animation can be triggered on <code>:focus</code>. Try shifting focus (using the TAB key) to the button below to see the effect.</p> <div style="text-align: center"> <button class="test-button">Test button</button> </div> <pre> button { outline: 2px solid transparent; outline-offset: 50px; transition: 1s ease all; } button:focus { outline-offset: 0; } </pre> <p>I'm hoping this would make identifying focused button controls (as they're focused) easier. Because the outline is not part of the click target of the button, you can also transition a thick, transparent outline to a tight, thinner one without blocking surrounding elements.</p> <div style="text-align: center"> <button class="test-button-2">Test button</button> </div> <p>Now we just need to remove the transition for <code>:active</code> so that clicks don't trigger the shrinking effect (below).</p> <pre> button:active { transition: none; } </pre> <p>Some browsers (not many) <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/outline-offset">don't support <code>outline-offset</code></a>. For these browsers, the outline just changes from transparent to solid and we're back to square one. Other browsers don't support transitions. Fine, so it doesn't move, but it still appears like it always did. What do you think?</p> Apps For All: Praise And Errata https://heydonworks.com/article/apps-for-all:-praise-and-errata/ 2014-07-21T00:00:00.000Z https://heydonworks.com/article/apps-for-all:-praise-and-errata/ <p>In case you weren't already aware, I wrote a book. This is an unusual book since it is a whole technical book dedicated to making web applications accessible. Want to understand how to make dynamic, interactive applications that don't alienate and annoy folks? Using WAI-ARIA and other cool stuff? I've got you covered.</p> <figure> <img src="https://shop.smashingmagazine.com/media/catalog/product/cache/2/image/342x365/9df78eab33525d08d6e5fb8d27136e95/a/p/apps-for-all_v2_icon_grey-shop.png" alt="Book cover for Apps For All Coding Accessible Web Applications"><figcaption><cite><a href="https://shop.smashingmagazine.com/apps-for-all-coding-accessible-web-applications.html">Apps For All: Coding Accessible Web Applications</a></cite></figcaption></figure> <p>So there you have it. This post is where I'm collecting together reviews and endorsements for the book, plus where I'm listing any errata that the keen-eyed have spotted. Thank you.</p> <ul> <li><a href="#praise">Praise for <em>Apps For All</em></a></li> <li><a href="#errata">Errata (small bits I screwed up)</a></li> </ul> <h2 id="praise">Praise</h2> <p>The preeminent Bruce Lawson <a href="http://www.brucelawson.co.uk/2014/apps-for-all-coding-accessible-web-applications-book-review/">wrote a review of Apps For All</a> on his blog. Sample quotation: <q>Every developer should read this book, and put its techniques into practice. Now.</q>.</p> <blockquote class="long"> <p>Heydon has written a truly awesome book here! He gets right to the stuff that developers love most: Coding. He provides concise context for those not too familiar with accessibility yet, but doesn't scare devs with legal stuff. He concentrates on the positive impact aspects aside those legal reqs and thus makes sure the book is fun to read! If you've been looking for a modern up-to-date easy introduction or refreshment of accessibility coding skills, this is the book to purchase!</p> <footer><cite><a href="http://www.marcozehe.de/">Marco Zehe (Mozilla)</a></cite></footer> </blockquote> <blockquote class="twitter-tweet" lang="en"><p>Are you a <a href="https://twitter.com/hashtag/webdev?src=hash">#webdev</a> wanting to code accessible web apps? Buy this <a href="http://t.co/wL5tz2ORtm">http://t.co/wL5tz2ORtm</a> by <a href="https://twitter.com/heydonworks">@heydonworks</a> w/o delay. That is all. <a href="https://twitter.com/hashtag/a11y?src=hash">#a11y</a> <a href="https://twitter.com/hashtag/dev?src=hash">#dev</a></p>&mdash; Jennison Asuncion (@Jennison) <a href="https://twitter.com/Jennison/statuses/475170224308645889">June 7, 2014</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <blockquote class="long"> <p>Having read this book over the last couple of days I am in no doubt as to what all the developers at work are getting for Xmas. Its a fantastic read that sets out the reasons for WAI ARIA in a really easy to read and understand manner. the concepts are well explained and the code snippets are an awesome compliment to the well delivered prose. Its both funny and educational at the same time and I would highly recommend it to any developer who is keen to broaden his skill set. Fantastic job Heydon and I look forward to the sequel </p> <footer><cite><a href="https://twitter.com/mishu70">Hamish MacKenzie, Global Accessibility Manager</a></cite></footer> </blockquote> <h2 class="errata">Errata</h2> <p>The errata listed below refer to pages in the PDF version of the book. Many thanks to all those who spotted them, particularly <a href="https://twitter.com/GaryJ">@GaryJ</a>, <a href="https://twitter.com/KevinLozandier">@KevinLozandier</a> and <a href="https://twitter.com/carpeau">@carpeau</a>.</p> <ul> <li>In chapter 5, Peekaboo, the markup for the tab interface is really garbled and doesn't add up. <a href="https://heydonworks.com/practical_aria_examples/#tab-interface">Refer to the example code here for the correct HTML</a>.</li> <li><strong>Page 24:</strong> Code snippet should be for the <code>button:active</code> selector, not the simple <code>button</code> selector</li> <li><strong>Page 24:</strong> The <code>top</code> value here should be <code>4px</code> to match the <code>4px</code> <code>box-shadow</code> from the earlier, corresponding example</li> <li><strong>Page 35:</strong> I can't spell "somehwere" (path in the code snippet)</li> <li><strong>Page 35:</strong> <code>aria-controls</code> should point to <code>submenu</code>, not <code>submenu1</code></li> <li><strong>Page 40:</strong> I'm using CSS comments in HTML for some reason&hellip;</li> <li><strong>Page 88:</strong> There are two code examples. Ignore the <code>ID</code> and <code>aria-controls</code> values in the second. Stick to the first and the live example</li> <li><strong>Page 104:</strong> "YI really didn't like&hellip;". Yes, that should be "I&hellip;"</li> </ul> Squib Font https://heydonworks.com/article/squib-font/ 2014-08-15T00:00:00.000Z https://heydonworks.com/article/squib-font/ <section class="project"> <h2>Squib Font</h2> <p>The name <strong>Squib</strong> comes from "Square" and "Slab". Squib supports a total of 165 characters, including all the basic punctuation characters and common Western European accents. It also has an eszett!</p> <div aria-label="external links"><a href="http://foundry.heydonworks.com/squib/">Squib demo page and download</a> <a href="https://github.com/Heydon/Squib-Font">Squib on Github</a></div> </section> Auticons https://heydonworks.com/article/auticons/ 2014-08-16T00:00:00.000Z https://heydonworks.com/article/auticons/ <section class="project"> <h2>Auticons Icon Font</h2> <p>Auticons is an icon font and CSS set that harnesses the awesome power of attribute selectors. It places resolution independent icons before or after any hyperlink with an href that matches a certain, expected pattern. In other words, it's an <em>automatic</em> icon font.</p> <div aria-label="external links"> <a href="https://heydonworks.com/auticons-icon-font/">Auticons demo page</a> <a href="https://heydonworks.com/auticons-icon-font/auticons.zip">Auticons download</a> </div> </section> Paragrabbr https://heydonworks.com/article/paragrabbr/ 2014-08-16T00:00:00.000Z https://heydonworks.com/article/paragrabbr/ <section class="project"> <h2>Paragrabbr</h2> <p>I use Paragrabbr <em>a lot</em>. It's a lorem ipsum generator I wrote in AngularJS which includes special punctuation &mdash; like em dashes &mdash; and phrasing elements like <code>&lt;a&gt;</code>, <code>&lt;strong&gt;</code> and even <code>&lt;kbd&gt;</code>. Helps you get your type design detail right.</p> <div aria-label="external links"><a href="http://paragrabbr.heydonworks.com/">Use Paragrabbr</a></div> </section> Revenge.css https://heydonworks.com/article/revenge.css/ 2014-08-16T00:00:00.000Z https://heydonworks.com/article/revenge.css/ <section class="project"> <h2>REVENGE.CSS</h2> <strong>Revenge.css</strong> is a CSS bookmarklet that reports bad html using pseudo content. If the page you use it with has malformed links, deprecated attributes, <code>&lt;div&gt;</code>s inside inline elements, inaccessible buttons, badly nested sections or other errors, you'll see some ugly, pink errors written in nobody's favourite font: <em>Comic Sans</em>. <div aria-label="external links"><a href="https://heydonworks.com/revenge_css_bookmarklet/">Revenge.css</a> <a href="https://github.com/Heydon/REVENGE.CSS/tree/master">Revenge.css on Github</a></div> </section> Practical Aria Examples https://heydonworks.com/article/practical-aria-examples/ 2014-08-17T00:00:00.000Z https://heydonworks.com/article/practical-aria-examples/ <section class="project"> <h2>Practical ARIA Examples</h2> <p>I have written <a href="https://shop.smashingmagazine.com/apps-for-all-coding-accessible-web-applications.html">a book about web application accessibility using WAI-ARIA</a> for Smashing Magazine &mdash; the first of its kind. This popular page hosts all of the examples from the book and more.</p> <div aria-label="external links"><a href="https://heydonworks.com/practical_aria_examples/">Explore the examples</a></div> </section> A Double Edged Sword https://heydonworks.com/article/a-double-edged-sword/ 2014-10-28T00:00:00.000Z https://heydonworks.com/article/a-double-edged-sword/ <p><strong>Editor's note:</strong> <em>This article has been submitted anonymously to me as the editor of <a href="http://www.geekmentalhelp.com/">geekmentalhelp.com</a> &mdash; the website of the <a href="https://twitter.com/search?src=typd&q=%23geekmentalhelp">#geekmentalhelp</a> campaign. Not everyone is in a position to "come out" as a sufferer of mental health problems, but they are still out there; members of our community.</em></p> <hr> <p>This week is <strong>Geek Mental Help Week</strong>. I admit to having mixed feelings about this. On one hand, I salute the effort. We need more awareness of these very disabling conditions. On the other hand, these kind of awareness campaigns hit me hard and I end up just wanting to crawl under a rock until they are over.</p> <p>I am a geek. Nowhere as geeky as some, but certainly geeky enough to wear that hat with pride.</p> <p>I also have been dealing with chronic (often severe) depression for the last 30 or so years. This is not something I discuss in public as there is still much stigma attached to it. There are very real risks to me and my loved ones if the fact I deal with depression, and its extent, became known. This is why I asked this post be anonymous.</p> <p>And in part it is why awareness campaigns such as the <a href="http://geekmentalhelp.com/">Geek Mental Help Week</a> are so important. The public needs to be educated about the existence and the reality of mental illnesses, including in the IT world. And our geeky brothers and sisters who battle mental illness need to know they aren't alone. Mental illness exists. <a href="http://www.nimh.nih.gov/health/statistics/prevalence/serious-mental-illness-smi-among-us-adults.shtml">4.6% of adult Americans experienced a serious mental illness in 2012</a>. <a href="http://www.cmha.ca/media/fast-facts-about-mental-illness/#.VE7I1Mn63Es">20% of Canadians will personally experience a mental illness in their lifetime</a>. <a href="http://www.mentalhealth.org.uk/help-information/mental-health-statistics/suicide/">In the UK, suicide is the leading cause of death for folks under the age of 35</a>. I'm glad these issues are being discussed. I'm glad these stories are coming out.</p> <p>That said, I find it <em>incredibly difficult</em> to have stories of depression thrown in my face, over and over, and over again. I want to scream &quot;ENOUGH ALREADY!&quot; I'm still healing from the furor that hit the web after Robin Williams committed suicide. A lot of well intentioned individuals were talking about it. They were discussing the importance of reaching out to people and making sure every suicidal individual out there had access to help. I'm not sure how many of these people realized the negative impact they were having on a lot of people in situations like mine. There's rarely a day that goes by without me thinking about suicide. </p> <p>I'm reminded of the <a href="https://www.ruok.org.au/">R U Ok?</a> campaign that came out of Australia, &quot;encouraging all Australians to regularly and meaningfully ask anyone struggling with life, 'are you ok?'&quot; It looked like people were randomly asking people &quot;Are you ok?&quot; They asked you that, and seemed to think it discharged them of responsibility. I've wanted to answer back &quot;No, I'm not ***king ok,&quot; just to see what they would say, what they would do. But I knew full well there was nothing they could do or say for <em>me</em>.</p> <p>In some respect, it's a bit like the media campaigns about &quot;speed kills&quot; or &quot;don't drink and drive,&quot; you know, the graphic ads showing the effect of a high speed car crash? It doesn't seem to have a real effect on people who speed or drink. But it sure as hell has a direct and negative impact on people who have lost loved ones in car crashes caused by people who were speeding or drinking.</p> <p>I have a favor to ask of you. If you are new to this, if you have no experience of dealing with mental illness (personally or through loved ones), please, do take a moment to consider the impact of your enthusiasm about the issue. Because awareness campaigns are double-edged swords. We need to build awareness without forgetting there are real people, suffering real pain, that sometimes get caught in the cross-fire.</p> <p>In the meantime, I know that the thing for me to do is withdraw when these things happen. I need to take my distance from the onslaught. And so once more, I shall disconnect for a few days, until the enthusiasm fades a bit, until I can hang out without being confronted with so much talk about mental illness.</p> The Agreement https://heydonworks.com/article/the-agreement/ 2015-05-10T00:00:00.000Z https://heydonworks.com/article/the-agreement/ <p>I had this one friend at school. Let's call him Darren.</p> <p>Darren was a liar — a compulsive one — and boy did he tell some whoppers. Not &quot;the world was created in one week&quot; whoppers, but big ones nonetheless.</p> <p>One lie Darren would tell, at the age of 12, was that he had lost his virginity. Now, nobody had any primary evidence (eww) that this was <em>not</em> the case. But his diminutive age, the fact that he went to an all boys school, his reputation for demonstrably lying in other cases and his resemblance to a tug boat all contributed to the incredibility of his claim. Not one of us could <em>prove</em> he was a virgin, but it stood to reason that he was.</p> <p>The part I find interesting is that none of the other 12-year-old boys would question his claim. Not one. Not because they didn't know how, or were afraid to confront him, but because it would not be politic. The unwritten law stated that one unbelievable lie was worth another and, so long as we didn't skewer his fantasy, he would have to accept that he couldn't skewer ours.</p> <p>Within weeks, every gawky, unattractive and socially inept 12-year-old boy who had come into contact with Darren was a virgin no longer. An agreement had formed, quite organically; an unspoken one to believe the unbelievable.</p> <p>So what do you suppose would happen to any boy who questioned the ludicrous sexual voracity of our barely pubescent cohort? What do you suppose would happen to the boys who, when asked, &quot;have you lost your virginity too?&quot; would reply, &quot;of course not, I'm twelve years old.&quot; Naturally, they were set upon; teased and taunted and ridiculed. The defenders were so fierce because the lie was so fragile.</p> <p>I'm ashamed to say I sometimes tended to be a &quot;defender&quot; as a child, but I try my best to be the kid who says &quot;nope&quot; as an adult. For others, reaching maturity does not appear to be a case of growing the confidence to be truthful. Others choose to weaponize their unbeliefs, trading taunts for decapitations. Why? Because the shame of lying to oneself is cumulative over time, and because the starkness of violent acts make the lies that beget them feel ever so true.</p> Frame Based Animation With Sass https://heydonworks.com/article/frame-based-animation-with-sass/ 2015-06-05T00:00:00.000Z https://heydonworks.com/article/frame-based-animation-with-sass/ <section class="project"> <h2>Frame Based Animation with Sass</h2> <p>I wanted an easy way to create traditional animations, wherein each frame is a different drawing. I created this Sass <code>@mixin</code> which generates keyframe animation blocks for nth children, placing each of these "frames" in an animated sequence. Note the use of the <code>steps(1)</code> timing function&hellip;</p> <div aria-label="external links"><a href="https://github.com/Heydon/frame-based-animation">Code on Github (including Bower command for installation if preferable)</a></div> </section> An album for a11y https://heydonworks.com/article/an-album-for-a11y/ 2015-06-28T00:00:00.000Z https://heydonworks.com/article/an-album-for-a11y/ <p>TL;DR I'm putting together an album to raise money for an organization that supports web accessibility.</p> <hr> <p>I had this brainwave while nursing a hangover in Brighton after Responsive Day Out: There are a load of folks working in the overlapping fields of web standards and accessibility who are musicians. Some really quite accomplished. So, why not ask around and have some tracks donated to a &quot;charity&quot; album which generates funds to support web accessibility. Simple(s).</p> <h2>Tracks flying in</h2> <p>The response has been promising, so it's likely to go ahead. The tracks submitted so far (in no particular order yet) are:</p> <ul> <li>Luck &mdash; <a href="http://twitter.com/gorkamolero">@gorkamolero</a></li> <li>Imprecise and Infrared &mdash; <a href="http://twitter.com/brucel">@brucel</a></li> <li>The WCAG 2.0 Theme Song &mdash; <a href="http://twitter.com/davidmacd">@davidmacd</a></li> <li>The Git Rap &mdash; <a href="http://twitter.com/marak">@marak</a></li> <li>Eatin' Dust (Fu Manchu cover) &mdash; me</li> <li>Tour De Force &mdash; <a href="http://twitter.com/brothercake">@brothercake</a></li> <li>Swallows &mdash; <a href="http://twitter.com/thatemil">@thatemil</a></li> <li>Man With Small F (The Inaccessible PDF song) &mdash; <a href="http://twitter.com/terrillthompson">@terrillthompson</a></li> <li>Girl In The Room &mdash; <a href="http://twitter.com/brucel">@brucel</a></li> </ul> <p><strong>Are you a musician? Do you work in/on/under the Web? Do you have a piece of music laying around? Please contact me using heydon@heydonworks.com or via Twitter.</strong></p> <p>You'll notice there's two submissions by Bruce Lawson. This means I can legitimately use the expression &quot;Brucey bonus&quot;, so that's nice. I think it's a good balance between web development-themed novelty tracks and just good tunes. In addition, I'm trying to pen a track about <code>&lt;div&gt;</code>s called &quot;Divs&quot;.</p> <h2>Artwork</h2> <p>Artwork-wise, I have done a bit of creative lettering. I've taken the <a href="https://twitter.com/search?q=%23a11y&src=typd">#a11y</a> hashtag and supplanted the 11 for two fingers forming the Ronnie James Dio-originated &quot;devil horns&quot; hand gesture. Here's how it's looking:</p> <figure> <img src="https://heydonworks.com/images/2015/06/logo_demo.png" alt="a11y drawn using the devil horns hand gesture for the 11." width="600" height="333"> <figcaption>Accessibility rocks (geddit!?)</figcaption> </figure> <h2>The beneficiary</h2> <p>There has been some discussion about the beneficiary of the proceeds. Ideally, I want it to support an international web accessibility org', but I've had trouble finding one of them. So the shortlist is <a href="http://www.nvaccess.org/">NVaccess (creators of the NVDA screen reader)</a>, <a href="http://www.w3.org/WAI/">The Web Accessibility Initiative (WAI)</a> and <a href="https://www.bcab.org.uk/">The British Computer Association Of The Blind</a>. Let me know which you prefer in the comments and I'll take it on board.</p> <h2>E-commerce</h2> <p>I'm currently considering <a href="https://selz.com/">selz.com</a> for actually selling the record. I was impressed with the inclusion of focus styles and a &quot;skip to content&quot; link on their homepage. <a href="https://gumroad.com/">Gumroad</a> was lacking in these areas. Other suggestions welcome.</p> <p><span aria-label="devil horns emoticon">\m/</span></p> Heydon Is Dead https://heydonworks.com/article/heydon-is-dead/ 2015-07-15T00:00:00.000Z https://heydonworks.com/article/heydon-is-dead/ <p><em>This post is the first in a two part series examining the senescence and ultimate mortality of this blog's proprietor, Heydon Pickering. This week, guest author <strong>Malcolm Leader-Thought</strong> will make the case that, yes, Heydon Pickering is, in fact, dead; kaput; pushing up the daisies. In the second installment, <strong>Tim Upman-Ship</strong> will argue that, &quot;no, Heydon is not dead, in fact I saw him walking down Bedford Street on Saturday morning. He looked well, actually. I think he's working out.&quot;</em></p> <hr> <p>Have you ever considered the notion that Heydon Pickering might be dead? Probably not — there's no reason why it should occur to you. But now I've brought it up, don't you feel compelled to examine the idea further, if only just to revel in its absurdity? <strong>Yes you do</strong>. I'll be the first to admit it's a controversial argument to make. In fact, it has very little utility other than in creating controversy, driving traffic to its locus of pointless speculation.</p> <p>If you open up your mind and really think about it, this puts a question mark over my use of the word &quot;admit&quot;: It makes it sound like this patently manufactured controversy was an accidental happenstance, which is disingenuous. But it's important to ask questions, and it's a good thing that people like me are brave enough to do so. Try to ignore the fact that I started by making statements and now I'm talking about questions for some reason.</p> <figure> <img src="https://heydonworks.com/images/2015/07/question-mark.gif" alt="A big question mark" width="500" height="700" class="alignnone size-full wp-image-294" style="max-width: 250px"> <figcaption>A question mark, yesterday.</figcaption> </figure> <p>Let's have a list. Do me a favor and pretend that each item in the list is, somehow, supporting evidence that Heydon Pickering is dead, rather than merely a discrete morsel of conjectural drivel.</p> <ul> <li>Heydon hasn't changed his Twitter avatar in over three days</li> <li>I've never met Heydon</li> <li>Heydon hasn't replied to that long, rambling email I sent the other day &mdash; the one filled with vague and nonsensical questions</li> <li>Heydon staggered into the office of my tech startup on Tuesday morning with a pallid complexion and empty eyes, then proceeded to bite 372 grammes of flesh out of my left arse cheek. (This isn't technically true but you can't argue that it <em>couldn't</em> happen, because everything is possible no matter how unlikely. Also, that "372" figure is oddly specific, which must mean something.)</li> </ul> <h2>Stuff moves fast</h2> <p>It was never really about evidence. Well, it was twenty minutes ago when I was making the list you just read, but I've lost confidence in that and I've decided to change tack. Now it's all about getting you on side with sweeping statements and making you feel there's a vague threat of disenfranchisement on the horizon.</p> <p>I mean, what if Heydon Pickering is dead and you're the last person to publicly acknowledge it? Do you really want to be the only person sending Heydon tweets and birthday cards in five or even two year's time? Can you afford the professional and personal embarrassment of being seen to fixate on the deceased? <strong>Of course not</strong>, and I think we can agree that the question of whether Heydon Pickering has demonstrably <em>popped his clogs</em> isn't even a factor here.</p> <p>Don't worry, I can help. Your career is safe in my hands. All you have to do is compose a simple tweet. Just write the word &quot;this&quot; and link to this article. That's it. Look, I've even mocked it up for you:</p> <img src="https://heydonworks.com/images/2015/07/Selection_530-1024x217.png" alt="Tech Crunch linking to this article with the word this" width="640" height="135" class="alignnone size-large wp-image-312"> <p>If you're lucky and you're one of the first to do so, you might even be credited as an early adopter: one of the first people to consider Heydon Pickering no longer a living, breathing mammalian organism. Then when he <em>really</em> dies, you can say you were ahead of the curve.</p> <figure> <img src="https://heydonworks.com/images/2015/07/baton-e1436958235786.jpg" alt="baton" width="600" height="194" class="alignnone size-full wp-image-308"> <figcaption>Is it time to pass on the baton of life? To, like, a child or something?</figcaption> </figure> <h2>Now an interview</h2> <p>In this final section, I'm going to call upon the experience of a person you've never heard of who you suspect is either my colleague or lover.</p> <p><strong>So, Kenneth, is Heydon dead?</strong></p> <p>&quot;That's an important question — a question we all need to ask. And I think the answer is 'it depends'. It depends on whether Heydon is up and about, breathing and talking and generally doing things as a living person might or if he's laying down very still, secreting the scent of necrosis.&quot;</p> <p><strong>Okay, but do you think he will die, if he hasn't already?</strong></p> <p>&quot;I think the writing's on the wall. Heydon Pickering's mortality means he just isn't going to live forever. It might be time to bite the bullet and start working and conversing with younger and fitter people. People who were born after Heydon.&quot;</p> <p><strong>What do you think the future holds?</strong></p> <p>&quot;I think we need to radically rethink the landscape. In fact, I think we need to start thinking in terms of seascapes instead. We've started to invest in lobsters, since they do not show signs of senescence at all; they just keep on growing and getting stronger throughout their lives. They're also much more willing to reproduce than Heydon.&quot;</p> Screen Reader Strategy Survey https://heydonworks.com/article/screen-reader-strategy-survey/ 2015-09-18T00:00:00.000Z https://heydonworks.com/article/screen-reader-strategy-survey/ <p>They say accessibility is about people. Inaccessibility is about people too, of course. In either case, it's people — flesh-and-blood, living, breathing people — that interfaces are built to cater for, successfully or otherwise.</p> <p>What we learn in user research is that people are unpredictable, resistant, hesitant, contrary, determined, inventive and most of all disparate. Yet we spend large amounts of our time as assistive technology testers worrying about the technicalities of which screen reader supports what with which browser on which operating system. We focus on discrete instances of what's broken or unbroken, without considering the people using these technologies regularly and what strategies they employ to solve problems and complete tasks. In short, we don't tend to treat screen reader users like users.</p> <p>Despite having some knowledge of the conventions and controls of NVDA, JAWS et al, my sporadic test usage of screen readers is mere fumbling — fumbling around pages <em>I've</em> built looking for information <em>I</em> already know is there, usually while <em>I'm</em> looking at said pages. This really doesn't tell me a great deal. So, I want to ask any screen reader users reading this to help me and others to fill in some gaps.</p> <p>To follow is a short list of questions that you can fill in at your convenience, leaving out any that aren't applicable or you're not happy answering. I'm not expecting any kind of feedback that can be converted to numbers and metrics, so there'll be no dreaded visualisations; I just want to hear how you go about things. You can send your answers to <a href="mailto:heydon@heydonworks.com">heydon@heydonworks.com</a> and I aim to publish them, respecting your anonymity unless you wish to be cited.</p> <p>Thank you.</p> <p><strong>Edit:</strong> <a href="http://www.heydonworks.com/article/responses-to-the-screen-reader-strategy-survey">Here are the responses!</a>.</p> <ul> <li>When you arrive on a new, unfamiliar web page, for which you have no prior knowledge or expectations, what actions do you perform first?</li> <li>If, while using a web page, you suddenly find yourself lost (or in a place you didn't expect to be) what do you do to get back on track?</li> <li>When it becomes clear that a web page is complex, what do you do to help break down the information?</li> <li>If you know there's some information on a website but you don't know where, what helps you to find it?</li> <li>What's the most difficult part of navigating a web page?</li> <li>What one thing do web designers do in the design of their web pages that makes your life most difficult?</li> <li>Which features or aspects of web pages do you consistently find the most difficult to use and why?</li> </ul> Flexbox Grid Finesse https://heydonworks.com/article/flexbox-grid-finesse/ 2015-12-05T00:00:00.000Z https://heydonworks.com/article/flexbox-grid-finesse/ <p><em>(This post was originally published on Medium, put has a permanent home here.)</em></p> <p>Flexbox&mdash;not to be confused with <a href="https://en.wikipedia.org/wiki/Sex_Box">Sex Box</a>, the British TV show wherein Mariella Frostrup interviews people who&#x2019;ve just had sex in a box&mdash;is the CSS layout toolkit <em>de rigueur</em>. Of all the celebrated features of Flexbox, it is the light work it makes of producing wrappable grids, tolerant of dynamic content, that I think&#x2019;s integral. </p> <p>In this article, I&#x2019;ll cover a few techniques to exploit Flexbox&#x2019;s internal algorithms and design finessed grids intended for changing quantities and dimensions of content.</p> <h2 id="basic-wrapping">Basic wrapping</h2> <pre class="prettyprint"><code class=" hljs css"><span class="hljs-class">.parent</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">display</span>:<span class="hljs-value"> flex</span></span>; <span class="hljs-rule"><span class="hljs-attribute">flex-flow</span>:<span class="hljs-value"> row wrap</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-class">.child</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">flex</span>:<span class="hljs-value"> <span class="hljs-number">1</span> <span class="hljs-number">0</span> <span class="hljs-number">25</span>%</span></span>; <span class="hljs-rule">}</span></span></code></pre> <p>I&#x2019;ve made the <code>.parent</code> a flex container and used the <code>flex-flow</code> shorthand to set the <code>flex-direction</code> to <code>row</code> (i.e. following the horizontal axis) and enabled wrapping. Wrapping operates according to the <code>flex-basis</code> set on children; in this case <code>25%</code>. </p> <p>100 divided by 25 is 4, meaning what we have here is a 4 column grid. Simple stuff, I know. With wrapping on, a new row is begun every time you exceed 4 additional children. The last row is always complete, either because the total is exactly divisible by 4, or because the left over children are &#x201c;grown&#x201d; to share a row&#x2019;s width. The &#x201c;1&#x201d; in <code>flex: 1 0 25%</code> essentially means the ability for children to grow is set to <em>on</em>.</p> <div><img src="https://heydonworks.com/images/2015/12/1.png" alt="A four column grid, without gaps as new items are included." width="799" height="111" class="alignnone size-full wp-image-333"></div> <p>The upshot is that you can employ a grid which &#x201c;tidies&#x201d; itself, distributing children automatically. This is powerful stuff. I can be assured that no matter the number of children currently included, my layout will be acceptable.</p> <h2 id="element-queries">Element queries</h2> <p>I&#x2019;m not the first (I think <a href="https://twitter.com/zomigi">Zoe Gillenwater</a> pointed it out) to notice that Flexbox can be made to employ something akin to &#x201c;element queries&#x201d;; changes in an element&#x2019;s layout based on that element&#x2019;s own dimensions. By incorporating a <code>min-width</code> into the last example, I can trigger elements to grow at this &#x201c;breakpoint&#x201d;. </p> <pre class="prettyprint"><code class=" hljs css"><span class="hljs-class">.parent</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">display</span>:<span class="hljs-value"> flex</span></span>; <span class="hljs-rule"><span class="hljs-attribute">flex-flow</span>:<span class="hljs-value"> row wrap</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-class">.child</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">flex</span>:<span class="hljs-value"> <span class="hljs-number">1</span> <span class="hljs-number">0</span> <span class="hljs-number">25</span>%</span></span>; <span class="hljs-rule"><span class="hljs-attribute">min-width</span>:<span class="hljs-value"> <span class="hljs-number">5</span>em</span></span>; <span class="hljs-rule">}</span></span></code></pre> <p>I have made my grid entirely responsive with just one additional declaration. The number of columns is predicated on the simple axiom that no one column (element) can be fewer than <code>5em</code> in width. Flexbox&#x2019;s <code>grow</code> takes care of expanding children that hit this minimum width, making sure they never get any narrower than this setting. Wrapping takes care of everything else.</p> <div><img src="https://heydonworks.com/images/2015/12/2.png" alt="As the viewport narrows, the grid layout reduces in columns until there is just one column at a 500px viewport width" width="701" height="210" class="alignnone size-full wp-image-334"></div> <h2 id="dealing-with-remainders-of-1">Dealing with remainders of 1</h2> <p>If I have a 4 column grid with 8 children present then I add a child element, that element will constitute the whole of the bottom row. Ideally, I&#x2019;d like to move things around so that this is not the case. By harnessing the ability of my elements to grow and incorporating nome <code>nth-child</code> magic, I can essentially borrow elements from the penultimate row to distribute the elements towards the end of the grid more reasonably. I can also do this without negatively affecting other quantities of elements producing more than a single remainder or no remainder at all.</p> <p>In the following example, I&#x2019;ve adapted the first example in this article.</p> <pre class="prettyprint"><code class=" hljs css"><span class="hljs-class">.parent</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">display</span>:<span class="hljs-value"> flex</span></span>; <span class="hljs-rule"><span class="hljs-attribute">flex-flow</span>:<span class="hljs-value"> row wrap</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-class">.child</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">flex</span>:<span class="hljs-value"> <span class="hljs-number">1</span> <span class="hljs-number">0</span> <span class="hljs-number">25</span>%</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-class">.child</span><span class="hljs-pseudo">:nth-last-child(2)</span><span class="hljs-pseudo">:nth-child(4n)</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">min-width</span>:<span class="hljs-value"> <span class="hljs-number">33</span>%</span></span>; <span class="hljs-rule">}</span></span></code></pre> <p>This selector expression in the last block targets any element that falls in the fourth and final column (<code>4n</code>) which is simultaneously the penultimate element &#x201d;“ that is, the element before the long, single remainder. By bumping this element&#x2019;s width to <code>33%</code>, it&#x2019;s forced down into the final line, leaving the penultimate line with just three elements. </p> <p>The result is the elimination of the single element and a dynamic grid that resolves into a line of 4, then 3, then 2 children when there is a single remainder. No matter how many child elements are present, the grid never ends with a single element row.</p> <div><img src="https://heydonworks.com/images/2015/12/3.png" alt="Before and after: the second example ends with not one element but two on the row, preceded by three children on the penultimate row." width="676" height="171" class="alignnone size-full wp-image-335"></div> <p>Try adding and removing items in <a href="http://codepen.io/heydon/pen/zvNxZN">this codePen demo</a> and experimenting with different numbers of columns. The basic formula for the selector is <code>.child:nth-last-child(2):nth-child([number of columns]n)</code>. The width you set has to be somewhere between the base width and the base width for the grid if it had one less column. So, if there are five columns, the width set in this override should be between 20% and 25%.</p> <h2 id="controlled-chaos">Controlled chaos</h2> <p>In the last example, I singled out a child element based on its index using the algebraic <code>:nth-child</code> and <code>nth-last-child</code>. Because of my Flexbox configuration&#x2019;s insistence of filling the available space according to its element growth and wrapping features, I could do this safe in the knowledge that I would not produce an incomplete, gap-ridden grid.</p> <p>Based on this principle, I can arbitrarily change the widths of any grid children I like. I can get quite expressive with this and build in some algorithmic asymmetry.</p> <pre class="prettyprint"><code class=" hljs css"><span class="hljs-class">.child</span><span class="hljs-pseudo">:nth-child(3n)</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> <span class="hljs-number">33.333</span>%</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-class">.child</span><span class="hljs-pseudo">:nth-child(5n)</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> <span class="hljs-number">50</span>%</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-class">.child</span><span class="hljs-pseudo">:nth-child(7n)</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> <span class="hljs-number">66.666</span>%</span></span>; <span class="hljs-rule">}</span></span></code></pre> <p>By using prime numbers (3, 5 and 7) to augment the child elements&#x2019; width at intervals, any perceived regularity in the layout can be easily diminished. However, the layout never <em>breaks</em> as such thanks to our go-to wrapping and growth settings. Be sure to try out the <a href="http://codepen.io/heydon/pen/GpbQdP">codePen demo</a> for this one and experiment with different, superimposed <code>nth-child</code> intervals.</p> <h2 id="gutter-tactics">Gutter tactics</h2> <p><em>(This is an edit to the original article after <a href="https://medium.com/@StuCoxMedia/how-would-you-suggest-adding-a-gutter-with-this-pattern-6e176fb6b4e9#.2ts42s545">Stu Cox</a> started a discussion about how one might deal with gutters.)</em></p> <p>Gutters are, put simply, the gaps between grid children to space them. I&#x2019;m not absolutely certain what the &#x201c;flexy&#x201d; way to add gutters to any of my described grids would be, but I am aware of one technique which would create gutters that do not break when wrapping produces remainders.</p> <pre class="prettyprint"><code class=" hljs css"><span class="hljs-class">.parent</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">display</span>:<span class="hljs-value"> flex</span></span>; <span class="hljs-rule"><span class="hljs-attribute">flex-flow</span>:<span class="hljs-value"> row wrap</span></span>; <span class="hljs-rule"><span class="hljs-attribute">margin-left</span>:<span class="hljs-value"> -<span class="hljs-number">0.5</span>rem</span></span>; <span class="hljs-rule"><span class="hljs-attribute">margin-right</span>:<span class="hljs-value"> -<span class="hljs-number">0.5</span>rem</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-class">.child</span> <span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">flex</span>:<span class="hljs-value"> <span class="hljs-number">1</span> <span class="hljs-number">0</span> <span class="hljs-number">25</span>%</span></span>; <span class="hljs-rule"><span class="hljs-attribute">box-sizing</span>:<span class="hljs-value"> border-box</span></span>; <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">0</span> <span class="hljs-number">0.5</span>rem <span class="hljs-number">1</span>rem</span></span>; <span class="hljs-rule">}</span></span></code></pre> <p>It is important that I treat each item equally, rather than trying to anticipate things with nth children, because any of my items can potentially grow or wrap. Hence the <code>padding: 0.5rem 1rem</code> on all <code>.child</code> elements. This produces a <code>1rem</code> gutter around each child, no matter how they wrap or grow.</p> <p>All that&#x2019;s left is to compensate for the redundant 0.5rem space for left-most and right-most children, facilitated by the left and right negative margins on the parent (Stu arrived at this notion). Depending on the vertical rhythm of your page, you may want to remove the redundant bottom margin of the last child row too, with margin-bottom: -1rem on the parent too. There is <a href="http://codepen.io/heydon/pen/EVqwOW">a codePen to play with</a>.</p> <h2 id="conclusion">Conclusion</h2> <p>I hope that this short article has given you something to think about regarding the way Flexbox handles and tolerates dynamic content, allowing you to tersely code robust yet expressive layouts. With Flexbox, for the first time, we&#x2019;re afforded something akin to true grid <em>systems</em>; grids which govern themselves, freeing us to focus on content creation and aesthetics.</p> Look At This Shitty Tweet Button https://heydonworks.com/article/look-at-this-shitty-tweet-button/ 2016-02-04T00:00:00.000Z https://heydonworks.com/article/look-at-this-shitty-tweet-button/ <p style="text-align: center;"><a class="twitter-share-button" href="https://twitter.com/share" data-via="heydonworks" data-size="large">Tweet</a> <script>// <![CDATA[ !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs'); // ]]></script></p> Responses To The Screen Reader Strategy Survey https://heydonworks.com/article/responses-to-the-screen-reader-strategy-survey/ 2016-06-30T00:00:00.000Z https://heydonworks.com/article/responses-to-the-screen-reader-strategy-survey/ <p>In September of last year, I decided I wanted to hear stories about how screen reader users access The Web. I suspected, as a sighted web user, I made a lot of incorrect assumptions. Accordingly, <a href="http://www.heydonworks.com/article/screen-reader-strategy-survey">I composed seven questions to find out about strategies for reading and operation</a>.</p> <p>Following are the raw, unedited responses (minus the occasional typo). I don't want to editorialize, but let's just say I learned a <em>lot</em>.</p> <p>(It should be noted that two respondents wanted it to be known that they believed their high level of screen reader expertise was not typical and their 'strategies' unlikely to be representative.)</p> <hr> <h2>Survey responses</h2> <h3>When you arrive on a new, unfamiliar web page, for which you have no prior knowledge or expectations, what actions do you perform first?</h3> <p>&quot;I try to get a general layout of the page by searching for headings and landmarks. If the site is busy and inundated with breadcrumb links and other random cruft not related to the desired content, I use NVDA's skip links command which sometimes helps. I've also seen separators used to break up sections of a page. In short, I use element navigation heavily and scope out a mental visualization of the website's layout.&quot;</p> <p>&quot;The first thing I am most likely to do is use H to navigate by headings or use the tab key to see what links are available or a combination of the two.&quot;</p> <p>&quot;I start by using my down-arrow, if it's a new site to me. If not, I'd start by navigating by headings. And if I were super familiar with it, and I knew an ARIA landmark would get me right where I wanted to be, I'd use that.&quot;</p> <p>&quot;When I first go to a page, my screen reader starts an auto read and I usually stop that and check the headings. However, I never go to a page and have no expectations. I have always landed on a page for a reason, I know what subject it's likely to be about etc. One doesn't just open a browser and say take me to some random page when I haven't searched for something or tried to open something. There is always expectation if that makes sense. As I say, headings are my go to thing for most situations, but on some pages I will know I am looking for something other than just information, so I might know I need to look for form fields etc.&quot;</p> <p>&quot;For general exploration, I'll use landmark navigation or heading navigation to look around. If I'm looking for a search facility, I'll use the screen reader shortcut for moving to the first form field on the page. If I think the thing I'm looking for will be in the header area, I'll use the cursor keys to explore in more detail. If I'm looking for a link I'll call up the links dialogue, possibly taking a guess at first letter navigation to find the one I'm after.I might also search for a particular string on the page if I'm looking for something particular in the content.&quot;</p> <p>&quot;I usually try to find a heading and then go from there. Usually, I do this by pressing the #1 or #2 on the keyboard, since the hope is that a competent web developer coded the site and that headings are where and at the level they should be. If I can’t quickly find a heading, I press H to navigate to any heading. If none exists, I’ll start at the top of the page, press the page-down key to get past all the navigation links, and up/down arrow to find my way to the main information.&quot;</p> <p>&quot;If I'm on the Mac, as I normally am, and the page is an article of some kind, I go into 'reader mode' if I can. If that fails, and sometimes even if it works, headings are my go-to navigation. If the page has no headings, and if Reader didn't work, I'm usually on a page for a specific purpose so I'll use my screen reader's 'find' feature to look for keywords I know have to be there. If that fails, or if I'm somehow on a page for no specific reason, I'll just skim through it line by line or element by element. By that point, especially if I don't find something of interest relatively quickly, I'll abandon the page and seek out my information elsewhere.&quot;</p> <p>&quot;I almost always use heading navigation unless it’s a page I’m very familiar with (for instance a forum thread, where I’ll jump to the table of topics). Failing that, I’ll use the key to jump to non-link text, which often finds the part of the page I’m looking for. Other strategies I regularly employ is finding text on the page or using the reader view in Safari or Firefox.&quot;</p> <p>&quot;I first read the page title, then look for an <code>h1</code>, then a <code>main</code> region.&quot;</p> <p>&quot;First I would look for regions such as nav and main and if no joy then hit the H key to look for headings and then start arrowing down to explore when it looks like I am at a place of interest. If there are no regions or Headings I normally commence swearing.&quot;</p> <p>&quot;That would vary a little depending on the type of site (retail, news, information etc). Generally though, I would hit &quot;h&quot; to jump to the first heading and hopefully get some indication as to whether the site will give me what I want. Depending on how that goes, may continue down the page or go back to the main nav. If there are no formal headings, after muttering darkly I would try going to the top of the page and using &quot;n&quot; to find the first normal (not a link) text. That is the same in Window-Eyes and NVDA.&quot;</p> <p>&quot;Why would users arrive on a page for which they have no prior knowledge or expectations? Unless it’s spam/a popup, they have come there with a purpose, generally from Google. Anyway, users use (1) iterating through the page element by element (whatever their screenreader allows) (2) Ctrl+F find (3) Going back because they can’t find what they want quickly. In WebbIE they can hit Ctrl+K or Control+Down to skip past non-content/to the first meaningful heading. Control+Down was probably better understood by people: down takes me through the page one line at a time, but Control+Down jumps past links and stuff.&quot;</p> <h3>If, while using a web page, you suddenly find yourself lost (or in a place you didn’t expect to be) what do you do to get back on track?</h3> <p>&quot;I search for phrases with NVDA's find function (Firefox's find is not as reliable at shifting NVDA's virtual cursor to the expected point on the page). If the site has a heading I can jump to in order to start interacting with the page again, I will do that and continue my work.&quot;</p> <p>&quot;I will tend to either attempt to go back a page, or I will find a link that should take me to the Home page of the website I am on.&quot;</p> <p>&quot;Start arrowing up and down. Go in/out of forms/browse mode (if I've been put in there without my doing it myself) . The idea is to get out of it to be able to &quot;look around&quot; to figure out what triggered it.&quot;</p> <p>&quot;I check the headings. Headings, having 6 levels, are the best way to structure information, especially as most screen readers let you navigate by any heading or by headings at a specific level.&quot;</p> <p>&quot;Check the page title to determine whether I'm on the page I thought I was. If not, I'll hit the back button since logic suggests I've been taken to a new page. Force a refresh of the virtual buffer (on Windows machines) to check whether content had materialized without my screen reader being aware of it and/or letting me know. Use the cursor keys to quickly explore around my current location, and if that turns up nothing useful I'll use landmark/heading navigation to try and find some familiar point on the page.&quot;</p> <p>&quot;I honestly never really thought about it. Sometimes, if I lose my place, I use the JAWS find feature and type in a word or phrase I remember hearing to try and get myself back there…though this is something I mostly have to use in eBooks.&quot;</p> <p>&quot;I usually remember what I was just reading, so will search for a couple words I remember. Failing that, I'm back to heading navigation, or link navigation if I know there was a specific link around where I'd been.&quot;</p> <p>&quot;I generally repaint the screen and use a screen-reader find function for a word I recently heard to zip straight to the part of the page I want. I lose my place on a page very infrequently, it sometimes happens if I’ve started reading a page on a slow connection so the page reloads when I’m partway through it.&quot;</p> <p>&quot;Usually go to the top of the page and do a screenreader search for the last content I remember.&quot;</p> <p>&quot;Hit Q to navigate to the main region if there is one or use Heading navigation to find where I need to be.&quot;</p> <p>&quot;More dark muttering. Then perhaps try Back or looking for the Home link.&quot;</p> <p>&quot;Hit back, try the next Google result.&quot;</p> <h3>When it becomes clear that a web page is complex, what do you do to help break down the information?</h3> <p>&quot;First, I click my tongue in vexation. Then, I begin scoping the site line by line using the arrow keys. Sometimes all it takes is slowing my TTS rate down and taking in the information slower. I search for patterns, and take notes on whatever I'm researching. (and also on the site layout to reference later).&quot;</p> <p>&quot;I will attempt to navigate by headings to find the relative information on the page that I am looking for.&quot;</p> <p>&quot;Same as for the first question. There's no help for it; it takes time, and people have to read, even if they <em>think</em> they can just use links lists and headings. I never use links lists, by the way -- too much info out of context. But less experienced people do. One of the key issues that folks seem unaware of is that good screen reader training is very much lacking. Those who are <em>doing</em> the training sometimes (often?) don't know very much, so it's no wonder.&quot;</p> <p>&quot;Again, I check through the headings to see where it is most likely to be. I find searches don't often help and other tactics would be used so rarely and dependent upon situation and task.&quot;</p> <p>&quot;Nothing in particular. Possibly a product of being familiar with how web things work, I don't often find pages more/less complex than others. Where the accessibility (rather than the complexity) is atrocious, I've been known to resort to Firebug to figure out what's going on.&quot;</p> <p>&quot;I really use headings a lot. Beyond that, I use the arrow keys almost exclusively. My issue with regions and the like is that they aren’t universally used, so it’s just faster and simpler for me to use what I know will work a majority of the time rather than to try and guess at how accessibly-minded the web developer is.&quot;</p> <p>&quot;Reader mode is, again, my friend here. If the meat of the page is all I want, Reader is perfect. If it doesn't work, or if I need to look at the full page (such as a forum topic), I'll see if portions are separated by headings. If not, I'll see if I can find a pattern, such as each forum reply having the same set of information above it, or each Amazon review containing the same linked text at its start. If I can find something like that, I'll do a text search for some words to jump from section to section, or very quickly arrow along, listening for the repeated information to tell me when I've gotten to a new section. If there are no repeats, and no headings,I'm back to moving through the page item by item, which I'll usually do rather quickly. I don't need all the words, just an idea of what's where.&quot;</p> <p>&quot;That really depends on the structure. If there’s tabular data I use table navigation, otherwise I use end-of-element or move to non-link text keys to maximize my time in the text flow of the page.&quot;</p> <p>&quot;Try to get a sort of outline view using headings and regions.&quot;</p> <p>&quot;'Complex' is a rather broad term. A page may be complex and structurally sound or may include lashings of poorly structured code, image links without alt attributes etc. In general though, I would use various combinations of provided navigation, headings, landmarks and intuition. Sometimes I will change browser and/or screen reader. That can be especially helpful when a site is poorly coded.&quot;</p> <p>&quot;Give up, hit back, try the next Google result.&quot;</p> <h3>If you know there’s some information on a website but you don’t know where, what helps you to find it?</h3> <p>&quot;Most sites have a search function. That combined with find commands, I find things relatively quickly. If those methods don't work, I will Google domain search with specific strings. If I'm really getting annoyed and the website has a site map, I'll sift through it and drink coffee until I find the items I'm looking for. Overall though, finding and search box solves most issues for me.&quot;</p> <p>&quot;I would use the search feature of the website or what I commonly do is Google for the information on the website. Usually, that will bring the information up.&quot;</p> <p>&quot;Using the find feature of the browser to search for words, along with arrowing, using headings, etc., as above.&quot;</p> <p>&quot;This is not a reasonable question. It really depends on the page. I could say non-standard controls, like the menu buttons on Facebook, I could say working out what has changed dynamically if it is not where the focus is, I could say lack of clarity in the design of the page, it not being clear which of two buttons or links to follow as they appear to be similar. You probably need a survey monkey to cover all the possible answers and work out what bugs people rather than this freeform making us try to think lol!&quot;</p> <p>&quot;I usually use Google. The &quot;site:xyz.com keyword&quot; function is almost always more effective than site specific search, wading through the site navigation, or other methods.&quot;</p> <p>&quot;If it’s on the same actual page as I’m on, the JAWS “Find” feature is a wonderful thing. If not, I’ll either use the navigation links at the top of the page and manually search, or I’ll even just pull up Google, type in the website name, and include the keyword. Google seems to be better at finding the relevant info I want rather than using sites’ built-in search features.&quot;</p> <p>&quot;Again, text searching or headings, or both. If I know the information, I'll guess at keywords that are probably in the text I want and do some searches for those. Once that fails, heading navigation is next, followed by the afore mentioned skimming.&quot;</p> <p>&quot;Find on page is useful, for example if reading a news story a keyword in the title often indicates the start of the article body. For navigation on a site rather than a page I look for site maps often (because of that find on page feature) or for very large websites I prefer their search (or using a search engine with a site restrictor).&quot;</p> <p>&quot;The website search, or in desperation the sitemap.&quot;</p> <p>&quot;Bring up the list of links or headings or I use the search function.&quot;</p> <p>&quot;Start off with nav links which, if well named, will often provide clues. If not making any progress, will then try site search. This yields remarkably varying results from one site to another. On some occasions I have more luck searching from Google than from within the site itself. One feature I use extensively is the screen reader's search facility, which is more effective in finding something specific on a web page than using the browser's search. I am amazed at how many screen reader users I have met who are unaware of the facility.&quot;</p> <p>&quot;Try a different Google search. Ask a blind mailing list or sighted friend.&quot;</p> <h3>What’s the most difficult part of navigating a web page?</h3> <p>&quot;Unlabeled elements and sluggishness, navigation being hampered by busy flashy websites. (see below for more)</p> <ol> <li>If the website is heavy, that is, lagging NVDA and the browser, that's very deterring. Developers need to understand usability and information access before painting their sites with weighty animations and banners. There is an elegant balance between efficiency and glitter.</li> <li>Poor presentation of form controls. Example: One line of text is "Please enter your name". Then the fields themselves have "first name" and "last name" in the boxes respectively. Never, ever ever put text inside a field that is expected to be filled out. Mistakes and scrambled text occurs a lot because of this.</li> </ol> <p>Another example is a table with a ton of fields. Edit edit edit checkbox checkbox combo... doesn't help me. Unlabeled controls in general will only discourage me from using your site. And for the sake of sanity, label clickable elements!&quot;</p> <p>&quot;The worst is when there are no headings. Say I am looking at a page containing products of some sort. More often than not, the titles of the products are not headings, and therefore, quickly being able to go through the products is time consuming.&quot;</p> <p>&quot;Web pages aren't nearly the problems they used to be. As I see it, the problems today are with Web app.s and ARIA &quot;gone wild,&quot; (credit the title of one of Jared Smith's presentations) And also, there are often problems with forms, and those can be real showstoppers. I'd say poor forms and web apps are really causing trouble. Think of the kinds of project management/issue trackers you use and how inaccessible they are. Also note that I suspect most normal consumers think of something like the Twitter web site as a page when, of course, it's not really.&quot;</p> <p>&quot;Not design it well. There is no one thing I could pinpoint above other things apart from just poor design. Captchas can be show stoppers, as can unlabelled buttons, no headings or navigation etc. Again, this is a survey monkey job for me.&quot;</p> <p>&quot;Too much clutter. Badly placed content (advertising iframes in the middle of a blog post for example), or just too much extraneous content that has to be navigated around/through in order to get to the proper content of the page — and the more proper semantic markup is missing, the worse this gets.&quot;</p> <p>&quot;Besides content that just isn’t accessible at all no matter what, having no headings is frustrating, and poorly-labeled links also present challenges.&quot;</p> <p>&quot;That can vary, based on the page. Generally, lack of structure, specifically headings, is a huge problem.&quot;</p> <p>&quot;Inconsistency. Sometimes, pages are well structured in terms of headings, paragraphs, lists etc and that’s brilliant, but until all pages are you can’t rely on them for every page. It’s a similar story with landmarks, web-based applications, audio/video players and so on, they’re not used consistently enough around the web to make the access to them uniform.&quot;</p> <p>&quot;Things that happen unexpectedly, such as change of focus.&quot;</p> <p>&quot;Lack of semantic code and uneducated devs.&quot;</p> <p>&quot;That depends very much on the site. Very often, sites that I have trouble with also challenge sighted friends and family. Airline sites, with their convoluted processes for booking and finding relevant information are prime examples. Some web developers labour under the misapprehension that visitors admire their 'sophisticated' presentations when what we really want is to find information and/or complete a transaction quickly and efficiently.&quot;</p> <p>&quot;Finding the content of interest, traditionally. Having the page change as you go along, or in response to changes you make that you then can’t find. Not putting LABEL elements in forms. Missing ALT. Frames.&quot;</p> <h3>What one thing do web designers do in the design of their web pages that makes your life most difficult?</h3> <p>&quot;Improper use of elements or overuse of them. Example: a site that has thirty headings that are a paragraph long, or a blog site that has tables just for articles. They may decorate the page, but couldn't they use a boarder or margin things to get a similar feel? Also, flash. Please terminate every and any use of Flash. It's buggy and slow, and generally unlabeled or invisible. Videos auto-playing is a nightmare to deal with as well.&quot;</p> <p>&quot;Inaccessible CAPTCHAs or audio CAPTCHAs that are hard or almost impossible to understand are the biggest issue.&quot;</p> <p>&quot;I think that it's not just developers. I think it's developers, designers, and folks at higher levels, who over-complicate for <em>everyone</em>, not just for blind folks. The purpose(s) of the site/application get lost in the branding requirements, along with other items that simply <em>must</em> be present (in the minds of corporates). Sometimes, the functionality (reason I came to the site) gets buried, and that's not a dev's fault.&quot;</p> <p>&quot;Forget about keyboard accessibility.&quot;</p> <p>&quot;Web apps are probably the most frustrating, so much so that I just don’t use them because I have no interest in working with half-accessible solutions. My time is valuable, and unless it were for a job (where I would be paid), I have no interest in Google Docs/iCloud etc.&quot;</p> <p>&quot;Again, that depends on the page/site. Lack of structure is one, unlabeled links or text fields is another, and, when looking at pages with code on them, images/screenshots of code instead of text are incredibly annoying.&quot;</p> <p>&quot;Use inappropriate markup. Tables for navigation, lists of items that aren’t in list tags, miss image descriptions or use “image” or “description” in the image description, name iframes or dialogues poorly because they don’t see the name in use or provide plugins (flash, audio, video, menus etc) that aren’t accessible. It all comes back to poorly coded structures on the pages.&quot;</p> <p>&quot;Try to squash a link to everything on the homepage, usually resulting in a badly marked-up carousel.&quot;</p> <p>&quot;Divs and spans with no ARIA for custom elements with no ARIA or incorrect use of ARIA.&quot;</p> <p>&quot;There isn't one thing. As mentioned above, having to hunt for information which should be readily at hand can be very tedious. If one thing does stand out, it is that most sites to which it applies do not have correctly marked up forms. This can turn what should be a straight forward process into a tedium or, in some cases, an impossibility.&quot;</p> <p>&quot;Change it. Users develop strategies. When pages change they must be relearned. When tesco.com got rid of their layout tables – to improve accessibility! – everyone complained: they knew how to find things in the tables (and used table mode in JAWS to navigate them…)&quot;</p> <h3>Which features or aspects of web pages do you consistently find the most difficult to use and why?</h3> <p>&quot;Unsure on this one. Perhaps a page that auto-updates frequently whilst in an edit field? Google Instant, etc. It makes NVDA jump around sometimes.&quot;</p> <p>&quot;The two features I run into often are first, editable fields that try to force me to use the drop down to select the information. Why not just make those true drop downs is beyond me. The Better Business Bureau is doing that quite a bit, and it needs to end. The second thing I run into is Submit buttons that do not work with screen readers turned on when I am trying to send an e-mail through the contact us page on a website.&quot;</p> <p>&quot;Most ARIA-related &quot;features&quot; are difficult to use because they're not coded correctly. And it's long been my contention that even when they are coded correctly, most blind folks have never seen how they're supposed to work correctly, so haven't been taught about how to use them.&quot;</p> <p>&quot;Wow, the breadth of this question just makes my mind go blank. I use so many pages with so much success, but it is generally something different that stops me. Captchas, and asking me why is an insult, try using them blindfold lol, menu buttons that expand or collapse but don't seem to reveal options, who knows what they are actually called, because we get no feedback and have to mess about with different screen reader modes to interact with them, unlabelled buttons as we have to guess what to press, all sorts.&quot;</p> <p>&quot;Often the most simple. Pseudo links and buttons that cannot be focused on or used with a keyboard. Also infographics. Don't get me started! Missing text descriptions in general (short or long).&quot;</p> <p>&quot;Unlabeled or poorly labeled forms, badly designed tables, clickable items that don't appear in link or button navigation, and frames containing ads stuck in the middle of articles all contribute to making sites more difficult to use.&quot;</p> <p>&quot;Elements primarily designed with a mouse in mind. Multi-select lists, roll-over menus and submenus, expandable textboxes, drag and drop items and, of course, flash-based widgets.&quot;</p> <p>&quot;Inaccessible widgets, or select boxes with <code>onchange</code> events.&quot;</p> <p>&quot;Anything with Drag and Drop for obvious reasons. Places where an action causes an update elsewhere that either does not have a live region or does not shift focus and take you there.&quot;</p> <ul> <li>"Poorly structured forms because I have to guess what goes in which field;</li> <li>Image links without alt attributes because I either have to deduce the destination from the garbled text, guess or go elsewhere;</li> <li>almost paradoxically over-use of ARIA roles because this can add to verbosity and even be misleading;</li> <li>Scripting that introduces information that is not reported by the screen reader because it can seem like a link etc has done nothing and this is where ARIA CAN BE USEFUL."</li> </ul> <p>&quot;Change again.&quot;</p> Star Trek TNG: First Impressions https://heydonworks.com/article/star-trek-tng:-first-impressions/ 2016-07-08T00:00:00.000Z https://heydonworks.com/article/star-trek-tng:-first-impressions/ <p><a href="https://en.wikipedia.org/wiki/Star_Trek:_The_Next_Generation">Star Trek: The Next Generation</a> was on TV in the UK when I was a little younger than Wesley Crusher, but I never watched it properly. I've started watching it on Netflix and I'm about twenty episodes into the first season. These are some notes I've made.</p> <hr> <p>The set is very sterile. Reassuringly tidy though. No dashboard dross or the like.</p> <p>I like how the first baddies introduced (the Ferenghi) are described as &quot;capitalists&quot; and therefore evil. They act a bit like the crappier orcs out of LOTR.</p> <p>It's nice how everyone gets on so well with Worf. I expected a little bit more anti-Klingon racial tension, though. Be interesting if it came from Geordie. I like to imagine Worf's sash is from winning a beauty pageant.</p> <p>It occurs to me the Klingons are a bit like the English. Wedded to the past and needlessly combative.</p> <p>Doctor Crusher: Name of a hip-hop producer, face of someone who's very much <em>not</em> a hip-hop producer.</p> <p>The Captain's role is bitter sweet. He's a sort of childless father. Comforting BBC Radio 4 voice.</p> <p>I think Deanna Troi should have a smaller part. <em>Way</em> too much mission-critical stuff depends on her telepathic 'insights'. Doesn't seem like a good protocol. I imagine she was called Diana Troy, then changed her name when she found out she was a telepath. Pretentious.</p> <p>The computer interfaces look to me like they could benefit from some clearer labeling and better differentiated colors.</p> <p>All alien races like shiny clothes. Space is camp AF.</p> <p>Yar is my second favorite after the Captain. I like that the security officer is a woman. Lovely, wispy hair.</p> <p>There's something unseemly about Riker. He constantly looks like he's trying to brave his way through a sex scandal.</p> <p>Wesley gets an inordinate amount of romantic attention. It's a mystery to me how.</p> <p>Data scares the shit out of me. I know he's an android, but I just see a psychopath. I keep expecting him to suddenly and indiscriminately strangle one of the other crew members then tilt his head and say &quot;most curious&quot; when they stop struggling.</p> <p>There are a lot of alien forces which all seem to exist for the sole purpose of creating existential crises.</p> Designer Is Not A Profession https://heydonworks.com/article/designer-is-not-a-profession/ 2016-08-22T00:00:00.000Z https://heydonworks.com/article/designer-is-not-a-profession/ <p>Design is a wonderful thing. It's an integral part of how we work to shape the world around us.</p> <p>But it is not a discrete profession or occupation.</p> <p>We are not divided into designers and people who are not designers.</p> <p>If someone says you don't have the right background, you haven't spoken to or listened to the right people, or you don't have the appropriate skills or experience to be a designer? They are wrong.</p> <p>If someone says particular skills — creative, discursive, technical — preclude you from being a designer and put you in a category outside of design? They are wrong.</p> <p>Design is not in the mastery of any particular medium, skill, piece of software, style, or philosophy.</p> <p>Websites, boats, guns, hats, buildings, events, fonts, and data schemas can all be designed or not designed. But it isn't in hiring a designer that the crucial difference is made.</p> <p>All design consultants can do is encourage <em>you</em> to design. And you should know enough to be doing it already.</p> <p>Designing is deliberating; reasoning; justifying. It is joining up the dots.</p> <p>Designing is what we're doing when we're <em>not</em> doing. It's deciding what's right to do, what the best way to do it is, for who, by who, for how long, and with what. Context, relationships, implications.</p> <p>If you don't do any of this, your work will be horrendous. If you hire someone else to do it for you, it will not be saved. You cannot add design.</p> <p>If you care to think about your work as you work, then you are a designer.</p> <p>Everything else — Javascript, Microsoft Excel, a pencil, Adobe Illustrator, a soldering iron, a coffee machine, MySQL, a pair of knitting needles — is a tool.</p> <p>Designers cannot be identified by their tools because anything can be a designer's tool.</p> <p>That is, so long as it's the right tool for the job.</p> Signs You May Be A Designer, Not Just A Coder https://heydonworks.com/article/signs-you-may-be-a-designer-not-just-a-coder/ 2016-11-03T00:00:00.000Z https://heydonworks.com/article/signs-you-may-be-a-designer-not-just-a-coder/ <ol> <li>You spend more time contemplating and discussing code than you do writing it.</li> <li>You spend more time thinking about how the end product affects users than you do about how pleasurable it is for you to write its code.</li> <li>You think in terms of relationships and systems, not just the thing you're coding up at the time.</li> <li>You choose technologies based on what they can achieve, not how new, trendy, or ergonomic they are.</li> <li>When a bug ticket is given to you, you take the time to consider what its implications are rather than just diving in to write it off your list.</li> <li>You're not happy to add new features just because it gives you something to do.</li> <li>You're not happy being told what to code or how to code it. You think you should be part of that decision making process.</li> <li>You think of code as means to an end. It's a tool for realizing design thinking.</li> </ol> <p>Is this you? Then you are not a coder. You are a designer who is skilled in coding.</p> Working For People https://heydonworks.com/article/working-for-people/ 2016-11-23T00:00:00.000Z https://heydonworks.com/article/working-for-people/ <p>2016 has not been an exemplary year in some ways. What with the anti-intellectualism and fascism and kleptocracy and all. And you know what? I'm not <em>completely</em> convinced everything's going to be okay again when the clock strikes twelve on New Year's Eve.</p> <p>I'm not convinced the far right will develop a sudden fondness for anyone with a better tan than them, doctors and scientists will be respected and revered for actually knowing a thing or two, or Mike Pence's head will spontaneously fall off, exploding in a cloud of rainbow-colored sherbet.</p> <h2>What I'm doing</h2> <p>In the new year, I want to offer my services — at reduced rates <a href="#rates">*</a> — to organizations who are doing good for society in the wake of neoliberalism and under the spectre of fascism; organizations who are trying to make things a bit better for ordinary and vulnerable people.</p> <p>I'm only one person who can only make the tiniest difference and, hey, maybe I'm only doing this to quell my own guilt for having the privilege of being a white, male, english speaker. But anyway.</p> <h3>What I can offer</h3> <ul> <li>Branding (styleguides — including typography, iconography etc. and associated documentation)</li> <li>Pattern libraries (catalogues of attractive and accessible interface components written in HTML, JS, and CSS)</li> <li>Prototyping</li> <li>Accessibility remediation (diagnosis and advice on fixing accessibility and usability issues in your existing interfaces)</li> <li>Copywriting and help with readability</li> <li>Fast, responsive websites</li> <li>Other stuff; just ask</li> </ul> <p>I'm a web designer/developer with 10+ years experience. I have two books published on interface design with Smashing Magazine. The latest, <a href="https://www.smashingmagazine.com/inclusive-design-patterns/">Inclusive Design Patterns</a>, was released just a month ago and is set to sell out before Christmas. I worked as a front-end developer for several years with <a href="https://www.neontribe.co.uk/">Neontribe</a>, helping to design and create applications for folks with disabilities and mental health concerns, as well as for educational projects. I currently work with <a href="https://www.paciellogroup.com/">The Paciello Group</a> who offer expert accessibility guidance to large organizations, mostly in the US. I have spoken (including keynotes) at large conferences in The Netherlands, Sweden, Germany, Romania, and the UK on interface design and web accessibility.</p> <h3>Who I'm offering work to</h3> <ul> <li>Charities and non-profits supporting the vulnerable, disabled, and ethnic minorities</li> <li>Campaign and legal organizations working to protect civil liberties and rights</li> <li>Organizations fighting racism</li> <li>Organizations representing and advocating for the LGBTQ community / communities</li> <li>Advocate organizations for the autistic community where autistic folks actually have an influence in the organization</li> <li>Feminist organizations and organizations supporting women's reproductive rights</li> <li>Organizations offering free education services, especially in politics and critical thinking</li> </ul> <p>One type of organization I will not work for is any organization that uses resources to promote religion. So, for example, I'd be delighted to support the Muslim community but not the spread of Islamic doctrine. Another example would be a Christian organization which includes proselytising in its activities. I am a humanist and want to work with people, including religious individuals, if the cause and focus is to help other human beings in need.</p> <p>I work remotely and I tend to restrict long haul travel for the sake of mental wellbeing and productivity.</p> <h2>Is this you?</h2> <p>Are you someone working for any such described organization? Or do you know someone who is? I'm available by email: <strong>heydon@heydonworks.com</strong>.</p> <ul> <li>Negotiable. My standard corporate rate is not exorbitant already and I am prepared to offer between 33% and 50% reductions. Under some circumstances, free work may be applicable.</li> </ul> The New Linkin Park Album Is Not By Nasum https://heydonworks.com/article/the-new-linkin-park-album-is-not-by-nasum/ 2017-06-24T00:00:00.000Z https://heydonworks.com/article/the-new-linkin-park-album-is-not-by-nasum/ <p>I've just been listening to the new Linkin Park album. The first thing that jumped out at me was that, in keeping with previous Linkin Park albums, it is not in fact an album by Nasum. This appears to have caused disappointment among their audience, and rightly so. In one case, <a href="http://www.nme.com/news/music/linkin-park-jug-thrown-heavy-hellfest-2090797">a fan threw a jug at singer Chester Bennington</a>.</p> <p>A jug.</p> <p>I say threw, but it was more a sort of lacklustre roll — the kind of half-baked act of defiance one might expect to be inspired by Linkin fucking Park.</p> <p>Linkin Park have always been soulless, gutless, wet shit. They are no more a hard-rock-and-metal band than Avril Lavigne. At least Avril (&quot;Avy&quot;, I call her) was able to elicit hatred. So why the sudden consternation about their new record, <em>&quot;One More Light&quot;</em>?</p> <p>Don't get me wrong, it <em>is</em> bilge. I mean, it has a song promisingly titled &quot;Battle Symphony&quot; but which sounds like Katy Perry gently pity-wanking an elderly Jonas brother. But what did anyone expect? When you were listening to all the other Linkin Park records what were you thinking? &quot;2002 projections show that this band of whinging, charmless gimps will be the new Motörhead by 2017.&quot;</p> <p>I'm being disingenuous. I know perfectly well why fans are hypoglycemically lobbing jugs at Linkin Park, and it's all about <strong>the broken pact</strong>. With this record, Linkin Park have welched. From the outset the deal was that they'd ship a few overproduced &quot;heavy&quot; guitars. That way you could fill your boots with insipid whining but pretend you were listening to actual rock and roll music.</p> <p>Distorted guitars can't make music cool, punk, or rebellious on their own and Linkin Park are testament to that. But they seem to make it easier to believe you're not listening to the same generic waffle as everyone else, if that's what you need to believe.</p> <p>Now all the guitars are gone and you're left with the same beige effluent there always was. You either like it or you don't and, if you don't, you wasted the last 15 years not listening to Nasum.</p> aria-label is a xenophobe https://heydonworks.com/article/aria-label-is-a-xenophobe/ 2018-02-01T00:00:00.000Z https://heydonworks.com/article/aria-label-is-a-xenophobe/ <p>Internationalization is a major component of inclusive design. But with automatic translation features provided by Google and Microsoft, it's mercifully simple to support — at least at the most basic level. Just include a default language for the page, like <code>lang=&quot;en&quot;</code>, on the <code>&lt;html&gt;</code> element to give translation services a helping hand.</p> <p>It's amazing how many sites <em>don't</em> do this. I know, because as an accessibility specialist I have to look out for it. If it's not there, there are certain implications for screen readers and their voice profiles.</p> <p>Anyway, services like Google's do most of the heavy lifting by looking for strings and simply translating them. Not as good as a manual translation by a bilingual, human speaker, but surprisingly okay.</p> <p>The only trouble comes with attributes, and determining which provide strings for users, and which programmatic tokens. While you wouldn't want <code>aria-pressed=&quot;true&quot;</code> to be translated to <code>aria-pressed=&quot;vrai&quot;</code>, strings intended for human consumption like the value of an <code>aria-label</code> <em>should</em> be covered.</p> <p>Unfortunately, unlike longstanding attributes marked for assistive technology consumption (<code>alt</code> and <code>title</code> to name a couple), <code>aria-label</code> is ignored by Google's translator. <a href="http://t.co/IKYEbvWi7U">MS Translate</a> has the same issue, <a href="https://twitter.com/FremyCompany/status/957129361106247682">I'm told</a>.</p> <p>So yeah, <code>aria-label</code> kind of refuses to speak other languages (but, in fairness, it's not really <code>aria-label</code>'s fault).</p> <h2>Here are some test cases</h2> <ul> <li><a href="https://s.codepen.io/heydon/debug/rpXWzX">Using <code>alt</code> and <code>title</code> for a submit button/image</a></li> <li><a href="https://s.codepen.io/heydon/debug/xpvERy">Using <code>aria-label</code> for a submit button</a></li> </ul> <p>(English should be listed as a supported language in Chrome, but not French, for these to work.)</p> <h2>Workarounds</h2> <h3>✖️ Not recommended</h3> <p>So, you <em>could</em> use JavaScript to dynamically assign the <code>aria-label</code> based on the page's <code>lang</code>…</p> <pre><code>const labels = { en: 'Submit', fr: 'Soumettre', es: 'Enviar', de: 'Einreichen' }; const lang = document.documentElement.lang; const submit = document.querySelector('[type="submit"]'); submit.setAttribute('aria-label', labels[lang]);</code> </pre> <p>Urgh. That could quickly get unmaintainable when managing a lot of ARIA labels. One thing it does have going for it, though, is more control over the specific translation, so it might be a good way to override automatic translation.</p> <h3>✔️ Recommended</h3> <p>Use <code>aria-labelledby</code>! It refers to an element (which can be hidden if you like) containing a text node, which we know gets translated.</p> <pre><code>&lt;span id="submit-label" hidden>Submit&lt;/span> &lt;button type="submit" aria-labelledby="submit-label">→&lt;/button></code> </pre> <p>See how the <code>#submit-label</code> element is <code>hidden</code>. This means it won't be encountered independently of the button by screen readers but, because of the explicit association, it still announces when the button is focused. Good.</p> <h3>✔️✔️✔️ More Recommended</h3> <p>That last approach is a bit complex and contrived. Why not just have a <a href="https://gist.github.com/marcol/3979586">visually hidden</a> <code>&lt;span&gt;</code> inside the button?</p> <pre><code>&lt;button type="submit"> &lt;span class="visually-hidden">Submit&lt;/span> &lt;span aria-hidden="true">→&lt;/span> &lt;/button></code> </pre> <p>Note the <code>aria-hidden</code>. Now that an ARIA label isn't there to override the &quot;→&quot; text node, this symbol would be read out in screen readers (&quot;right arrow&quot;). Using <code>aria-hidden</code> puts a stop to that.</p> <h3>✔️✔️✔️✔️✔️✔️ GALAXY BRAIN RECOMMENDED</h3> <p>Just use some fucking text. Text that people can see and read and hear in their screen readers all at once. Fucking arrows.</p> Your Tooltips Are Bogus https://heydonworks.com/article/your-tooltips-are-bogus/ 2018-03-21T00:00:00.000Z https://heydonworks.com/article/your-tooltips-are-bogus/ <p>Tooltips are implemented all over the place. Badly. Let me count the ways.</p> <h2>It's attached to a non-interactive element</h2> <p>It's not a tooltip if there's no tool (control, button, whatever). What you're really doing is just hiding content away. Why?</p> <h2>It's attached to a non-interactive element that's focusable</h2> <p>So, at some point, you realize that your faux-tooltip (see above) only works on hover, meaning keyboard users don't have access to it. Accordingly, you add <code>tabindex=&quot;0&quot;</code> to it or turn it into a <code>&lt;button&gt;</code>.</p> <p>You've played yourself. Non-interactive elements (elements that do nothing when you click them) should not be focusable, as per <a href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-focus-order.html">Focus Order, 2.4.3</a>.</p> <p>Even if you consider the showing of the tooltip an interactive 'action', it happening on focus makes little sense, especially to unsighted screen reader users who won't know anything has happened.</p> <h2>It doesn't work by touch</h2> <p>Your tooltip is a tip for an actual tool: good. But it doesn't work by touch because tapping the tool/button/whatever activates it. If the user's lucky, they may see the tooltip briefly before the button's action takes place. By then, it's too late.</p> <p>Yes, this means that most tooltips are just not viable components in 2018. Solve the problem differently.</p> <h2>It does nothing for AT users</h2> <p>Okay, you've decided to make the tooltip click-activated because that works by touch. Of course, now the button can only show a tooltip and do nothing else. Not a problem, if that's all it's for.</p> <p>But! You've also used <code>aria-labelledby</code> or <code>aria-describedby</code> so that screen reader users have access to the tooltip message from the button. Great, but now clicking the button doesn't actually do anything as far as they can tell.</p> <h2>The tooltip contains interactive content</h2> <p>You're thinking of dialogs. Use a dialog.</p> <hr> <p>You probably don't need to use a tooltip, but if you do <a href="https://inclusive-components.design/tooltips-toggletips/">I wrote this to help you go about it in an accessible way</a>.</p> Quick 2018 Review https://heydonworks.com/article/quick-2018-review/ 2018-12-24T00:00:00.000Z https://heydonworks.com/article/quick-2018-review/ <p>Just for the sake of some links for the most part — in case you missed anything.</p> <ul> <li>I helped Bulb make their new, <a href="http://design.bulb.co.uk/#/patterns/styles/colors/README.md">accessible design system</a></li> <li>Inclusive Components went from <a href="https://inclusive-components.design/">blog</a> to <a href="http://book.inclusive-components.design/">book</a></li> <li>I created a <a href="https://mutable.gallery/">customizable generative art gallery</a> with SVG and Vue</li> <li>I learned lots about web components and created a <a href="https://github.com/Heydon/bruck">prototyping tool</a></li> <li>I gave <a href="https://fronteers.nl/congres/2018/speakers#heydon-pickering">my third Fronteers conference talk</a></li> <li>I wrote and produced my first instructional videos, on <a href="https://www.youtube.com/watch?v=k-v7lmmF7kc">CSS custom properties</a> and <a href="https://www.youtube.com/watch?v=eCHt8zsbCT4">CSS shapes</a></li> <li>I wrote about the <a href="https://medium.com/@Heydon/choosing-the-right-javascript-arrow-function-a-guide-5151c5c6b8b6">many JavaScript arrow functions</a></li> <li>I spoke at my second <a href="https://www.meetup.com/London-Accessibility-Meetup/">London Accessibility meetup</a></li> <li>I started working with the BBC to help them rewrite their front-end design patterns</li> <li>I gave the last keynote at the wonderful <a href="http://conf.a11yto.com/">a11yTO conference</a></li> <li>I started a conversation about <a href="https://medium.com/@Heydon/reluctant-gatekeeping-the-problem-with-full-stack-e9ad836570f6">full stack development, sexism, and capitalism</a></li> <li>I went bowling with some Syrian refugees</li> <li>I ran my first workshops, in The Hague and Toronto</li> <li>I had a lot of dark and hopeless days, was visited by the memories of past failures and degradations, and cried in the shower a lot</li> <li>Some stuff I can't remember</li> </ul> Facebook Withdraws React https://heydonworks.com/article/facebook-withdraws-react/ 2019-03-22T00:00:00.000Z https://heydonworks.com/article/facebook-withdraws-react/ <p>It's important you <a href="https://petition.parliament.uk/petitions/241584">sign and share this petition</a>. Right now, it's the closest thing Britain has to averting serious disaster in the next few days. It's really important, unlike the status of a single open source JavaScript project. Thank you.</p> <p><strong><a href="https://petition.parliament.uk/petitions/241584">Revoke Article 50</a></strong></p> Every Layout Is Released: Some Facts https://heydonworks.com/article/every-layout-is-released:-some-facts/ 2019-07-29T00:00:00.000Z https://heydonworks.com/article/every-layout-is-released:-some-facts/ <p>In case you haven't already heard: the <a href="https://every-layout.dev/checkout">full version of <strong>Every Layout</strong></a> is now ready for purchase! You'll find all the information you need on the <a href="https://every-layout.dev/"><strong>Every Layout</strong> site</a>.</p> <p>This post is just an opportunity to tell you that in a different channel (done!) and to share some fun™ facts about how <strong>Every Layout</strong> came together.</p> <ol> <li>Andy and I didn't actually meet IRL (in real life) until after the launch of our product.</li> <li>The site/book includes over 100 diagrams, all in black and white, and created in the superior (free!) SVG editor: <a href="https://inkscape.org/">Inkscape</a>.</li> <li>The weird sounding phrases (&quot;CSS is hard&quot;, &quot;CSS is bad&quot;, &quot;I hate CSS&quot;) from the <a href="https://www.youtube.com/watch?v=rCLO5jRLC3k">trailer video</a> were created using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis">Speech Synthesis API</a> with randomized voice profiles and pitches for each word.</li> <li>Heydon promised to wear a pair of latex crab claws for his <a href="https://vimeo.com/showcase/4673650/video/345905639">Patterns Day talk</a> if the site took more than 5000 subscribers. On the morning of Patterns Day, the subscriber count was 5046. As many have pointed out, the claws—despite coming from the card game You've Got Crabs—are anatomically more similar to those of a lobster.</li> <li>The site, built using <a href="https://www.11ty.io/">Eleventy</a>, uses JSDOM to server-side render the <a href="https://every-layout.dev/layouts/">layout components</a> which, despite being custom elements, are therefore not dependent of JavaScript running in the browser.</li> <li>The book is created by hooking up <a href="https://www.11ty.io/">Eleventy</a> with <a href="https://pandoc.org/">pandoc</a> to produce the EPUB file.</li> <li>We have <a href="https://every-layout.dev/blog/you-pay/">an honour system</a>, according to which you may qualify for a free copy of <strong>Every Layout</strong>. When you buy <strong>Every Layout</strong>, you help us give those who can't afford it free copies. We've given away more than 25 free copies already.</li> <li>At least one person uses the music from the trailer video (composed by Heydon) <a href="https://www.youtube.com/watch?v=rCLO5jRLC3k&lc=Ugx1h_jBIWXsE-o244B4AaABAg">as their alarm clock</a>.</li> <li>The development codename for Every Layout was <em>Robert</em>, which should be pronounced as The Alderman pronounces it on <a href="https://athleticomince.com/">Athletico Mince</a>.</li> </ol>