[Valid RSS] This is a valid RSS feed.


This feed is valid, but interoperability with the widest range of feed readers could be improved by implementing the following recommendations.


  1. <?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
  2. xmlns:content=""
  3. xmlns:wfw=""
  4. xmlns:dc=""
  5. xmlns:atom=""
  6. xmlns:sy=""
  7. xmlns:slash=""
  8. >
  10. <channel>
  11. <title>Thoughts From Eric</title>
  12. <atom:link href=";scope=full" rel="self" type="application/rss+xml" />
  13. <link></link>
  14. <description>Things that Eric A. Meyer, CSS expert, writes about on his personal Web site; it&#039;s largely Web standards and Web technology, but also various bits of culture, politics, personal observations, and other miscellaneous stuff</description>
  15. <lastBuildDate>Wed, 05 Sep 2018 14:59:27 +0000</lastBuildDate>
  16. <language>en-US</language>
  17. <sy:updatePeriod>hourly</sy:updatePeriod>
  18. <sy:updateFrequency>1</sy:updateFrequency>
  19. <item>
  20. <title>Variable Font Support</title>
  21. <link></link>
  22. <comments></comments>
  23. <pubDate>Wed, 05 Sep 2018 14:59:27 +0000</pubDate>
  24. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  25. <category><![CDATA[Browsers]]></category>
  26. <category><![CDATA[CSS]]></category>
  28. <guid isPermaLink="false"></guid>
  29. <description><![CDATA[If you get reports that a font isn’t doing the variable thing you styled, but it’s working fine for you, keep “check their operating system version” on your list of diagnostic tests.]]></description>
  30. <content:encoded><![CDATA[<p>Firefox 62 <a href="">ships today</a>, bringing with it some real CSS goodness.  For one: float shapes!  Which means now, mainline Firefox users will see the text flow past the blender in “<a href="">Handiwork</a>” the same way Chrome users have for a long time now.</p>
  32. <p>But an even bigger addition is support for <a href="">variable fonts</a>.  The ability to have one font file that mathematically describes variants on the base face means that all kinds of fine-grained typography is possible with far less bandwidth overhead and a major reduction in page weight.</p>
  34. <p>However: bear in mind that like Safari, but unlike Chrome, Firefox’s variable-font support is dependent on the operating system on which is runs.  If you have Windows 10, or Max OS X 10.13, then you have variable font support in Firefox and Safari.  Earlier versions of those operating systems don’t support variable fonts, and so Safari and Firefox don’t either.  Chrome rolls its own variable-font support, so it can extend support backwards in the OS timeline.</p>
  36. <p>(I don’t know how things stand in the Linux world.  Hopefully someone can clear things up in the comments!)</p>
  38. <p>I say this not to chastise Firefox (nor Safari), because I tend to think leaning on the OS for this sort of thing is reasonable.  I feel the same way about form elements like <code>&lt;select&gt;</code> dropdowns, to be clear, which I know likely places me in the minority.  The point here is to give you a heads-up: if you get reports that a font isn’t doing the variable thing you styled, but it’s working fine for you, keep “check their operating system version” on your list of diagnostic tests.</p>
  39. ]]></content:encoded>
  40. <wfw:commentRss></wfw:commentRss>
  41. <slash:comments>6</slash:comments>
  42. </item>
  43. <item>
  44. <title>Firefox’s :screenshot command</title>
  45. <link></link>
  46. <comments></comments>
  47. <pubDate>Fri, 24 Aug 2018 14:56:36 +0000</pubDate>
  48. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  49. <category><![CDATA[Browsers]]></category>
  50. <category><![CDATA[Hacks]]></category>
  51. <category><![CDATA[Tools]]></category>
  53. <guid isPermaLink="false"></guid>
  54. <description><![CDATA[An update on the <kbd>:screenshot</kbd> (formerly <kbd>screenshot</kbd>) command in Firefox, which I first wrote about in 2015.]]></description>
  55. <content:encoded><![CDATA[<p>Back in 2015, <a href="">I wrote about Firefox’s <kbd>screenshot</kbd> utility</a>, which used to be a command in the <acronym title="Graphical Command Line Interpreter">GCLI</acronym>.  Well, the GCLI is gone now, but the coders at Mozilla <a href="">have brought command-line screenshotting</a> back with <kbd>:screenshot</kbd>, currently available in Firefox Nightly and Firefox Dev Edition.  It’s available in the Web Console (<kbd>⌥⌘K</kbd> or Tools → Web Developer → Console).</p>
  57. <figure>
  58. <a href=""><img src="" alt="" class="wp-image-4313 framed" srcset=" 640w, 300w" sizes="(max-width: 640px) 100vw, 640px" /></a>
  59. <figcaption>An image I captured by typing <kbd>:screenshot --dpr 0.5</kbd> in the Web Console</figcaption>
  60. </figure>
  62. <p>Once you’re in the Web Console, you can type <kbd>:sc</kbd> and then hit Tab to autocomplete <kbd>:screenshot</kbd>. From there, everything is the same as <a href="">I wrote in 2015</a>, with the exception that the <kbd>--imgur</kbd> and <kbd>--chrome</kbd> options <strong>no longer exist</strong>.  There are plans to add uploading to Firefox Screenshots as a replacement for the old Imgur option, but as of this writing, that’s still in the future.</p>
  64. <p>So the list of <kbd>:screenshot</kbd> options as of late August 2018 is:</p>
  66. <dl class="compact separated">
  67. <dt><kbd>--clipboard</kbd></dt>
  68. <dd>Copies the image to your OS clipboard for pasting into other programs.  Prevents saving to a file unless you use the <kbd>--file</kbd> option to force file-writing.</dd>
  69. <dt><kbd>--delay</kbd></dt>
  70. <dd>The time in seconds to wait before taking the screenshot; handy if you want to pop open a menu or invoke a hover state for the screenshot.  You can use any number, not just integers.</dd>
  71. <dt><kbd>--dpr</kbd></dt>
  72. <dd>The Device Pixel Ratio (DPR) of the captured image.  Values above 1 yield “zoomed-in” images; values below 1 create “zoomed-out“ results.  <a href="">See the original article</a> for more details.</dd>
  73. <dt><kbd>--fullpage</kbd></dt>
  74. <dd>Captures the entire page, not just the portion of the page visible in the browser’s viewport.  For unusually long (or wide) pages, this can cause problems like crashing, not capturing all of the page, or just failing to capture anything at all.</dd>
  75. <dt><kbd>--selector</kbd></dt>
  76. <dd>Accepts a CSS selector and captures only that element and its descendants.</dd>
  77. <dt><kbd>--file</kbd></dt>
  78. <dd>When <kbd>true</kbd>, forces writing of the captured image to a file, even if <kbd>--clipboard</kbd> is also being used.  Setting this to <kbd>false</kbd> doesn’t seem to have any effect.</dd>
  79. <dt><kbd>--filename</kbd></dt>
  80. <dd>Allows you to set a filename rather than accept the default.  Explicitly saying <kbd>--filename</kbd> seems to be optional; I find that writing simply <kbd>:screenshot test</kbd> yields a file called <tt>test.png</tt>, without the need to write <kbd>:screenshot --filename test</kbd>. <acronym title="Your Firefox May Vary">YFFMV</acronym>.</dd>
  81. </dl>
  83. <p>
  84. I do have one warning: if you capture an image to a filename like <tt>test.png</tt>, and then you capture to that same filename, <strong>the new image will overwrite the old image</strong>.  This can bite you if you’re using the up-arrow history scroll to capture images in quick succession, and forget to change the filename for each new capture.  If you don’t supply a filename, then the file’s name uses the pattern of your OS screen capture naming; e.g., <em>Screen Shot 2018-08-23 at 16.44.41.png</em> on my machine.
  85. </p>
  86. <p>
  87. I still use <kbd>:screenshot</kbd> to this day, and I’m very happy to see it restored to the browser—thank you, Mozillans!  You’re the best.
  88. </p>]]></content:encoded>
  89. <wfw:commentRss></wfw:commentRss>
  90. <slash:comments>6</slash:comments>
  91. </item>
  92. <item>
  93. <title>Securing Web Sites Made Them Less Accessible</title>
  94. <link></link>
  95. <comments></comments>
  96. <pubDate>Tue, 07 Aug 2018 14:47:55 +0000</pubDate>
  97. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  98. <category><![CDATA[Accessibility]]></category>
  99. <category><![CDATA[Commentary]]></category>
  100. <category><![CDATA[Web]]></category>
  102. <guid isPermaLink="false"></guid>
  103. <description><![CDATA[In the middle of last month (July 2018), I found myself staring at a projector screen, waiting once again to see if Wikipedia would load.  If I was lucky, the page started rendering 15-20 seconds after I sent the request.  If not, it could be closer to 60 seconds, assuming the browser didn’t just time out on the connection.]]></description>
  104. <content:encoded><![CDATA[<p>In the middle of last month (July 2018), I found myself staring at a projector screen, waiting once again to see if Wikipedia would load.  If I was lucky, the page started rendering 15-20 seconds after I sent the request.  If not, it could be closer to 60 seconds, assuming the browser didn’t just time out on the connection.  I saw a lot of “the server stopped responding” over the course of a few days.</p>
  106. <p>It wasn’t just Wikipedia, either.  CNN International had similar load times.  So did Google’s main search page.  Even this here site, with minimal assets to load, took a minimum of 10 seconds to start rendering.  Usually longer.</p>
  108. <p>In 2018?  Yes.  In rural Uganda, where I was improvising an introduction to web development for a class of vocational students, that’s the reality.  They can have a computer lab full of Dell desktops running Windows or rows of Raspberry Pis running Ubuntu or whatever setup there is, but when satellites in geosynchronous earth orbit are your only source of internet, you wait.  And wait.  And wait.</p>
  110. <p>I want to explain why—and far more importantly, how we’ve made that experience interminably worse and more expensive in the name of our comfort and security.</p>
  112. <p>First, please consider the enormously constrained nature of satellite internet access.  If you’re already familiar with this world, skip ahead a few paragraphs; but if not, permit me a brief description of the challenges.</p>
  114. <p>For geosynchronous-satellite internet access, the speed of light become a factor in ping times: just having the signals propagate through a mixture of vacuum and atmosphere chews up approximately half a second of travel time over roughly 89,000 miles (~152,000km).  If that all that distance were vacuum, your absolute floor for ping latency is about 506 milliseconds.</p>
  116. <p>That’s just the time for the signals to make two round trips to geosynchronous orbit and back.  In reality, there are the times to route the packets on either end, and the re-transmission time at the satellite itself.</p>
  118. <p>But that’s not the real connection killer in most cases: packet loss is.  After all, these packets are going to orbit and back.  Lots of things along those long and lonely signal paths can cause the packets to get dropped.  50% packet loss is not uncommon; 80% is not unexpected.</p>
  120. <p>So, you’re losing half your packets (or more), and the packets that aren’t lost have latency times around two-thirds of a second (or more).  <em>Each.</em></p>
  122. <p>That’s reason enough to set up a local caching server.  Another, even more pressing reason is that pretty much all commercial satellite connections come with data caps.  Where I was, their cap was 50GB/month.  Beyond that, they could either pay overages, or just not have data until the next month.  So if you can locally cache URLs so that they only count against your data usage the first time they’re loaded, you do that.  And someone had, for the school where I was teaching.</p>
  124. <p>But there I stood anyway, hoping my requests to load simple web pages would bear fruit, and I could continue teaching basic web principles to a group of vocational students.  Because Wikipedia wouldn’t cache.  Google wouldn’t cache.  Meyerweb wouldn’t cache.  Almost <em>nothing</em> would cache.</p>
  126. <p>Why?</p>
  128. <p><acronym title="HyperText Transfer Protocol (Secure)">HTTPS</acronym>.</p>
  130. <p>A local caching server, meant to speed up commonly-requested sites and reduce bandwidth usage, is a “man in the middle”.  HTTPS, which by design prevents man-in-the-middle attacks, utterly breaks local caching servers.  So I kept waiting and waiting for remote resources, eating into that month’s data cap with every request.</p>
  132. <p>The drive to force every site on the web to HTTPS has pushed the web further away from the next billion users—not to mention a whole lot of the previous half-billion.  I saw a piece that claimed, “Investing in HTTPS makes it faster, cheaper, and easier for everyone.”  If you define “everyone” as people with gigabit fiber access, sure.  Maybe it’s even true for most of those whose last mile is copper.  But for people beyond the reach of glass and wire, every word of that claim was wrong.</p>
  134. <p>If this is a surprise to you, you’re by no means alone.  I hadn’t heard anything about it, so I asked a number of colleagues if they knew about the problem.  Not only had they not, they all reacted the same way I did: this must not be an actual problem, or we’d have heard about it!  But no.</p>
  136. <p>Can we do anything?  For users of up-to-date browsers, yes: <a href="">service workers</a> create a “good” man in the middle that sidesteps the HTTPS problem, so far as I understand.  So if you’re serving content over HTTPS, creating a service worker should be one of your top priorities right now, even if it’s just to do straightforward local caching and nothing fancier.  I haven’t gotten one up for meyerweb yet, but I will do so very soon.</p>
  138. <p>That’s great for modern browsers, but not everyone has the option to be modern.  Sometimes they’re constrained by old operating systems to run older browsers, ones with no service-worker support: a lab full of Windows XP machines limited to IE8, for example.  Or on even older machines, running Windows 95 or other operating systems of that era.  Those are most likely to be the very people who are in situations where they’re limited to satellite internet or other similarly slow services with unforgiving data caps.  Even in the highly-wired world, you can still find older installs of operating systems and browsers: public libraries, to pick but one example.  Securing the web literally made it less accessible to many, many people around the world.</p>
  140. <p>Beyond deploying service workers and hoping those struggling to bridge the digital divide make it across, I don’t really have a solution here.  I think HTTPS is probably a net positive overall, and I don’t know what we could have done better.  All I know is that I saw, first-hand, the negative externality that was pushed onto people far, far away from our data centers and our thoughts.</p>
  142. <p class="note">My thanks to <a href="" rel="acquaintance">Tim Kadlec</a> and <a href="" rel="acquaintance colleague met">Ethan Marcotte</a> for their feedback and insight while I was drafting this post, and to <a href="" rel="acquaintance colleague met">Lara Hogan</a> and <a href="" rel="friend colleague met">Aaron Gustafson</a> for their early assistance wth my research.</p>]]></content:encoded>
  143. <wfw:commentRss></wfw:commentRss>
  144. <slash:comments>47</slash:comments>
  145. </item>
  146. <item>
  147. <title>The China Anniversary</title>
  148. <link></link>
  149. <comments></comments>
  150. <pubDate>Thu, 19 Jul 2018 18:41:15 +0000</pubDate>
  151. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  152. <category><![CDATA[Personal]]></category>
  154. <guid isPermaLink="false"></guid>
  155. <description><![CDATA[It was twenty years ago today, under the wide-spreading boughs of a tree in the front yard of a house on Long Island, that Kat and I exchanged our wedding vows before a small crowd of friends and family.]]></description>
  156. <content:encoded><![CDATA[<p>It was twenty years ago today, under the wide-spreading boughs of a tree in the front yard of a house on Long Island, that Kat and I exchanged our wedding vows before a small crowd of friends and family.  Immediately after, we all moved to the tent in the back yard to celebrate.</p>
  158. <p>The twentieth anniversary is, <a href="">traditionally</a>, the china anniversary.  Kat’s immediate reaction upon hearing this was that it makes total sense, since by 20 years you’ve probably broken most of your wedding china and need replacements.  For us, though, the resonance is a little different, since our honeymoon was a trip to China.  And therein hangs an origin story.</p>
  160. <p>At some point in the late 1997, Kat and I were at a Meyer family gathering, probably Thanksgiving, at my paternal grandparents’ house in Cincinnati.  As was my wont, I was perusing the stacks of National Geographics they had always lying around.  Not like in a dentist’s office; no, these were always up to date.  But there were always many of them, interleaved with many similarly contemporary Readers’ Digests.</p>
  162. <p>I picked up <a href="">one with a cover shot and title about China’s Three Gorges</a><a href=""><img src="" alt="National Geographic, September 1997 issue" class="pic book cover" style="margin: 0.5em -1em 1em 1.5em" /></a>
  163. , and started leafing through it, eventually reaching the cover story.  It chronicled the incredible landscapes of the Three Gorges of the Yangtze River, soaring cliff faces and ancient villages.  I was immediately captivated by the story and especially the photography.  I decided that I wanted to see the Gorges before they were submerged by the Three Gorges Dam Project, which is the sort of snap decision I almost <em>never</em> make.  Usually I take time to analyze an idea and game out scenarios before reaching a conclusion, but not this time.  I was immediately certain.  I was certain enough to say it out loud to other people, like Kat and my parents and, who knows, probably a bunch of my extended family.</p>
  165. <p>Now, fast forward a bit.  At the end of that same year, Kat and I were with my parents for Christmas.  We went out to dinner at Mom’s favorite spot for her birthday (also <a href="">Boxing Day</a>) and my parents said they had presents for me and my sister.  We each got an envelope.</p>
  167. <p>Both of them contained checks for several thousand dollars, windfall of an inheritance distribution that Mom had insisted be passed on to us.  In mine, with the check, were a number of brochures for tours of China.</p>
  169. <p>I was speechless.  Kat asked what it was a couple of times, a little bewildered by the look on my face.</p>
  171. <p>And here I must take a side trip.  Kat and I had been on a trip to California a few weeks prior, just the two of us.  We spent a couple of nights at <a href="">Ragged Point</a>, a spot I’d stumbled over on a previous solo trip, back in the days when the rooms intentionally had no TVs or phones.  The restaurant was booked by a large group, so we ate dinner alone on the open patio under a heat umbrella, looking at the stars and enjoying the fantastic food; the chef at the time was a genius.  Music played softly through hidden speakers, and although we were literally sitting outside it felt as quiet and private as any candlelit back room.</p>
  173. <p>“<a href="">The Christmas Song</a>”, generally better known as “Chestnuts Roasting on an Open Fire”, started playing.  Kat, smiling, asked me if I would like to dance.  So we stood and danced close together, slowly shuffling around the open space the way untrained dancers do, just us and the song and the stars.</p>
  175. <p>Kat swears I drew breath and opened my mouth to ask her to marry me.  Maybe she’s right.  But I didn’t, then.  Nor the next day.  Nor on Christmas Day.  Which caused Kat to start thinking that maybe it wasn’t going to happen at all.  She was feeling disappointed and hurt by this, as you can probably imagine, but keeping it to herself because she wasn’t sure yet if she was right or wrong.</p>
  177. <p>So: back to Mom’s birthday dinner in Mansfield, Ohio, and me sitting stunned by the check and the China brochures and this unexpected, unprecedented windfall.</p>
  179. <p>“Eric, what is it?” Kat asked again, with some concern starting to color her words.</p>
  181. <p>“We’re going to China!” I finally blurted out.</p>
  183. <p>“No, <em>you’re</em> going to China,” she replied a little tartly.</p>
  185. <p>“No, <em>we’re</em> going to China,” I repeated.</p>
  187. <p>Because in that moment, right there, I knew that this trip I wanted to take, the things I wanted to see so badly before they were gone—I couldn’t imagine doing and seeing all that without Kat.</p>
  189. <p>That’s when I knew, beyond any shadow of a doubt, that I wanted to marry her.<a href=""></a></p>
  191. <p>I didn’t propose that night either, because I had to explain this all to her in halting, still-new words and help her (and me!) understand what had happened.  She got it, as I think I knew she would.  We went shopping for rings just after the New Year.  I formally proposed to her, shivering on an ice-crusted deck by the Chagrin Falls, on her birthday in March.</p>
  193. <figure class="opposite">
  194. <a href=""><img src="" alt="" class="aligncenter size-large wp-image-4266 framed" srcset=" 1024w, 150w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a>
  195. </figure>
  197. <p>And on July 19th, 1998, we stood underneath the spreading boughs of the tree in the front yard of her childhood home, and exchanged our wedding vows.  A short time later, in a backyard tent in the heat of a mid-July afternoon on Long Island, we stood on the compact dance floor and danced to “The Christmas Song”, baffling half the attendees and bemusing the other half.</p>
  199. <p>The next very day, we flew to China, and <a href="">saw so much together</a> over the next seventeen days: the Three Gorges, yes, but much more.  Suzhou, Dazu, and Guilin stand out in particular for being a little more remote and not so overrun by tourists, the kinds of spots we always find inherently more interesting than large cities and glitzed-up, polished destinations.  We still want to go back to <a href="">Guilin</a> some day.</p>
  201. <p>In the two decades since we vowed to love and honor and respect and amuse each other, we’ve had many adventures together.  Some were incredible, some were stressful, and some I would have spared us both.  Picking out a card was difficult, with so many of them written as if 20 years together could never be anything but an unbroken stretch of bliss and good fortune.  We’ve been through too much to respond well to such bromides; we’ve had fortune great and terrible, difficulty and ease, endless joy and boundless grief.</p>
  203. <p>Every one of those days and weeks and months and years, we’ve supported and shared with each other.  Kat’s been so strong, and so selfless, and I’ve tried to be the same for her.  Neither of us did so perfectly, but we always tried—and we always understood when the other had to nurse a weakness, or look inward for a while.  We have always been honest with each other, and accepted each other.  That, more than anything, is what’s allowed us to travel together these two decades and still love each other.</p>
  205. <p>I couldn’t have asked for a better partner in life and death than Kat, and I hope she’s even half as proud of and grateful for me as I am for her.</p>
  207. <p>Happy China Anniversary, my love.</p>
  209. <figure class="standalone">
  210. <a href=""><img src="" alt="" class="aligncenter size-large wp-image-4256" style="width: 70%;" srcset=" 1024w, 300w, 768w, 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /></a>
  211. <figcaption>On a train to Amsterdam, June 2018</figcaption>
  212. </figure>]]></content:encoded>
  213. <wfw:commentRss></wfw:commentRss>
  214. <slash:comments>10</slash:comments>
  215. </item>
  216. <item>
  217. <title>What is the CSS &#8216;ch&#8217; Unit?</title>
  218. <link></link>
  219. <comments></comments>
  220. <pubDate>Thu, 28 Jun 2018 16:15:38 +0000</pubDate>
  221. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  222. <category><![CDATA[CSS]]></category>
  223. <category><![CDATA[Guide]]></category>
  225. <guid isPermaLink="false"></guid>
  226. <description><![CDATA[Is '1ch' in CSS the width of one character?  Well… yes and no.  Mostly no.]]></description>
  227. <content:encoded><![CDATA[<p>I keep seeing authors and speakers refer to the <code>ch</code> unit as meaning “character width”.  This leads to claims that you can “make your content column 60 characters wide for maximum readability” or “size images to be a certain number of characters!”</p>
  229. <p>Well… yes and no.  Specifically, yes if you’re using fixed-width fonts.  Otherwise, mostly no.</p>
  231. <p>This is because, despite what the letters <code>ch</code> might imply, <code>ch</code> units are <em>not</em> “character” units.  They <a href="">are defined as</a>:</p>
  233. <blockquote cite="">
  234. Equal to the used advance measure of the &#8220;0&#8221; (ZERO, U+0030) glyph found in the font used to render it. (The advance measure of a glyph is its advance width or height, whichever is in the inline axis of the element.)
  235. </blockquote>
  237. <p>So however wide the “0” character is in a given typeface, that’s the measure of one <code>ch</code>.  In monospace (fixed-width) fonts, where all characters are the same width, <code>1ch</code> equals one character.  In proportional (variable-width) fonts, any given character could be wider or narrower than the “0” character.</p>
  239. <p>To illustrate this, here are a few example elements which are set to be exactly 20ch wide, and also contain exactly 20 characters.</p>
  241. <style type="text/css">
  242. section#ch-unit {display: flex; flex-wrap: wrap; justify-content: space-between; width: 100%; margin: 1em auto; font-size: smaller;}
  243. section#ch-unit div {line-height: 1.2;}
  244. section#ch-unit div:nth-of-type(1) {font-family: Courier;}
  245. section#ch-unit div:nth-of-type(2) {font-family: Helvetica;}
  246. section#ch-unit div:nth-of-type(3) {font-family: Georgia;}
  247. section#ch-unit span {display: block; width: 20ch; margin: 0.125em 0; background: rgba(255,0,0,0.33); white-space: pre;}
  248. </style>
  249. <section class="example" id="ch-unit">
  250. <div>
  251. <h3>Courier</h3>
  252. <span>Look, 20 characters.</span>
  253. <span>abcdefghijklmnopqrst</span>
  254. <span>12345678901234567890</span>
  255. <span>iiiiiiiiiiiiiiiiiiii</span>
  256. <span>mmmmmmmmmmmmmmmmmmmm</span>
  257. </div>
  258. <div>
  259. <h3>Helvetica</h3>
  260. <span>Look, 20 characters.</span>
  261. <span>abcdefghijklmnopqrst</span>
  262. <span>12345678901234567890</span>
  263. <span>iiiiiiiiiiiiiiiiiiii</span>
  264. <span>mmmmmmmmmmmmmmmmmmmm</span>
  265. </div>
  266. <div>
  267. <h3>Georgia</h3>
  268. <span>Look, 20 characters.</span>
  269. <span>abcdefghijklmnopqrst</span>
  270. <span>12345678901234567890</span>
  271. <span>iiiiiiiiiiiiiiiiiiii</span>
  272. <span>mmmmmmmmmmmmmmmmmmmm</span>
  273. </div>
  274. </section>
  276. <p>It’s probably no surprise that in Courier, all the elements are the exact same width as their text contents.  In Helvetica, by contrast, this is mostly not the case <em>except</em> for numbers, which appear to be fixed-width.  In Georgia, by contrast, none of the text contents fit the boxes, not even the numbers.</p>
  278. <p>What I’ve found through random experimentation is that in proportional typefaces, <code>1ch</code> is <em>usually</em> wider than the average character width, usually by around 20-30%.  But there are at least a few typefaces where the zero symbol is skinny with respect to the other letterforms; in such a case, <code>1ch</code> is narrower than the average character width.  Trajan Pro is one example I found where the zero was a bit narrower than the average, but I’m sure there are others. Conversely, I’m sure there are typefaces with Big Fat Zeroes, in which case the difference between <code>ch</code> and the average character width could be around 50%.</p>
  280. <p>So in general, if you want an 80-character column width and you’re going to use <code>ch</code> to size it, aim for about <code>60ch</code>, unless you’re specifically working with a typeface that has a skinny zero.  And if you’re working with multiple typefaces, say one for headlines and another for body copy, be careful about setting <code>ch</code> measures and thinking they’ll be equivalent between the two fonts.  The odds are very, very high they won’t be.</p>
  282. <p>It would be interesting to see the Working Group take up the idea of average character width as a unit of measure—say, <code>1acw</code> or possibly just <code>1cw</code>—which actually uses all the letterforms in a typeface to calculate an average value.  That would get a lot closer to “make your columns 60 characters wide!” in a lot more cases than <code>ch</code> does now.</p>
  283. ]]></content:encoded>
  284. <wfw:commentRss></wfw:commentRss>
  285. <slash:comments>13</slash:comments>
  286. </item>
  287. <item>
  288. <title>Decimated</title>
  289. <link></link>
  290. <comments></comments>
  291. <pubDate>Thu, 07 Jun 2018 18:29:37 +0000</pubDate>
  292. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  293. <category><![CDATA[Personal]]></category>
  294. <category><![CDATA[Rebecca]]></category>
  296. <guid isPermaLink="false"></guid>
  297. <description><![CDATA[In another timeline, an early alarm woke Kat and me this morning so we could sneak into Rebecca’s room with her siblings and wish her a happy birthday at the moment she turned ten, 7:24am, June 7th, 2018.]]></description>
  298. <content:encoded><![CDATA[<a href=""><img src="" alt="Rebecca blows out the candles on a birthday cake." width="100%" class="aligncenter size-large wp-image-4219" srcset=" 1024w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a>
  300. <p>In another timeline, an early alarm woke Kat and me this morning so we could sneak into Rebecca’s room with her siblings and wish her a happy birthday at the moment she turned ten, 7:24am, June 7th, 2018.</p>
  302. <p>Two digits.  It’s a big milestone, in its way.  Rebecca’s best friend Ruth passed it a few days ago.  Ruth, who she called “Ruthie”.  Who shared all three of her initials, and practically had the same birthday.  Who was the last person to whom Rebecca ever spoke a complete sentence in her full voice, the morning of the day before she died: “Goodbye Ruthie, I love you, MWAH!”</p>
  304. <p>Ruth, who still dreams of Rebecca, happy dreams that make her waking sad.</p>
  306. <p>I have dreams like that too, when I remember them.  I don’t often remember my dreams.  But sometimes, I get to spend a little time with her, free of sorrow, on a nighttime walk or at an amusement park my subconscious constructed out of all the parks we ever took her to.</p>
  308. <p>Kat and Carolyn and Joshua and I went to the grave marker this morning, because Kat works all afternoon into the evening and Joshua has an all-day LEGO and chess camp and Carolyn has friends to see before summer vacation gets crazy.  Because life moves on even when a part of you can’t understand why the sky doesn’t collapse and the world doesn’t crack open and time doesn’t shatter into a million sharded memories.  Classes get taken, grades get graduated, camps get attended, trips get planned, work has to be done.  Each day follows on the one before, pulling you further and further away from the last moments your life was normal.</p>
  310. <p>We stood or sat or huddled around the flecked slate blue granite slab under the gray clouds of morning, emotions flaring and fading, subsumed by a profound sorrow without many tears.  We’re too used to it, now.  The sobs of previous years have given way to a steeled mourning.  Sometimes there is resentment at the stupid blind unfairness of the holes shot through all our hearts, the hole in our lives, and all the things she and we never got to experience.</p>
  312. <p>Her playgroup friends still talk of her with their parents.  Rebecca was a good friend, she was funny, she was fun, she was so nice.  In their way, still trying to come to grips with what happened to her.  To them.</p>
  314. <p>They don’t mention her to us.  Children, trying to protect the grown-ups.</p>
  316. <p>Which makes sense, since they know, now, that sometimes grown-ups can’t protect the children.  Sometimes the killer gets into the house and there is nothing you can do to cast it out.</p>
  318. <p>Sometimes there is nothing anyone can do, except hold the victim’s hand as her life ebbs away, and wish your desperate pleas to take her place had been heard.  That there was something to hear, anything to hear, and accept a frantic parent’s bargain of life for life.</p>
  320. <p>Ten years ago today, Rebecca came into this world.  Four years ago today, she left it.</p>
  322. <p>I can’t remember if I ever told her I would never forget her, or if I was too afraid of frightening her.</p>
  324. <p>I clearly remember when and where she told me, sobbing, knowing she would die, that she would never forget me.</p>
  326. <p>I can still recall the terrified strength in her arms, locked around my neck.</p>
  328. <p>I hope I told her then.</p>
  330. <p>Today she should have been ten.</p>
  331. ]]></content:encoded>
  332. <wfw:commentRss></wfw:commentRss>
  333. <slash:comments>14</slash:comments>
  334. </item>
  335. <item>
  336. <title>Specificity in :not(), :has(), and :matches()</title>
  337. <link></link>
  338. <comments></comments>
  339. <pubDate>Tue, 05 Jun 2018 19:51:00 +0000</pubDate>
  340. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  341. <category><![CDATA[CSS]]></category>
  343. <guid isPermaLink="false"></guid>
  344. <description><![CDATA[Following up on an older post with some new developments in the world of pseudo-classes and specificity.]]></description>
  345. <content:encoded><![CDATA[<p>A few years back, I wrote <a href="">a short post on specificity, element proximity, and the negation pseudo-class</a>.  Everything in it is still accurate and relevant, but I have some updates to share.</p>
  347. <p>First off, I’d like to clarify something that some people may have found confusing.  In that post, I said:</p>
  349. <blockquote cite="">But it turns out that the negation pseudo-class isn’t counted as a pseudo-class.
  350. </blockquote>
  352. <p>That might leave some people with the idea that the entire negation portion of the selector is ignored for the purposes of specificity, especially if you don’t speak spec.</p>
  354. <p>So consider the following:</p>
  356. <pre class="css"><code>div:not(.one) p
  357. </code></pre>
  359. <p>In order from left to right, that’s an element selector (<code>div</code>), a negation pesudo-class (<code>:not</code>) a class selector (<code>.one</code>), and another element selection (<code>p</code>).  Two element selectors and one class selector are counted towards the specificity, yielding a total of <code>0,0,1,2</code>.  That’s the same specificity as <code> p</code>, though the two selectors select <em>very</em> different things.</p>
  361. <p>In Ye Olden Days, that was easy enough to work out, because <code>:not()</code> could only ever contain a simple selector.  Things are looking to get more complicated, however—<code>:not()</code> is set to accept grouped selectors.  So we will at some point be able to say:</p>
  363. <pre class="css"><code>div:not(.one, .two, #navbar) p
  364. </code></pre>
  366. <p>So any <code>p</code> element that is <em>not</em> descended from a <code>div</code> that has a <code>class</code> containing either <code>one</code> or <code>two</code> (or both), or that has an <code>id</code> of <code>navbar</code>, will be selected.</p>
  368. <p>But how do we calculate the specificity of that whole selector?  Just add up all the pieces?  No.  The Working Group recently decided that the specificity contributed from inside a <code>:not()</code> will be equal to the single selector with the highest specificity.  So given <code>div:not(.one, .two, #navbar) p</code>, the <code>#navbar</code> will contribute <code>0,1,0,0</code> to the overall specificity of the selector, yielding a total of <code>0,1,0,2</code>.  The specificities of <code>.one</code> and <code>.two</code> are ignored.</p>
  370. <p>This same approach will be taken with the <code>:has()</code> and <code>:matches()</code> pseudo-classes.  Thus we get the following:</p>
  372. <pre class="css"><code>
  373. :matches(nav, header, footer#pageend) a[href] {color: silver;}  /* 0,1,1,2 */
  374. article:has(a.external, a img)  /* 0,0,1,2 */
  375. input:not([type="radio"], [type="checkbox"])  /* 0,0,1,1 */
  376. </code></pre>
  378. <p>In the first instance, the bits that are added together are <code>footer#pageend</code> and <code>a[href]</code>, so that’s one ID, one attribute, and two elements.  In the second, it’s <code>article</code> and <code>a.external</code> for one class and two elements.  And last, we add up <code>input</code> and either of the <code>[type=""]</code> attribute selectors, since their specificities are equal, which means we add up one attribute and one element.</p>
  380. <p>There is still, so far as I’m aware, no concept of DOM-tree proximity in CSS.  I would still continue to wager that will remain true, though I’d put a fair bit less money down now than I would have six years ago.</p>
  381. ]]></content:encoded>
  382. <wfw:commentRss></wfw:commentRss>
  383. <slash:comments>6</slash:comments>
  384. </item>
  385. <item>
  386. <title>GDPR Compliance Notice</title>
  387. <link></link>
  388. <comments></comments>
  389. <pubDate>Fri, 25 May 2018 04:00:50 +0000</pubDate>
  390. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  391. <category><![CDATA[General]]></category>
  393. <guid isPermaLink="false"></guid>
  394. <description><![CDATA[A statement regarding this web site and the data associated with it as compared to the GDPR.]]></description>
  395. <content:encoded><![CDATA[<p>Hi there!  This is a statement regarding this web site and the data associated with it as compared to the <a href=""><acronym title="General Data Protection Regulation">GDPR</acronym></a>.  You might think this is ridiculous, but as my site is at least somewhat business-related—it promotes my work, invites people to contact me for consulting or speaking engagements, and the like—here we are.</p>
  397. <p>So:</p>
  399. <ul>
  400. <li>Meyerweb does not set any cookies in your browser, nor does it track you.  This has always been the case, except for a brief period in which I enabled Jetpack to do something or other and then later discovered it was pulling in… other things.  I disabled it immediately, and have no intention of ever enabling it again.</li>
  401. <li>Meyerweb’s web host keeps copies of the server’s access logs, which contain the IP address of the device you use to access meyerweb.  It does <em>not</em>, to the best of my knowledge, record any other personally identifying information, unless you hacked your browser’s <a href="">UA string</a> to contain such information.  Then it will be in the server access logs, and probably next to impossible to get out.</li>
  402. <li>As an anti-spam measure, commenters have always been required to supply an email address in order to comment.  Optionally, they may supply a name and URL.  If you have commented in the past, whatever information you provided is still stored in a local database, associated with that comment.  If you wish to have that information removed, <a href="mailto:[email protected]">contact me</a> and I’ll do my best to remove it.  This may also end up with me removing your comment(s), though I will always try to preserve them.</li>
  403. <li>If you have enabled the “email me about followup comments” or “email me about new posts” features of the site, those are managed by  I do not store that information locally, nor do I have access to it in any way.</li>
  404. <li>If you wish to have any personal information about you removed from meyerweb, you can <a href="mailto:[email protected]">always contact me</a>, and I’ll do my best to handle the request as soon as possible.  If you haven’t heard back from me within ten days, please assume the first attempt got spam-canned or buried in the ongoing avalanche that is my inbox, and ping me <a href="">on Twitter</a> about the silence.  Please <em>don’t</em> use Twitter as a method of first contact about this, since we’ll have to take any conversation about personally identifying information off Twitter and into email anyway.</li>
  405. </ul>
  407. <p>And I believe that’s it.  If I missed anything, let me know and I’ll update as needed.</p>
  408. ]]></content:encoded>
  409. <wfw:commentRss></wfw:commentRss>
  410. <slash:comments>4</slash:comments>
  411. </item>
  412. <item>
  413. <title>A St. Baldrick’s Appeal From Joshua</title>
  414. <link></link>
  415. <comments></comments>
  416. <pubDate>Tue, 20 Mar 2018 18:42:35 +0000</pubDate>
  417. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  418. <category><![CDATA[Cancer]]></category>
  419. <category><![CDATA[Joshua]]></category>
  420. <category><![CDATA[Personal]]></category>
  422. <guid isPermaLink="false"></guid>
  423. <description><![CDATA[My son Joshua is shaving his head (and <a href="">raising money</a>) for St. Baldrick’s to fight childhood cancer, and he’d appreciate your support.]]></description>
  424. <content:encoded><![CDATA[<p>In March of 2014, our son Joshua, then a newly-minted three-year-old, shaved his head for <a href="">St. Baldrick’s</a> for the first time, in support of his sister Rebecca, who at the time seemed to be in remission.  This coming Sunday, now <a href="">in support of all St. Baldrick’s beneficiaries</a> and in memory of the sister with whom he shared so much love, he’ll shave his head for the fifth time.  He’s been letting his hair grow out since the start of the year just for this occasion, and he’s already looking forward to 2020, when he will officially become a Knight of the Bald Table—at the age of nine.</p>
  426. <p>As he was last year, Joshua is a member of <a href="">Team Fairfax</a>, representing the elementary school all three of our kids have attended.  This year he was designated a Team Captain despite only being a first-grader.</p>
  428. <p>Joshua surpassed his initial goal and set a new, much more ambitious threshold of $1,200.  As I write this, he’s just over $150 away.  If you can <a href="">help him get over and beyond that line</a>, he—and I—would very much appreciate it.</p>
  429. ]]></content:encoded>
  430. <wfw:commentRss></wfw:commentRss>
  431. <slash:comments>0</slash:comments>
  432. </item>
  433. <item>
  434. <title>Displaying CSS Breakpoint Information with Generated Content</title>
  435. <link></link>
  436. <comments></comments>
  437. <pubDate>Wed, 21 Feb 2018 21:56:03 +0000</pubDate>
  438. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  439. <category><![CDATA[CSS]]></category>
  440. <category><![CDATA[Hacks]]></category>
  442. <guid isPermaLink="false"></guid>
  443. <description><![CDATA[A quick-and-dirty way to keep track of which breakpoint is in force as you test a design’s responsiveness.]]></description>
  444. <content:encoded><![CDATA[<p>In the course of experimenting with an example design for my talks at <a href="">An Event Apart</a> this year, I came up with a way to keep track of which breakpoint was in force as I tested the design’s responsiveness.  I searched the web to see if anyone else had written about this and didn’t come up with any results, so I’ll document it here.  And probably also in the talks.</p>
  446. <p>What I found was that, since I was setting breakpoints in ems instead of pixels, the responsive testing view in browsers didn’t really help, because I can’t maintain realtime mapping in my head from the current pixel value to however many rems it equals.  Since I don’t think the browser has a simple display of that information, I decided I’d do it myself.</p>
  448. <p>It starts with some generated content:</p>
  450. <pre class="css"><code>body::before {content: "default";
  451.    position: fixed; top: 1px; right: 1px; z-index: 100; padding: 1ch;
  452.    background: rgba(0,0,0,0.67); color: rgba(255,255,255,0.75);
  453.    font: bold 0.85rem Lucida Grande, sans-serif;}
  454. </code></pre>
  456. <p>You can of course change these to some other placement and appearance.  You can also attach these styles to the <code>html</code> element, or your page wrapper if you have one, or honestly even the footer of your document—since the <code>position</code> is <code>fixed</code>, it’ll be viewport-relative no matter where it originates.  The real point here is that we’re generating a bit of text we can change at each breakpoint, like so:</p>
  458. <pre class="css"><code>@media (max-width: 38em) {
  459.    body::before {content: "&lt;38em";}
  460.    /* the rest of the breakpoint styles here */
  461. }
  462. @media (max-width: 50em) {
  463.    body::before {content: "&lt;50em";}
  464.    /* the rest of the breakpoint styles here */
  465. }
  466. @media (min-width: 80em) {
  467.    body::before {content: ">80em";}
  468.    /* the rest of the breakpoint styles here */
  469. }
  470. </code></pre>
  472. <p>The labels can be any string you want, so you can use “Narrow”, “Wide”, and so on just as easily as showing the measure in play, as I did.</p>
  474. <p>The downside for me is that we automatically can’t make the labels cumulative in native CSS.  That means the order the <code>@media</code> blocks appear will determine which label is shown, even if multiple blocks are being applied.  As an example, given the styles above, at a width of 25em, the label shown will be <code>&lt;50em</code> even though both the 38em and 50em blocks apply.</p>
  476. <p>There are ways around this, like switching the order of the <code>max-width</code> blocks so the 38em block comes after the 50em block.  Or we could play specificity games:</p>
  478. <pre class="css"><code>@media (max-width: 38em) {
  479.    html body::before {content: "&lt;38em";}
  480.    /* the rest of the breakpoint styles here */
  481. }
  482. @media (max-width: 50em) {
  483.    body::before {content: "&lt;50em";}
  484.    /* the rest of the breakpoint styles here */
  485. }
  486. </code></pre>
  488. <p>That’s not a solution that scales, sadly.  Probably better to sort the <code>max-width</code> media blocks in descending order, if you think you might end up with several.</p>
  490. <p>The upside is that it’s easy to find and remove these lines once the development phase moves to QA.  Even better, before that point, you get a fully customizable in-viewport indication of where you are in the breakpoint stack as you look at the work in progress.  It’s pretty trivial to take this further by also changing the background color of the little box.  Maybe use a green for all the block above the “standard” set, and a red for all those below it.  Or toss in little background image icons of a phone or a desktop, if you have some handy.</p>
  492. <p>So that’s the quick-and-dirty little responsive development hack I came up with this morning.  I hope it’s useful to some of you out there—and, if so, by all means share and enjoy!</p>
  494. <hr />
  496. <p><ins datetime="2018-02-27T17:10:55+00:00" title="27 February 2018">Addendum: Emil Björklund <a href="">proposes a variant approach that uses CSS Custom Properties</a> (aka CSS variables) to implement this technique.</ins></p>]]></content:encoded>
  497. <wfw:commentRss></wfw:commentRss>
  498. <slash:comments>10</slash:comments>
  499. </item>
  500. <item>
  501. <title>“CSS Pocket Reference, 5th Edition” to Production</title>
  502. <link></link>
  503. <comments></comments>
  504. <pubDate>Thu, 15 Feb 2018 17:48:02 +0000</pubDate>
  505. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  506. <category><![CDATA[Books]]></category>
  507. <category><![CDATA[CSS]]></category>
  508. <category><![CDATA[Writing]]></category>
  510. <guid isPermaLink="false"></guid>
  511. <description><![CDATA[Just over an hour before I started writing this post, I handed off <cite>CSS Pocket Reference, 5th Edition</cite> to the Production department at O’Reilly.]]></description>
  512. <content:encoded><![CDATA[<p>Just over an hour before I started writing this post, I handed off <cite>CSS Pocket Reference, 5th Edition</cite> to the Production department at <a href="">O’Reilly</a>.  What that means, practically speaking, is that barring any changes that the editors find need to be made, I’m done.</p>
  514. <p>Besides all the new-new-NEW properties included in this edition (flexbox and grid being just two of the most obvious examples), we put a lot into improving the formatting for this edition.  Previous editions used a more sprawling format that led to the 4th edition getting up to 238 pages, which cast serious shade on the word “Pocket” there in the title.  After all, not all of us live in climates or cultures where 24/7 cargo pants are a viable option.</p>
  516. <p>So with a few ideas from me and several more from the production team, we managed to add in all the new properties and <em>still</em> bring the page count down below 200.  My guess is the final copy will come in about 190 pages, but much will depend on how crazy the indexer gets, and how much the formatting gets changed in the final massaging.</p>
  518. <p>We don’t have a firm release date yet; I’m pulling for April, but it’s really not up to me.  I’ll make announcements via all the usual channels when pre-order is available, and of course when publication day arrives.</p>
  520. <p>For now, for the first time in many years, I don’t have a book project on my to-do list.  I don’t even have a book proposal on my to-do list.  It’s a slightly weird feeling, but not an unwelcome one.  I’ll be putting the extra time into my content for <a href="">An Event Apart</a>: I’m giving a talk this year on <a href="">using the new CSS tools to make our jobs easier</a>, and doing Day Aparts in <a href="">Boston</a> and <a href="">San Francisco</a> where I spend six hours diving deep into guts of stuff like flexbox Grid, writing modes, features queries, and a whole lot more.</p>
  522. <p>So my time will continue to be fully spoken for, is what I’m saying.  It’ll all be fun stuff, though, and it’s hard to ask for more out of my work.</p>
  523. ]]></content:encoded>
  524. <wfw:commentRss></wfw:commentRss>
  525. <slash:comments>0</slash:comments>
  526. </item>
  527. <item>
  528. <title>My Contribution to “Modern Loss”</title>
  529. <link></link>
  530. <comments></comments>
  531. <pubDate>Thu, 25 Jan 2018 15:36:56 +0000</pubDate>
  532. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  533. <category><![CDATA[Books]]></category>
  534. <category><![CDATA[Projects]]></category>
  535. <category><![CDATA[Writing]]></category>
  537. <guid isPermaLink="false"></guid>
  538. <description><![CDATA[A few words about my essay “The Second Third Child”, included in the new book from Modern Loss.]]></description>
  539. <content:encoded><![CDATA[<p><figure> <a href=""><img src="" alt="" width="200" height="300" class="book cover tilt size-medium wp-image-4158" srcset=" 200w, 333w" sizes="(max-width: 200px) 100vw, 200px" /></a> </figure></p>
  541. <blockquote>
  542.   <p>My wife Kat and I tell ourselves we’d love another child for who they are, not for who they replace. We even believe it. But we can’t be sure of it—and that keeps us from shutting our eyes, jumping back into the adoption process, and hoping it will turn out okay. We know all too horribly well that sometimes, it doesn’t.</p>
  543. </blockquote>
  545. <p>That’s the opening of my essay “The Second Third Child”, included in <a href="">the new book from Modern Loss</a> titled <cite>Modern Loss: Candid Conversation About Grief. Beginners Welcome</cite>, published this week.</p>
  547. <p>I’m deeply honored to be one of the 40+ contributors to the book, some of whom you may know—Dresden Dolls co-founder <a href="" rel="acquaintance met">Amanda Palmer</a>, CNN’s <a href="">Brian Stelter</a>, author <a href="">Lucy Kalanithi</a>, <cite>Dear Evan Hansen</cite> director <a href="">Michael Greif</a>, <a href="">Stacy London</a> of <cite>What Not To Wear</cite>—and many of whom you may not, as I will be unknown to the vast majority of the book’s readers. I’ve written articles for Modern Loss in the past, but to be entrusted with a part of their first book was humbling.</p>
  549. <p>Several of the essays in the book are intentionally funny, but mine is not one of them. It’s quiet, reflective, and elegiac in more than one way, but never anything but honest. It appears in the first section of the book, titled “Collateral Damage”.</p>
  551. <p>As <a href="">Stephen Colbert</a> put it: “Talking about loss can feel scary. This book isn’t. It’s about grieving deeply over the long term, and the reassurance that you’re far from broken because of it.” I hope my essay, and the book as a whole, helps readers to come to terms with their own grief, by seeing that they are not alone, and that they did the best they could even if it doesn’t feel that way at all.</p>
  553. <p>All my thanks to <a href="">Rebecca Soffer and Gabrielle Birkner</a> for making me a part of their incredible, inspiring work.</p>
  554. ]]></content:encoded>
  555. <wfw:commentRss></wfw:commentRss>
  556. <slash:comments>2</slash:comments>
  557. </item>
  558. <item>
  559. <title>Headings and Labels</title>
  560. <link></link>
  561. <comments></comments>
  562. <pubDate>Thu, 18 Jan 2018 20:42:00 +0000</pubDate>
  563. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  564. <category><![CDATA[(X)HTML]]></category>
  565. <category><![CDATA[Accessibility]]></category>
  566. <category><![CDATA[Design]]></category>
  567. <category><![CDATA[HTML5]]></category>
  568. <category><![CDATA[Redesign]]></category>
  570. <guid isPermaLink="false"></guid>
  571. <description><![CDATA[Following on my last two posts about accessibility improvements to meyerweb, I’ve made two more adjustments: better heading levels and added ARIA labels.]]></description>
  572. <content:encoded><![CDATA[<p>Following on my last two posts about accessibility improvements to meyerweb, I’ve made two more adjustments: better heading levels and added ARIA labels.</p>
  574. <p>For the heading levels, the problem I face is one familiar to many authors: what makes sense as an <code>&lt;h1&gt;</code> in some situations needs to be an <code>&lt;h2&gt;</code> in others.  The most common example is the titles of blog posts like this one.  On its permalink page, the title of the page is the title of the post.  There, it should be an <code>&lt;h1&gt;</code>.  On archive pages, including the home page of meyerweb, there are a number of posts shown one after the other.  In those situations, each post title should be an <code>&lt;h2&gt;</code>.</p>
  576. <p>Part of the redesign’s changes were to write a single PHP routine that generated posts and their markup, which I could then simply call from wherever.  So I added an optional function parameter that allowed me to indicate the context in which a post was being placed.  It goes something like this:</p>
  578. <pre class="php"><code>&lt;?php blogpostMarkup("archive"); ?&gt;
  579. </code></pre>
  581. <pre class="php"><code>function blogpostMarkup($type = "standalone") {
  582.     if ($type == "archive") $titletag = "h2"; else $titletag = "h1";
  583.     // …markup is all generated here…
  584.     echo $output;
  585. }
  586. </code></pre>
  588. <p>Or code to that effect.  (I did not go copy-paste from my actual code base.)</p>
  590. <p>So now, heading levels are what they should be, at least on most pages (I may have missed updating some of my old static HTML pages; feel free to point them out in the comments if you find one).  As a part of that effort, I removed the <code>&lt;h1&gt;</code> from the masthead except on the home page, being the one place it makes sense to be an <code>&lt;h1&gt;</code>.</p>
  592. <p>As for ARIA labels, that came about due to <a href="">a comment from Phil Kragnes</a> on my last post, where he observed that pages often have multiple elements with a <code>role</code> of <code>navigation</code>.  In order to make things more clear to ARIA users, I took Phil’s suggestion to add <code>aria-label</code> attributes with clarifying values.  So for the page-top skiplinks, I have:</p>
  594. <pre class="html"><code>&lt;nav role="navigation" aria-label="page" id="skiplinks"&gt;
  595. </code></pre>
  597. <p>Similarly, for the site-navigation bar, I have:</p>
  599. <pre class="html"><code>&lt;nav role="navigation" aria-label="site" id="navigate"&gt;
  600. </code></pre>
  602. <p>The idea is that screen readers will say “Page navigation region” and “Site navigation region” rather than just repeating “Navigation region” over and over.</p>
  604. <p>Other than cleaning up individual pages’ heading levels and the occasional custom layout fix (e.g., the <a href="">Color Equivalents Table</a> needed a local widening of the content column’s maximum size), I think the redesign has settled into the “occasional tinkering” phase.  I may do something to spruce up my old Web Review articles (like <a href="">the very first</a>, written when HTML tags were still uppercase!) and I’m thinking about adding subnavigation in certain sections, but otherwise I think this is about it.  Unless I decide to go <em>really</em> over the top and model my <a href="">Tools page</a> after Simon St. Laurent’s <a href="">lovely new Grid design</a>, that is…</p>
  606. <p>Of course, if you see something I overlooked, don’t hesitate to let me know!  I can’t guarantee fast response, but I can always guarantee careful consideration.</p>
  607. ]]></content:encoded>
  608. <wfw:commentRss></wfw:commentRss>
  609. <slash:comments>6</slash:comments>
  610. </item>
  611. <item>
  612. <title>Increasing Accessibility</title>
  613. <link></link>
  614. <comments></comments>
  615. <pubDate>Wed, 10 Jan 2018 21:13:43 +0000</pubDate>
  616. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  617. <category><![CDATA[(X)HTML]]></category>
  618. <category><![CDATA[Accessibility]]></category>
  619. <category><![CDATA[Commentary]]></category>
  620. <category><![CDATA[Design]]></category>
  621. <category><![CDATA[HTML5]]></category>
  622. <category><![CDATA[Redesign]]></category>
  624. <guid isPermaLink="false"></guid>
  625. <description><![CDATA[Thanks to the fantastic comments on <a href="">my previous post</a>, I’ve made some accessibility changes.]]></description>
  626. <content:encoded><![CDATA[<p>Thanks to the fantastic comments on <a href="">my previous post</a>, I’ve made some accessibility improvements.  Chief among them: adding WAI-ARIA <code>role</code> values to various parts of the structure.  These include:</p>
  628. <ul>
  629. <li><code>role="banner"</code> for the site’s masthead</li>
  630. <li><code>role="navigation"</code> added to the navigation links, including subnavigation links like previous/next posts</li>
  631. <li><code>role="main"</code> for the main portion of a page</li>
  632. <li><code>role="complementary"</code> for sidebars in the blog archives</li>
  633. <li><code>role="article"</code> for any blog post, whether there are several on a page or just one</li>
  634. </ul>
  636. <p>In addition, I restored skip links to the masthead of most pages (the rest will get them soon).  The links are revealed on keyboard focus, which I’m not sure I like.  I feel like these aren’t quite where they need to be.  A big limitation is the lack of <code>:matches()</code> (or similar) support in browsers, since I’d love to have any keyboard focus in the masthead <em>or</em> navigation links bring up the skip links, which requires some sort of parent selection.  I may end up using a tiny bit of enhancing Javascript to make the links’ UX more robust in JS situations, but still obviously available if JS fails.  And I may replicate them in the footer, as a way to quickly jump back up the page, especially to the navigation.</p>
  638. <p>Speaking of the navigation links, they’ve been moved in the source order to match their place in the visual layout.  My instincts with regard to source order and layout placement were confirmed to be woefully out of date: the best advice now is to put the markup where the layout calls for the content to be.  If you’re putting navigation links just under the masthead, then put their markup right after the masthead’s markup.  So I did that.</p>
  640. <p>The one thing I didn’t change is heading levels, which suffer all the usual problems.  Right now, the masthead’s “” is always an <code>&lt;h1&gt;</code> and the page title (or blog post titles) are all <code>&lt;h2&gt;</code>.  If I demoted the masthead content to, say, a plain old <code>&lt;div&gt;</code>, and promoted the post headings, then on pages like the home page, there’d be a whole bunch of <code>&lt;h1&gt;</code>s.  I’ve been told that’s a no-no.  If I’m wrong about that, let me know!</p>
  642. <p>There’s still more to do, but I was able to put these into place with no more than a few minutes’ work, and going by what commenters told me, these will help quite a bit.  My thanks to everyone who contributed their insights and expertise!</p>
  643. ]]></content:encoded>
  644. <wfw:commentRss></wfw:commentRss>
  645. <slash:comments>16</slash:comments>
  646. </item>
  647. <item>
  648. <title>How Do I Increase Accessibility?</title>
  649. <link></link>
  650. <comments></comments>
  651. <pubDate>Tue, 09 Jan 2018 01:42:43 +0000</pubDate>
  652. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  653. <category><![CDATA[Accessibility]]></category>
  654. <category><![CDATA[HTML5]]></category>
  655. <category><![CDATA[Questions]]></category>
  656. <category><![CDATA[Standards]]></category>
  658. <guid isPermaLink="false"></guid>
  659. <description><![CDATA[I have an accessibility question.  Okay, it’s a set of questions, but they’re really all facets of the same question.]]></description>
  660. <content:encoded><![CDATA[<p>I have an accessibility question.  Okay, it’s a set of questions, but they’re really all facets of the same question:</p>
  662. <p><em>How do I make my site’s structure the most accessible to the most people?</em></p>
  664. <p>Which sounds a bit broad.  Let me narrow it down.  Here’s the basic layout order of most pages on meyerweb:</p>
  666. <ol>
  667. <li>Masthead</li>
  668. <li>Navigation (in a <code>&lt;nav&gt;</code> element)</li>
  669. <li>Main page content (in a <code>&lt;main&gt;</code> element), occasionally with a sidebar</li>
  670. <li>Footer (in a <code>&lt;footer&gt;</code> element)</li>
  671. </ol>
  673. <p>But this is, at the moment, the source order of those pieces:</p>
  675. <ol>
  676. <li>Masthead</li>
  677. <li>Main page content (in a <code>&lt;main&gt;</code> element), occasionally with a sidebar</li>
  678. <li>Navigation (in a <code>&lt;nav&gt;</code> element)</li>
  679. <li>Footer (in a <code>&lt;footer&gt;</code> element)</li>
  680. </ol>
  682. <p>The difference is the navigation.  I put it later in the source order because I want those using speaking browsers to be able to get the content quickly, without having to tab through the navigation on every page.</p>
  684. <p>But is that actually a concern, given my use of a <code>&lt;main&gt;</code> element for the main content of the page?  And the <code>&lt;nav&gt;</code> and <code>&lt;footer&gt;</code> elements, do those also help with jumping around the page?  If not, what’s the best-practice structural order for those pieces?</p>
  686. <p>If so, does that mean it’s okay to put the navigation back up there in the source order, and stop doing wacky things with the <code>order</code> element to place it visually where it isn’t, structurally?</p>
  688. <p>I have the same questions for those who use keyboard tabbing of the visual layout, not speaking browsers.  What’s the best way to help them?  If it’s <code>tabindex</code>, how should I order the tabbing index?</p>
  690. <p>And in either case, do I need skip links to get people around quickly?  Do I <em>want</em> skip links?  Do my assistive-technology users want skip links?</p>
  692. <p>Maybe the real question is “Given this layout, and my desire to make getting to main content and other pieces of the page as easy as possible for those who rely on assistive technology, how should I structure and annotate the content to raise the fewest barriers for the fewest people?”</p>
  694. <p>Unless, of course, the <em>real</em> question is one I don’t know enough to ask.</p>
  696. <p>Can you help me out, accessibility hivemind?  I’d really appreciate some expert insight.  All my instincts are more than a decade out of date.</p>
  697. ]]></content:encoded>
  698. <wfw:commentRss></wfw:commentRss>
  699. <slash:comments>12</slash:comments>
  700. </item>
  701. </channel>
  702. </rss>
  703. <!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->

If you would like to create a banner that links to this page (i.e. this validation result), do the following:

  1. Download the "valid RSS" banner.

  2. Upload the image to your own server. (This step is important. Please do not link directly to the image on this server.)

  3. Add this HTML to your page (change the image src attribute if necessary):

If you would like to create a text link instead, here is the URL you can use:

Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda