[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>Thu, 07 Jun 2018 21:08:02 +0000</lastBuildDate>
  16. <language>en-US</language>
  17. <sy:updatePeriod>hourly</sy:updatePeriod>
  18. <sy:updateFrequency>1</sy:updateFrequency>
  19. <item>
  20. <title>Decimated</title>
  21. <link></link>
  22. <comments></comments>
  23. <pubDate>Thu, 07 Jun 2018 18:29:37 +0000</pubDate>
  24. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  25. <category><![CDATA[Personal]]></category>
  26. <category><![CDATA[Rebecca]]></category>
  28. <guid isPermaLink="false"></guid>
  29. <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>
  30. <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>
  32. <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>
  34. <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>
  36. <p>Ruth, who still dreams of Rebecca, happy dreams that make her waking sad.</p>
  38. <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>
  40. <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>
  42. <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>
  44. <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>
  46. <p>They don’t mention her to us.  Children, trying to protect the grown-ups.</p>
  48. <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>
  50. <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>
  52. <p>Ten years ago today, Rebecca came into this world.  Four years ago today, she left it.</p>
  54. <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>
  56. <p>I clearly remember when and where she told me, sobbing, knowing she would die, that she would never forget me.</p>
  58. <p>I can still recall the terrified strength in her arms, locked around my neck.</p>
  60. <p>I hope I told her then.</p>
  62. <p>Today she should have been ten.</p>
  63. ]]></content:encoded>
  64. <wfw:commentRss></wfw:commentRss>
  65. <slash:comments>12</slash:comments>
  66. </item>
  67. <item>
  68. <title>Specificity in :not(), :has(), and :matches()</title>
  69. <link></link>
  70. <comments></comments>
  71. <pubDate>Tue, 05 Jun 2018 19:51:00 +0000</pubDate>
  72. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  73. <category><![CDATA[CSS]]></category>
  75. <guid isPermaLink="false"></guid>
  76. <description><![CDATA[Following up on an older post with some new developments in the world of pseudo-classes and specificity.]]></description>
  77. <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>
  79. <p>First off, I’d like to clarify something that some people may have found confusing.  In that post, I said:</p>
  81. <blockquote cite="">But it turns out that the negation pseudo-class isn’t counted as a pseudo-class.
  82. </blockquote>
  84. <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>
  86. <p>So consider the following:</p>
  88. <pre class="css"><code>div:not(.one) p
  89. </code></pre>
  91. <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>
  93. <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>
  95. <pre class="css"><code>div:not(.one, .two, #navbar) p
  96. </code></pre>
  98. <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>
  100. <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>
  102. <p>This same approach will be taken with the <code>:has()</code> and <code>:matches()</code> pseudo-classes.  Thus we get the following:</p>
  104. <pre class="css"><code>
  105. :matches(nav, header, footer#pageend) a[href] {color: silver;}  /* 0,1,1,2 */
  106. article:has(a.external, a img)  /* 0,0,1,2 */
  107. input:not([type="radio"], [type="checkbox"])  /* 0,0,1,1 */
  108. </code></pre>
  110. <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>
  112. <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>
  113. ]]></content:encoded>
  114. <wfw:commentRss></wfw:commentRss>
  115. <slash:comments>4</slash:comments>
  116. </item>
  117. <item>
  118. <title>GDPR Compliance Notice</title>
  119. <link></link>
  120. <comments></comments>
  121. <pubDate>Fri, 25 May 2018 04:00:50 +0000</pubDate>
  122. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  123. <category><![CDATA[General]]></category>
  125. <guid isPermaLink="false"></guid>
  126. <description><![CDATA[A statement regarding this web site and the data associated with it as compared to the GDPR.]]></description>
  127. <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>
  129. <p>So:</p>
  131. <ul>
  132. <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>
  133. <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>
  134. <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>
  135. <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>
  136. <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>
  137. </ul>
  139. <p>And I believe that’s it.  If I missed anything, let me know and I’ll update as needed.</p>
  140. ]]></content:encoded>
  141. <wfw:commentRss></wfw:commentRss>
  142. <slash:comments>3</slash:comments>
  143. </item>
  144. <item>
  145. <title>A St. Baldrick’s Appeal From Joshua</title>
  146. <link></link>
  147. <comments></comments>
  148. <pubDate>Tue, 20 Mar 2018 18:42:35 +0000</pubDate>
  149. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  150. <category><![CDATA[Cancer]]></category>
  151. <category><![CDATA[Joshua]]></category>
  152. <category><![CDATA[Personal]]></category>
  154. <guid isPermaLink="false"></guid>
  155. <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>
  156. <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>
  158. <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>
  160. <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>
  161. ]]></content:encoded>
  162. <wfw:commentRss></wfw:commentRss>
  163. <slash:comments>0</slash:comments>
  164. </item>
  165. <item>
  166. <title>Displaying CSS Breakpoint Information with Generated Content</title>
  167. <link></link>
  168. <comments></comments>
  169. <pubDate>Wed, 21 Feb 2018 21:56:03 +0000</pubDate>
  170. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  171. <category><![CDATA[CSS]]></category>
  172. <category><![CDATA[Hacks]]></category>
  174. <guid isPermaLink="false"></guid>
  175. <description><![CDATA[A quick-and-dirty way to keep track of which breakpoint is in force as you test a design’s responsiveness.]]></description>
  176. <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>
  178. <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>
  180. <p>It starts with some generated content:</p>
  182. <pre class="css"><code>body::before {content: "default";
  183.    position: fixed; top: 1px; right: 1px; z-index: 100; padding: 1ch;
  184.    background: rgba(0,0,0,0.67); color: rgba(255,255,255,0.75);
  185.    font: bold 0.85rem Lucida Grande, sans-serif;}
  186. </code></pre>
  188. <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>
  190. <pre class="css"><code>@media (max-width: 38em) {
  191.    body::before {content: "&lt;38em";}
  192.    /* the rest of the breakpoint styles here */
  193. }
  194. @media (max-width: 50em) {
  195.    body::before {content: "&lt;50em";}
  196.    /* the rest of the breakpoint styles here */
  197. }
  198. @media (min-width: 80em) {
  199.    body::before {content: ">80em";}
  200.    /* the rest of the breakpoint styles here */
  201. }
  202. </code></pre>
  204. <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>
  206. <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>
  208. <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>
  210. <pre class="css"><code>@media (max-width: 38em) {
  211.    html body::before {content: "&lt;38em";}
  212.    /* the rest of the breakpoint styles here */
  213. }
  214. @media (max-width: 50em) {
  215.    body::before {content: "&lt;50em";}
  216.    /* the rest of the breakpoint styles here */
  217. }
  218. </code></pre>
  220. <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>
  222. <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>
  224. <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>
  226. <hr />
  228. <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>
  229. <wfw:commentRss></wfw:commentRss>
  230. <slash:comments>9</slash:comments>
  231. </item>
  232. <item>
  233. <title>“CSS Pocket Reference, 5th Edition” to Production</title>
  234. <link></link>
  235. <comments></comments>
  236. <pubDate>Thu, 15 Feb 2018 17:48:02 +0000</pubDate>
  237. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  238. <category><![CDATA[Books]]></category>
  239. <category><![CDATA[CSS]]></category>
  240. <category><![CDATA[Writing]]></category>
  242. <guid isPermaLink="false"></guid>
  243. <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>
  244. <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>
  246. <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>
  248. <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>
  250. <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>
  252. <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>
  254. <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>
  255. ]]></content:encoded>
  256. <wfw:commentRss></wfw:commentRss>
  257. <slash:comments>0</slash:comments>
  258. </item>
  259. <item>
  260. <title>My Contribution to “Modern Loss”</title>
  261. <link></link>
  262. <comments></comments>
  263. <pubDate>Thu, 25 Jan 2018 15:36:56 +0000</pubDate>
  264. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  265. <category><![CDATA[Books]]></category>
  266. <category><![CDATA[Projects]]></category>
  267. <category><![CDATA[Writing]]></category>
  269. <guid isPermaLink="false"></guid>
  270. <description><![CDATA[A few words about my essay “The Second Third Child”, included in the new book from Modern Loss.]]></description>
  271. <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>
  273. <blockquote>
  274.   <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>
  275. </blockquote>
  277. <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>
  279. <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>
  281. <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>
  283. <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>
  285. <p>All my thanks to <a href="">Rebecca Soffer and Gabrielle Birkner</a> for making me a part of their incredible, inspiring work.</p>
  286. ]]></content:encoded>
  287. <wfw:commentRss></wfw:commentRss>
  288. <slash:comments>2</slash:comments>
  289. </item>
  290. <item>
  291. <title>Headings and Labels</title>
  292. <link></link>
  293. <comments></comments>
  294. <pubDate>Thu, 18 Jan 2018 20:42:00 +0000</pubDate>
  295. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  296. <category><![CDATA[(X)HTML]]></category>
  297. <category><![CDATA[Accessibility]]></category>
  298. <category><![CDATA[Design]]></category>
  299. <category><![CDATA[HTML5]]></category>
  300. <category><![CDATA[Redesign]]></category>
  302. <guid isPermaLink="false"></guid>
  303. <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>
  304. <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>
  306. <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>
  308. <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>
  310. <pre class="php"><code>&lt;?php blogpostMarkup("archive"); ?&gt;
  311. </code></pre>
  313. <pre class="php"><code>function blogpostMarkup($type = "standalone") {
  314.     if ($type == "archive") $titletag = "h2"; else $titletag = "h1";
  315.     // …markup is all generated here…
  316.     echo $output;
  317. }
  318. </code></pre>
  320. <p>Or code to that effect.  (I did not go copy-paste from my actual code base.)</p>
  322. <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>
  324. <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>
  326. <pre class="html"><code>&lt;nav role="navigation" aria-label="page" id="skiplinks"&gt;
  327. </code></pre>
  329. <p>Similarly, for the site-navigation bar, I have:</p>
  331. <pre class="html"><code>&lt;nav role="navigation" aria-label="site" id="navigate"&gt;
  332. </code></pre>
  334. <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>
  336. <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>
  338. <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>
  339. ]]></content:encoded>
  340. <wfw:commentRss></wfw:commentRss>
  341. <slash:comments>6</slash:comments>
  342. </item>
  343. <item>
  344. <title>Increasing Accessibility</title>
  345. <link></link>
  346. <comments></comments>
  347. <pubDate>Wed, 10 Jan 2018 21:13:43 +0000</pubDate>
  348. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  349. <category><![CDATA[(X)HTML]]></category>
  350. <category><![CDATA[Accessibility]]></category>
  351. <category><![CDATA[Commentary]]></category>
  352. <category><![CDATA[Design]]></category>
  353. <category><![CDATA[HTML5]]></category>
  354. <category><![CDATA[Redesign]]></category>
  356. <guid isPermaLink="false"></guid>
  357. <description><![CDATA[Thanks to the fantastic comments on <a href="">my previous post</a>, I’ve made some accessibility changes.]]></description>
  358. <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>
  360. <ul>
  361. <li><code>role="banner"</code> for the site’s masthead</li>
  362. <li><code>role="navigation"</code> added to the navigation links, including subnavigation links like previous/next posts</li>
  363. <li><code>role="main"</code> for the main portion of a page</li>
  364. <li><code>role="complementary"</code> for sidebars in the blog archives</li>
  365. <li><code>role="article"</code> for any blog post, whether there are several on a page or just one</li>
  366. </ul>
  368. <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>
  370. <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>
  372. <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>
  374. <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>
  375. ]]></content:encoded>
  376. <wfw:commentRss></wfw:commentRss>
  377. <slash:comments>16</slash:comments>
  378. </item>
  379. <item>
  380. <title>How Do I Increase Accessibility?</title>
  381. <link></link>
  382. <comments></comments>
  383. <pubDate>Tue, 09 Jan 2018 01:42:43 +0000</pubDate>
  384. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  385. <category><![CDATA[Accessibility]]></category>
  386. <category><![CDATA[HTML5]]></category>
  387. <category><![CDATA[Questions]]></category>
  388. <category><![CDATA[Standards]]></category>
  390. <guid isPermaLink="false"></guid>
  391. <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>
  392. <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>
  394. <p><em>How do I make my site’s structure the most accessible to the most people?</em></p>
  396. <p>Which sounds a bit broad.  Let me narrow it down.  Here’s the basic layout order of most pages on meyerweb:</p>
  398. <ol>
  399. <li>Masthead</li>
  400. <li>Navigation (in a <code>&lt;nav&gt;</code> element)</li>
  401. <li>Main page content (in a <code>&lt;main&gt;</code> element), occasionally with a sidebar</li>
  402. <li>Footer (in a <code>&lt;footer&gt;</code> element)</li>
  403. </ol>
  405. <p>But this is, at the moment, the source order of those pieces:</p>
  407. <ol>
  408. <li>Masthead</li>
  409. <li>Main page content (in a <code>&lt;main&gt;</code> element), occasionally with a sidebar</li>
  410. <li>Navigation (in a <code>&lt;nav&gt;</code> element)</li>
  411. <li>Footer (in a <code>&lt;footer&gt;</code> element)</li>
  412. </ol>
  414. <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>
  416. <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>
  418. <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>
  420. <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>
  422. <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>
  424. <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>
  426. <p>Unless, of course, the <em>real</em> question is one I don’t know enough to ask.</p>
  428. <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>
  429. ]]></content:encoded>
  430. <wfw:commentRss></wfw:commentRss>
  431. <slash:comments>12</slash:comments>
  432. </item>
  433. <item>
  434. <title>The Newwwyear Design</title>
  435. <link></link>
  436. <comments></comments>
  437. <pubDate>Wed, 03 Jan 2018 18:01:53 +0000</pubDate>
  438. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  439. <category><![CDATA[Commentary]]></category>
  440. <category><![CDATA[Design]]></category>
  441. <category><![CDATA[Projects]]></category>
  443. <guid isPermaLink="false"></guid>
  444. <description><![CDATA[Well, here it is—the first new design for meyerweb since February 2005 (yes, almost 13 years).]]></description>
  445. <content:encoded><![CDATA[<p>Well, here it is—the first new design for meyerweb since February 2005 (yes, almost 13 years).  It isn’t 100% complete, since I still want to tweak the navigation and pieces of the footer, but it’s well past the minimum-viable threshold.</p>
  447. <p>My core goal was to make the site, particularly blog posts, more readable and inviting.  I think I achieved that, and I hope you agree.  The design should be more responsive-friendly than before, and I think all my flex and grid uses are progressively enhanced.  I do still need to better optimize my use of images, something I hope to start working on this week.</p>
  449. <p>Things I particularly like about the design, in no particular order:</p>
  451. <ul>
  452. <li>The viewport-height-scaled masthead, using a minimum height of <code>20vh</code>.  Makes it beautifully responsive, always allowing at least 80% of the viewport’s height to be given over to content, without requiring media queries.</li>
  453. <li>The “CSS” and “HTML” side labels I added to properly classed <code>pre</code> elements.  (For an example, see <a href="">this recent post</a>.)</li>
  454. <li>The fading horizontal separators I created with sized linear gradients, to stand in for horizontal rules.  See, for example, between post content and metadata, or underneath the navlinks up top of the page.  I first did this <a href="">over at An Event Apart</a> last year, and liked them a lot.  I may start decorating them further, which multiple backgrounds make easy, but for now I’m sticking with the simple separators.</li>
  455. <li>Using string-based <code>grid-template-areas</code> values to rearrange the footer at mobile sizes, and also to make the rare sidebar-bearing pages (such as those relating to <a href="">S5</a>) more robust.</li>
  456. </ul>
  458. <p>There are (many) other touches throughout, but those are some high points.</p>
  460. <p>As promised, I did livestream most of the process, and archived copies of those streams are <a href=";list=PL22dNRlBicBy6IpKun786rW0veWQyJJkB">available as a YouTube playlist</a> for those who might be interested.  I absolutely acknowledge that for most people, nine hours of screencasting overlaid with rambling monologue would be very much like watching paint dry in a hothouse, but as Abraham Lincoln once said: for those who like this sort of thing, this is the sort of thing they like.</p>
  462. <p>I was surprised to discover how darned easy it is to livestream.  I know we live in an age of digital wonders, but I had somehow gotten it into my head that streaming required dedicated hardware and gigabit upstream connections.  Nope: my five megabit upstream was sufficient to stream my desktop in HD (or close to it) and all I needed to broadcast was encoding software (I used <a href=""><acronym title="Open Broadcaster Software">OBS</acronym></a>) and a private key from YouTube, which was trivial to obtain.  The only hardware I needed was the laptop itself.  Having a <a href="">Røde Podcaster</a> for a microphone was certainly helpful, but I could’ve managed without it.</p>
  464. <p>(I did have a bit of weirdness where OBS stopped recognizing my laptop’s camera after my initial tests, but before I went live, so I wasn’t able to put up a window showing me while I typed.  Not exactly a big loss there.  Otherwise, everything seemed to go just fine.)</p>
  466. <p>My thanks to everyone who hung out in the chat room as I livestreamed.  I loved all the questions and suggestions—some of which made their way into the final design.  And extra thanks to <a href="" rel="friend colleague met">Jen Simmons</a>, who lit the fire that got me moving on this.  I enjoyed the whole process, and it felt like a great way to close the books on 2017.</p>
  467. ]]></content:encoded>
  468. <wfw:commentRss></wfw:commentRss>
  469. <slash:comments>14</slash:comments>
  470. </item>
  471. <item>
  472. <title>A Newwwyear Livestream</title>
  473. <link></link>
  474. <comments></comments>
  475. <pubDate>Tue, 26 Dec 2017 19:14:57 +0000</pubDate>
  476. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  477. <category><![CDATA[Redesign]]></category>
  478. <category><![CDATA[Speaking]]></category>
  480. <guid isPermaLink="false"></guid>
  481. <description><![CDATA[After I <a href="">announced my newwwyear plans</a>, a couple of people pinged me to ask if I’d do a Google Hangout or some such so that people could follow along as I live-redesign meyerweb.  And I thought, what the heck, why not?]]></description>
  482. <content:encoded><![CDATA[<p>
  483. After I <a href="">announced my newwwyear plans</a>, a couple of people pinged me to ask if I’d do a Google Hangout or some such so that people could follow along as I live-redesign meyerweb in production.  And I thought, that sounds like the nerdiest Twitch stream ever, but what the heck, why not?
  484. </p>
  485. <p>
  486. So!  I’m going to livestream at least part of my process <a href="">over on YouTube Live</a>, spread over a few days.  I picked YTL over Twitch because YouTube will archive the streams to my channel, whereas Twitch only holds onto them for 14 days, and one of my weaknesses is that I’m a data hoarder—I hate to throw away <em>anything</em> digital.  So I’ll keep copies on <abbr title="The Cloud">someone else’s computer</abbr>.
  487. </p>
  488. <p>
  489. During the stream, I’ll keep up a running commentary on what I’m doing and why.  This sounds artificial, but honestly, I talk to myself a lot as I work anyway.  I’ll also have the YouTube Live chat window open so people can ask questions about why I do what I do, and I’ll do my best to answer.  Or, you know, we can talk about the latest Star Wars movie or whatever.  I’m not going to put too many limits on it other than A) keep the language professional, since kids starting out in web design might join in; and B) treat everyone in the chat with respect.
  490. </p>
  491. <p>
  492. My guess is any given stream session will be two hours, tops.  My <strong>tentative</strong> schedule is:
  493. </p>
  494. <ol>
  495. <li>December 26th (today!) starting around 2000 UTC (3:00pm EST, 12:00n PST)</li>
  496. <li>December 27th, 1830 UTC (1:30pm EST, 10:30am PST)</li>
  497. <li>December 28th, <del datetime="2017-12-26T19:20:51+00:00">1900 UTC (2:00pm EST, 11:00am PST)</del><ins datetime="2017-12-26T19:20:51+00:00">1500 UTC (10:00am EST, 7:00am PST)</ins></li>
  498. <li>December 29th, 1500 UTC (10:00am EST, 7:00am PST)</li>
  499. </ol>
  500. <p>
  501. I don’t have a specific structure for how I’m going to approach this, other than: first I turn off all site-wide styling and put up a note about it, maybe add a few very minimal styles, rework the page structures to be sane without CSS, then start building up a new design.  I have no idea how long each part of that sequence will take (except the “remove site-wide styles” part, that’ll take a few seconds).  But there isn’t a scheduled “Typography Day” or what-have-you: I’ll probably go wandering off on tangents, riffing on happy accidents, fiddling with stuff as I notice it and it bugs me, etc., etc.  In other words, how I normally work.
  502. </p>
  503. <p>
  504. If any of this sounds interesting to you, please join in!  I’ll do my best to announce start times with an hour or so lead over on Twitter, and as comments on this post.</p>
  505. ]]></content:encoded>
  506. <wfw:commentRss></wfw:commentRss>
  507. <slash:comments>3</slash:comments>
  508. </item>
  509. <item>
  510. <title>A Meyerweb Makeover</title>
  511. <link></link>
  512. <comments></comments>
  513. <pubDate>Sat, 23 Dec 2017 14:25:50 +0000</pubDate>
  514. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  515. <category><![CDATA[Design]]></category>
  516. <category><![CDATA[Projects]]></category>
  517. <category><![CDATA[Redesign]]></category>
  518. <category><![CDATA[newwwyear]]></category>
  520. <guid isPermaLink="false"></guid>
  521. <description><![CDATA[This coming week, I’m going to redesign—which will be its first redesign in twelve and a half years.]]></description>
  522. <content:encoded><![CDATA[<p>This coming week, I’m going to redesign—which will be its first redesign in twelve and a half years.</p>
  524. <p>I’m doing this as part of <a href="">Jen Simmons</a>’ <a href="">#newwwyear</a> initiative.  As Jen put it:</p>
  526. <blockquote cite="">
  527. <p>Ok, here’s the deal. Tweet your personal website plan with the hashtag <a href="">#newwwyear</a> (thanks <a href="">@jamiemchale</a>!): 1) When will you start? 2) What will you try to accomplish? 3) When is your deadline? Improve an existing site. Start a new one. Burn one down &amp; start over. It’s up to you.</p>
  528. </blockquote>
  529. <blockquote cite="">
  530. <p>Many of us feel bad about our personal websites. Me included. We keep meaning to make one, improve what&#8217;s there, or burn it down and start over. We are busy. Afraid. Overwhelmed. Well, let&#8217;s do it. Maybe over the holidays. Maybe after, in the New Year. <a href="">#newwwyear</a></p>
  531. </blockquote>
  533. <p>On Friday, I announced my plan:</p>
  535. <ol>
  536. <li>I’ll start Wednesday, December 27th.</li>
  537. <li>I’ll redesign  for the first time in a dozen years, and I’ll do it live on the production site.</li>
  538. <li>My deadline is Wednesday, January 3rd, so I’ll have a week.</li>
  539. </ol>
  541. <p>I won’t be redesigning all day every day—I still have paying work to do, after all—but I’ll do my best to put in a couple of hours each weekday.</p>
  543. <p>When say I’ll do it live, I mean I’ll be making all my changes here on the production site, with minimal or no testing beforehand—literally opening the style sheet(s) into <a href="">BBEdit</a> via <a href="">Transmit</a>, and saving changes up to the server to see what happens.  Stuff will break, and then I’ll fix it, live in the public eye.  It’s possible I’ll try out new ideas and then junk them before moving on to others.  I’m hoping that accidents spark inspiration, as they often do.</p>
  545. <p>(There will be a local copy of the site in case things go so badly that I need to reset to the starting point.  I’m not <em>completely</em> insane, after all.)</p>
  547. <p>I have a vague plan with all this, which is: realign the site’s appearance to be more inviting, more readable, and more visually engaging.  I do have a few past experiments that I’ll fold in, like using relative times (e.g., “Two months ago”) on posts, but a lot of this will be me doing free-association design.  And hopefully a little markup cleanup and enhancement as well.</p>
  549. <p>I’m sticking with WordPress to drive the blog, given that it contains close to two decades of posts and makes it easy to allow comments, a feature I still value; and my hand-built old-school-standards-punk mostly-static templating system for the rest of the site, which let the site be static(ish) way before static was cool.  (No, I will <em>not</em> consider migrating to other CMSes or template systems: with a week set aside for this, I won’t have the time.)</p>
  551. <p>So, that’s the plan: a week for a meyerweb makeover.  I don’t know if I’ll keep up a running commentary <a href="">on Twitter</a> while I do, or if I’ll take breaks and blog short entries chronicling my progress, or what.  If someone sets up a #newwwyear Slack team, I’ll probably join in.  If the #newwwyear idea excites you, I hope you’ll join in too!</p>
  552. ]]></content:encoded>
  553. <wfw:commentRss></wfw:commentRss>
  554. <slash:comments>2</slash:comments>
  555. </item>
  556. <item>
  557. <title>Book Review: “Create with Code: Build Your Own Website”</title>
  558. <link></link>
  559. <comments></comments>
  560. <pubDate>Sun, 03 Dec 2017 15:51:12 +0000</pubDate>
  561. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  562. <category><![CDATA[Books]]></category>
  563. <category><![CDATA[Commentary]]></category>
  565. <guid isPermaLink="false"></guid>
  566. <description><![CDATA[A review of an introduction-to-web-design book that’s one of the best I’ve seen, <a href=""><cite>Create with Code: Build Your Own Website</cite></a>, written by <a href="">Clyde Hatter</a> of <a href="">CoderDojo</a>’s Dojo Bray in Ireland.]]></description>
  567. <content:encoded><![CDATA[<p>A thing people ask me with some regularity is, “What’s a good book for someone who wants to get started in web design?”  I’m here to review a book that’s one of the best I’ve seen, <a href=""><cite>Create with Code: Build Your Own Website</cite></a>, written by <a href="">Clyde Hatter</a> of <a href="">CoderDojo</a>’s Dojo Bray in Ireland.  I got my copy at my son’s elementary school Scholastic Book Fair earlier this year; it’s available from online booksellers and probably through local bookstores as well.</p>
  569. <figure style="margin-right: -1em;">
  570. <a href=""><img src="" alt="" width="232" height="300" class="book cover alignnone size-medium wp-image-4170" srcset=" 232w, 768w, 793w, 880w" sizes="(max-width: 232px) 100vw, 232px" /></a>
  571. </figure>
  573. <p>I’ll go into some details of what’s in it and what I think, and there will be some complaints.  So I want to stress up front: <em>this is an excellent book for people who want to learn web design</em>, with the modifier <em>if you’re available to help them out when they hit stumbling blocks</em>.  You aren’t going to have to hold their hands through the whole thing by any stretch, but there are moments where, for example, the filenames used in the text will mislead.  (More on that anon.)  For all that, it’s still an excellent book, and <strong>I recommend it.</strong></p>
  575. <p>The book is 94 pages, of which 88 pages are instructional, and none of it is filler—Mr. Hatter packs a surprising amount of good web design practice into those 88 pages.  The pages themselves are filled with colorful design, and the text is easily readable.  It’s aimed squarely at elementary-school readers, and it shows.  That’s a good thing, I hasten to add.  The tone is simple, uncomplicated, and stripped to the essentials.  At no point does it condescend.  It works well for any age, not just the suggested range of 7-17.  I enjoyed reading it, even though I knew literally everything the book covers.</p>
  577. <p>The organizing idea of the book is creating a small web site for a ninja band (!!!) called The Nanonauts.  In the course of the book, the reader sets up a home page, an About Us page, a page listing upcoming concerts, and a couple more.  Everything makes sense and interrelates, even if a couple of things feel ever so slightly forced.</p>
  579. <p>Here’s a page-number timeline of concepts’ first introductions:</p>
  581. <dl class="compact separated">
  582. <dt>p. 6</dt>
  583. <dd>Brainstorming site content and sketching a site map.  Bear in mind here that the actual instructional text starts on page 6.</dd>
  584. <dt>p. 10</dt>
  585. <dd>Adding a style sheet to an HTML document via a <code>link</code> element.</dd>
  586. <dt>p. 14</dt>
  587. <dd>A nice breakdown of how images are loaded into the page, what the various (common) image attributes are and mean, and the importance of good <code>alt</code> text.  On <em>page 14</em>.</dd>
  588. <dt>p. 17</dt>
  589. <dd>The concept of an empty element and how it differs from other elements.</dd>
  590. <dt>pp. 20-24</dt>
  591. <dd>An extended discussion of proper structure and good content for the web.  It shows how using headings and paragraphs breaks up large text walls, makes the distinction between ordered and unordered lists, and demonstrates the importance of proper element nesting.</dd>
  592. <dt>p. 25</dt>
  593. <dd>Diving into CSS.  A style sheet was added to the document back on page 10, but this is where CSS starts to be discussed in detail.</dd>
  594. <dt>p. 28</dt>
  595. <dd>Radial gradients!  They went there!  The syntax isn’t dissected and explained, but just showing working gradients clues readers in to their existence.  There’s also an example of styling <code>html</code> separately from <code>body</code>, without making a super big deal out of it.  This is a pattern throughout the rest of the book: many things are used without massively explaining them.  The author relies on the reader to repeat the example and see what happens.</dd>
  596. <dt>pp. 30-32</dt>
  597. <dd>A really great explanation of hexadecimal color values.  I’ve never seen better, to be honest.  That’s followed by a similarly great breakdown of the uses for, and differences between, <code>px</code>, <code>em</code>, and <code>%</code> values for sizing.</dd>
  598. <dt>p. 36</dt>
  599. <dd>The first of several really lovely step-by-step explanations of style blocks.  In this case, it’s styling a <code>nav</code> element with an unordered list of links, explaining the effects of each rule as it’s added.</dd>
  600. <dt>pp. 50-52</dt>
  601. <dd>An example of properly structuring and styling tabular data (in this case, a list of upcoming concerts).</dd>
  602. <dt>p. 59</dt>
  603. <dd>The box model and inline elements explained in sparing but useful detail.  This includes a brief look at inline elements and the baseline, and vertical alignment thereof.</dd>
  604. <dt>p. 74</dt>
  605. <dd>Responsive web design!  A nice introduction to media queries, and a quick primer on what responsive means and why it’s important.</dd>
  606. <dt>p. 78</dt>
  607. <dd>Floating images to wrap text around them. That segues into layout, using floats for the boxes enclosing the bits of content.</dd>
  608. <dt>p. 88</dt>
  609. <dd>Using web fonts (basically Google fonts).</dd>
  610. <dt>p. 90</dt>
  611. <dd>Putting your site online.</dd>
  612. </dl>
  614. <p>That isn’t everything that’s touched on in the book by a long shot—<code>max-width</code> and <code>min-width</code> show up early, as do <code>:last-child</code>, <code>border-radius</code>, and several more CSS features.  As I said above, these are generally introduced without much detailed explanation.  It’s a bold approach, but one that I think pays off handsomely.  Trusting the reader to become interested enough to track down the details on their own leaves room to include more things to spark interest.</p>
  616. <figure class="standalone">
  617. <a href=""><img src="" alt=""class="alignnone size-large wp-image-4171" srcset=" 1024w, 300w, 768w, 1242w" sizes="(max-width: 1024px) 100vw, 1024px" /></a>
  618. <figcaption>Pages 10 and 11.  Not all pages are this text-heavy.</figcaption>
  619. </figure>
  621. <p>That said, there are some aspects that may—probably will—cause confusion.  The biggest of these has to do with images.  There are several instances of using <code>img</code> to add images to pages, as you’d expect.  The author does provide a downloadable archive of assets, which is a little difficult to actually find (<a href="">here’s a direct link</a>), but the real problem is that once you extract the files, the filenames don’t match the filenames in print.  For example, in the book there’s a reference to <code>nanonauts.jpg</code>.  The corresponding file in the archive is <code>NINJA_FACE_FORWARD.png</code>.  At another point, <code>DSC03730.png</code> turns out to actually be <code>NINJA_GUITAR.png</code>.  There’s no indication of this whatsoever in the book.</p>
  623. <p>I get it: mistakes happen, and sometimes digital assets get out of step with print.  Nevertheless, I fear this could prove a major stumbling block for some readers.  They see one filename in the book, and that filename doesn’t exist in the assets.  Maybe they open up the asset images until they find the right one, and then maybe they figure out to replace the filename in the book with the one they found, and move on from there… but maybe they don’t.  I’d be a lot happier if there were an errata note and mapping table on the download page, or the online archive’s assets were corrected.</p>
  625. <p>Something similar happens on page 19, where the reader is directed to create a navigation link to <code>songs.html</code> when the page they’ve already created is called <code>our-songs.html</code>.  This one is a lot more forgivable, since the filenames are at least close to each other.  But again, it’s a place the reader might get lost and frustrated.  The painful irony is that this error appears in a “NINJA TIP” box that starts out, “Be careful when you’re typing links. You have to get them exactly right!”</p>
  627. <p>Another error of this kind happens in the section on adding a video to a page (p.45).  All the markup is there, and the URL they supply in great big text loads a video just fine.  The problem is that the video it loads is an ad for Scholastic, not the ninja-playing-a-guitar video the text very heavily implies it will be.  I don’t know if it used to be a rock ninja shredding power chords and Scholastic replaced it or what, but it almost feels like a bait and switch.  It was a little disheartening.</p>
  629. <img src="" alt="" class="pic" style="shape-outside: url(; shape-margin: 1em; margin-right: -75px;"/>
  631. <p>There’s one aspect I can’t quite make up my mind about, which is that just about everything in the book—text, design elements, media query breakpoints—is done using pixels.  A couple of percentage widths show up near the very end, but not much is said about them.  There is a very nice comparison of pixels, ems, and percentages on page 32, but with ems never being used (despite a claim to the contrary), readers are unlikely to use or understand them.</p>
  633. <p>Now, <em>I</em> don’t style this way, and my every instinct rebels against it.  But given that pixels really don’t mean what they used to, and that all modern browsers will scale pages up and down pretty seamlessly, is this a major problem?  I’m not sure that it is.  Either way, this does set readers on a specific initial path, and if that path bothers you, it’s worth knowing about so you can give them extra advice.</p>
  635. <p>The third thing I found weird was the two pages devoted to embedding a live Google Map into one of the pages (showing the location of the Nanonauts’ next show).  On the one hand, it’s cool in that it shows how some HTML elements (i.e., <code>iframe</code>) can serve as containers for external assets more complicated than images and videos, and having a live map show up in the page you’re building is probably pretty mind-blowing for someone just starting out.  On the other, it’s kind of a fiddly and unusual use case: not many novice sites need an embedded widget calling an API.</p>
  637. <p>I had less of a problem with the author showing a simple image-swapping-on-hover JavaScript solution, later in the book (even though my hindbrain kept chanting, “do that with CSS!”).  It’s a simple example of scripting pieces of the page, and lets Mr. Hatter talk about the DOM and DOM scripting without getting super crazy about it.</p>
  639. <p>The last thing I found a bit lacking was the closing two pages, which cover putting the site online.  The author does their best with the two pages, and what’s there is correct, but it’s just not enough to help everyone get the results of their work online.  I’m not sure two pages ever <em>could</em> be enough to help the novice audience.  I’d have liked to see this get four pages, so there was room for more detail and more options.  If you’re giving this book to someone to help them learn, my advice is to tell them up front that you’ll help them get their work online once they’ve finished the book.</p>
  641. <p>Okay, all that said?  I still <strong>absolutely recommend</strong> this as a beginners’ book.  Nearly every topic the text introduces, and there are many I didn’t mention here, is covered just the right amount and in just the right way to get readers where they need to be, excited about what they’ve accomplished, and ready to learn more on their own.  It’s pretty well up to date, at least as I write this, and isn’t likely to fall badly out of date any time soon.  Approachable, accessible, and instructive.</p>
  643. <p><strong>Final grade:</strong> I give it a solid <strong>B+</strong>, only falling short of A level due to the filename mismatches.</p>
  645. <img src="" alt="" class="standalone"/>
  647. <p class="note">Note: All images in this review are copyright <a href="">The CoderDojo Foundation</a>.  Some were taken from the book’s asset files.</p>
  649. ]]></content:encoded>
  650. <wfw:commentRss></wfw:commentRss>
  651. <slash:comments>0</slash:comments>
  652. </item>
  653. <item>
  654. <title>Generating Wireframe Boxes with CSS and HTML5</title>
  655. <link></link>
  656. <comments></comments>
  657. <pubDate>Mon, 27 Nov 2017 15:01:21 +0000</pubDate>
  658. <dc:creator><![CDATA[Eric Meyer]]></dc:creator>
  659. <category><![CDATA[CSS]]></category>
  660. <category><![CDATA[Hacks]]></category>
  661. <category><![CDATA[HTML5]]></category>
  663. <guid isPermaLink="false"></guid>
  664. <description><![CDATA[A method to create labeled wireframe-style boxes on top of existing page elements using a potpourri of CSS and tiny bits of HTML5.]]></description>
  665. <content:encoded><![CDATA[<p>I was recently noodling around with some new layout ideas for <a href="">An Event Apart</a>’s speaker pages (e.g., <a href="">Chris Coyier’s</a> or <a href="">Jen Simmons’</a>) and wanted to share the ideas with other members of the team.  But what I really wanted to show was wireframes to convey basic arrangement of the pieces, since I hadn’t yet done any time polishing details.</p>
  667. <p>I thought about taking screenshots and Photoshopping wireframe boxes over the various layout pieces, but then I wondered: could I overlay boxes on the live page with CSS?  Or perhaps even create and overlay them with nothing but some declarations and a wanton disregard for the sensibilities of god or man?</p>
  669. <p>And that’s when I realized…<em>I could</em>.</p>
  671. <img src="" alt="“Your scientists were so preoccupied with whether they could they didn’t stop to think if they should.” —Dr. Ian Malcolm (Jurassic Park, 1993)" class="standalone"/>
  673. <p>Now I’m going to share my discovery with you.</p>
  675. <p>Before I get started, I want to make one thing clear: this isn’t backward compatible.  I don’t care.  It doesn’t need to be.  It does work in the latest versions of Firefox and Chrome, within reasonable tolerances—Chrome falls a bit short on one aspect, which I’ll point out when we get there.</p>
  677. <p>All good?  Then let’s go.</p>
  679. <p>The goal was creating X-filled boxes that wireframers love so very, very much.  I figured, any container element that needs to have a box stuck over it gets a <code>class</code> of <code>wireframe</code>.</p>
  681. <pre class="html"><code>&lt;div class="wireframe"&gt;…(content goes here)…&lt;/div&gt;</code></pre>
  683. <p>(Don’t get too attached to that class, by the way: it doesn’t survive the article.  Foreshadowing!)</p>
  685. <p>The easy part was drawing a box around any element with that class.  I decided to use outlines, because they’re rarely employed for box edging and they don’t affect the layout even if your <code>box-sizing</code> is set to <code>content-box</code>.  (Mine usually is, by dint of not setting <code>box-sizing</code> at all.  But, you know, you do you.)</p>
  687. <pre class="css"><code>.wireframe {outline: 2px solid gray;}</code></pre>
  689. <figure class="standalone">
  690. <img src="" alt=""/>
  691. <figcaption>Adding simple boxes (to a redesigned local copy of <a href="">Rachel Andrew’s speaker page</a>)</figcaption>
  692. </figure>
  694. <p>The boxes overlap each other because the layout pieces on the right are, at least for the moment, floated.  They’re laid out that way so that if the right-hand content is short and the bio and articles run long, they can wrap around below the ‘sidebar’.  It’s generally useful to have the outlines showing the actual limits of the element boxes to which they’re attached.</p>
  696. <p>There is a potential drawback here: if your layout involves using negative margins to pull some elements out of their parents, <em>and</em> those parent elements are designated as wireframe boxes, outlines will stretch around the outhanging elements in Firefox, though not in Chrome.  Borders do not act the same way in Firefox.  I can’t rightly call this a bug, because I’m honestly not sure what outlines should do here.  Just be aware of it, is what I’m saying.</p>
  698. <p>Anyway, drawing rectangles with outlines, that’s the easy part.  Now I needed two diagonal lines, going from corner to corner.  But how?</p>
  700. <p>Linear gradients, that’s how.  See, if you use quadrant-based directions for your gradients, special magic math happens under the hood such that at the exact midpoint of the gradient, the color-line that extends perpendicularly off the gradient ray shoots precisely into the corners of the two quadrants adjacent to the quadrant into which the gradient ray is pointing.  Okay, that was probably hard to follow.  For example, set the gradient direction as <code>to top right</code> and the 50% color line of the gradient will run into the top left to the bottom right corners.</p>
  702. <p>That’s exactly what I needed!  Thus:</p>
  704. <pre class="css"><code>.wireframe {outline: 2px solid gray;
  705.    background:
  706.       linear-gradient(to top right,
  707.          transparent 49.9%, gray 49.9%,
  708.          gray 50.1%, transparent 50.1%);
  709. }</code></pre>
  711. <p>Okay, that’s one diagonal line.  The other is literally a copy of the first, except for having it go toward a different quadrant.</p>
  713. <pre class="css"><code>.wireframe {outline: 2px solid gray;
  714.    background:
  715.       linear-gradient(to top right,
  716.          transparent 49.9%, gray 49.9%,
  717.          gray 50.1%, transparent 50.1%),
  718.       linear-gradient(to bottom right,
  719.          transparent 49.9%, gray 49.9%,
  720.          gray 50.1%, transparent 50.1%);
  721. }</code></pre>
  723. <figure class="standalone">
  724. <img src="" alt=""/>
  725. <figcaption>Diagonal lines!</figcaption>
  726. </figure>
  728. <p>Bingo: an X.  But not one that scales terribly well.  Using percentages there means that the gray lines will be as thick as 0.2% the total length of the gradient ray.  Small boxes get thin, sometimes broken diagonals.  Great big boxes get thick honkin’ lines.</p>
  730. <p>So I fixed it with <code>calc()</code>.</p>
  732. <pre class="css"><code>.wireframe {outline: 2px solid gray;
  733.    background:
  734.       linear-gradient(to top right,
  735.          transparent calc(50% - 1px), gray calc(50% - 1px),
  736.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  737.       linear-gradient(to bottom right,
  738.          transparent calc(50% - 1px), gray calc(50% - 1px),
  739.          gray calc(50% + 1px), transparent calc(50% + 1px));
  740. }</code></pre>
  742. <figure class="standalone">
  743. <img src="" alt=""/>
  744. <figcaption>Properly sized diagonal lines!</figcaption>
  745. </figure>
  747. <p>And there you go: two-pixel-thick diagonal lines.</p>
  749. <p>There are two things to note here, before we move on.  First is that the spaces around the operators in the <code>calc()</code> values are intentional and, more to the point, necessary.  If you remove one or both of those spaces, <code>calc()</code> will simply fail to work.  In other words, <code>calc(50%-1px)</code> will <strong>fail</strong>—no background for you!  This is as designed, and there are reasons for it I don’t want to go into here, but suffice to say they exist and are arguably sensible.  <code>calc(50% - 1px)</code>, on the other hand, works as intended.</p>
  751. <p>Well, mostly: this is where Chrome comes up a bit short.  In large boxes, Chrome creates fuzzy lines thicker than 2 pixels.  I’m not sure what it’s doing to fudge the numbers here, but it sure seems like it’s fudging <em>something</em>.  The lines also don’t go into the corners quite as precisely as they should.  Firefox’s lines, on the other hand, come out correctly sized no matter what box size I set up, even if they are a bit jagged at times, and they go exactly into the corners of all the boxes I tested.  Chrome’s sloppiness here isn’t a deal-breaker, as far as I’m concerned, but it’s there and you should know about it.</p>
  753. <p>So that’s an element with an outer edge and two diagonal lines.  This is great as long as the box contains no actual <em>content</em>, which will sit on top of the diagonals, as you can see with the “hero image” in the top right.  Maybe that’s what you want, in which case great, but I specifically wanted <em>overlays</em>.  That way I could stick them on a live page and sort of fade out the contents while sticking wireframe boxes on top, to make the boxes the focus while still showing the stuff inside them.</p>
  755. <p>Enter generated content.  If I create a pseudo-element and attach the diagonal background gradients to <em>that</em>, they can sit on top of all the content.  That’ll also let me throw in a translucent background color to fill the box and fade out the contents.  Like so:</p>
  757. <pre class="css"><code>.wireframe {outline: 2px solid gray;
  758.    position: relative; z-index: 1;}
  759. .wireframe::before {
  760.    position: absolute; z-index: 8675309;
  761.    top: 0; bottom: 0; right: 0; left: 0;
  762.    background:
  763.       linear-gradient(to top right,
  764.          transparent calc(50% - 1px), gray calc(50% - 1px),
  765.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  766.       linear-gradient(to bottom right,
  767.          transparent calc(50% - 1px), gray calc(50% - 1px),
  768.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  769.       #FFF9;
  770.       content: "";
  771. }</code></pre>
  773. <figure class="standalone">
  774. <img src="" alt=""/>
  775. <figcaption>Placing the diagonals, and a translucent color, over the elements</figcaption>
  776. </figure>
  778. <p>I used <code>::before</code> mostly because hey, why not, but also because clearfix is usually an <code>::after</code> and I hear people are still using clearfix, more’s the pity.  So this avoids it.  If you’ve moved beyond the need for clearfix, then you can use <code>::after</code> just as easily.  Whatever floats your fancy.  (Get it?  Floats?  Yeah?  Clearfix?  Floats?  Ah, I kill me.)</p>
  780. <p>The stupidly large <code>z-index</code> on the <code>::before</code> is there to put the box overlay above any gridded, flexed, or positioned content that has an automatic <code>z-index</code>, or at least a sensible one.  You can raise it as high as you’d like (and your browser’s bit-depth will allow).  The small <code>z-index</code> on the elements themselves, on the other hand, makes sure they get an explicit stacking placement instead of an automatically-assigned place on the Z axis.  I find this generally settles a number of odd behaviors in various browsers.  Your experience may vary.</p>
  782. <p>It was at this point that I realized there was a whole other level here.  I mean, wireframe boxes stretched over content is pretty nifty all by itself.  That could have been enough.  But it wasn’t.</p>
  784. <p>Because what I realized was that I didn’t just want wireframe boxes, I wanted <em>labeled</em> wireframe boxes.  If a box was being applied to a list of articles, then I wanted a great big “Articles” label sitting in the middle of it, to make it obvious what was being placed there.</p>
  786. <p>Well, there was already a <code>content</code> property just sitting there, waiting to throw in actual content instead of an empty string, but how to fill it?  And that’s when I knew that <code>.wireframe</code>’s days were numbered.</p>
  788. <p>That’s because the easiest way to label each box was to use an <a href="">HTML data attribute</a> to attach the label I wanted to display.  And once that attribute was there, why not apply the wireframe styles based on the presence of the attribute, instead of adding class names that might get in the way of some unexpected DOM script?  So I changed the markup and CSS like this:</p>
  790. <pre class="html"><code>&lt;div data-wf="Articles"&gt;…(content goes here)…&lt;/div&gt;</code></pre>
  792. <pre class="css"><code>[data-wf] {outline: 2px solid gray;
  793.    position: relative; z-index: 1;}
  794. [data-wf]::before {
  795.    position: absolute; z-index: 8675309;
  796.    top: 0; bottom: 0; right: 0; left: 0;
  797.    background:
  798.       linear-gradient(to top right,
  799.          transparent calc(50% - 1px), gray calc(50% - 1px),
  800.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  801.       linear-gradient(to bottom right,
  802.          transparent calc(50% - 1px), gray calc(50% - 1px),
  803.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  804.       #FFF9;
  805.       content: "";
  806. }</code></pre>
  808. <p>(True story: I almost called it <code>data-wtf</code> instead.  <em>Almost.</em>)</p>
  810. <p>Having done that, I could modify the CSS to insert the attribute value, style the inserted text to look nice, and use flexbox properties to center it in the box.  So I did.</p>
  812. <pre class="css"><code>[data-wf] {outline: 2px solid gray;
  813.    position: relative; z-index: 1;}
  814. [data-wf]::before {
  815.    position: absolute; z-index: 8675309;
  816.    top: 0; bottom: 0; right: 0; left: 0;
  817.    background:
  818.       linear-gradient(to top right,
  819.          transparent calc(50% - 1px), gray calc(50% - 1px),
  820.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  821.       linear-gradient(to bottom right,
  822.          transparent calc(50% - 1px), gray calc(50% - 1px),
  823.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  824.       #FFF9;
  825.       content: attr(data-wf);
  826.       font: bold 2em Jubilat, Georgia, serif;
  827.       color: gray;
  828.       display: flex; justify-content: center; align-items: center;
  829. }</code></pre>
  831. <figure class="standalone">
  832. <img src="" alt=""/>
  833. <figcaption>Adding centered labels</figcaption>
  834. </figure>
  836. <p>That yielded big beautiful bold Jubilat labels (Jubilat is one of AEA’s brand font faces), sitting right on top of the center of the box, the crossing of the two diagonal lines behind them.</p>
  838. <p>Which actually turned out to be a small problem for me.  That text is certainly readable, but I wanted it to stand out a bit more from the diagonals.  I decided to stack text shadows in order to semi-simulate outside text stroking.</p>
  840. <pre class="css"><code>[data-wf] {outline: 2px solid gray;
  841.    position: relative; z-index: 1;}
  842. [data-wf]::before {
  843.    position: absolute; z-index: 8675309;
  844.    top: 0; bottom: 0; right: 0; left: 0;
  845.    background:
  846.       linear-gradient(to top right,
  847.          transparent calc(50% - 1px), gray calc(50% - 1px),
  848.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  849.       linear-gradient(to bottom right,
  850.          transparent calc(50% - 1px), gray calc(50% - 1px),
  851.          gray calc(50% + 1px), transparent calc(50% + 1px)),
  852.       #FFF9;
  853.       content: attr(data-wf);
  854.       font: bold 2em Jubilat, Georgia, serif;
  855.       color: gray;
  856.       text-shadow:
  857.          0 0 0.25em #FFF9, 0 0 0.25em #FFF9,
  858.          0 0 0.25em #FFF9, 0 0 0.25em #FFF9,
  859.          0 0 0.25em #FFF9;
  860.       display: flex; justify-content: center; align-items: center;
  861. }</code></pre>
  863. <figure class="standalone">
  864. <img src="" alt=""/>
  865. <figcaption>“Stroking” the box labels</figcaption>
  866. </figure>
  868. <p>It’s possible to use just four offset shadows with minimal or zero blur, but I find it sometimes creates weird jags on serif fonts, so I like stacking blurred shadows better.  But, again, you do you.</p>
  870. <p>As I looked over the results, it slowly dawned on me that the white-on-gray box scheme works well enough for a starting wireframe setup with no branding applied, but I was planning to drop these on pages with actual design and colors and that sort of thing.  I didn’t want the boxes to fill with translucent white; I wanted them to be translucent versions of the page background color.  And, furthermore, I wanted a way to be able to easily alter that color, when applied to different designs.</p>
  872. <p>Custom properties to the rescue!  Which is to say, native CSS variables to the rescue!</p>
  874. <p>Our page background color at An Event Apart is <code>#F7F6F1</code>, a combo I actually have memorized at this point.  Since I wanted to fill the boxes with a roughly three-quarters-opaque variant, I settled on <code>#F7F6F1BB</code>.  (Actual 75% is <code>BF</code>, if you care.)  So I defined a custom property for it:</p>
  876. <pre class="css"><code>html {
  877.    --fill: #F7F6F1BB;
  878. }</code></pre>
  880. <p>I could have assigned the variable to the <code>[data-wf]</code> rule instead of <code>html</code>, but I felt like setting them globally.  Because that’s how I roll, yo—Wulf &amp; Shaw have no strings on me.  If you want to bring the variables in closer, go for it.</p>
  882. <p>While I was there, I figured, why not, let’s also define a variable for the shared color of the outlines, diagonals, and label text.</p>
  884. <pre class="css"><code>html {
  885.    --fill: #F7F6F1BB;
  886.    --wire: gray;
  887. }</code></pre>
  889. <p>Then all I needed was to sprinkle variable calls where the colors were sitting.  I ended up here:</p>
  891. <pre class="css"><code>html {
  892.    --fill: #F7F6F1BB;
  893.    --wire: gray;
  894. }
  895. [data-wf] {outline: 2px solid var(--wire);
  896.    position: relative; z-index: 1;}
  897. [data-wf]::before {
  898.    position: absolute; z-index: 8675309;
  899.    top: 0; bottom: 0; right: 0; left: 0;
  900.    background:
  901.       linear-gradient(to top right,
  902.          transparent calc(50% - 1px), var(--wire) calc(50% - 1px),
  903.          var(--wire) calc(50% + 1px), transparent calc(50% + 1px)),
  904.       linear-gradient(to bottom right,
  905.          transparent calc(50% - 1px), var(--wire) calc(50% - 1px),
  906.          var(--wire) calc(50% + 1px), transparent calc(50% + 1px)),
  907.       var(--fill);
  908.       content: attr(data-wf);
  909.       font: bold 2em Jubilat, Georgia, serif;
  910.       color: var(--wire);
  911.       text-shadow:
  912.          0 0 0.25em var(--fill), 0 0 0.25em var(--fill),
  913.          0 0 0.25em var(--fill), 0 0 0.25em var(--fill),
  914.          0 0 0.25em var(--fill);
  915.       display: flex; justify-content: center; align-items: center;
  916. }</code></pre>
  918. <figure class="standalone">
  919. <img src="" alt=""/>
  920. <figcaption>The final product, with color themes and everything</figcaption>
  921. </figure>
  923. <p>The label could be broken out to use its own variable (e.g., <code>--text</code> or <code>--label</code>) easily enough, but I wanted a minimum of things to change.  I know myself too well to set up a bunch of controls to fiddle with, especially where color is concerned.</p>
  925. <p>And with that, I had a ready-to-hand, easily theme-able wireframing style block that I can drop into any development page and invoke simply by adding a few data attributes to the markup.  Data attributes, I might add, that would be trivially easy to later find and remove with regular expressions.  It’s a quick way to make it clear to stakeholders that a work in progress is, in fact, in progress, as well as a handy way to visualize which pieces of a prototype layout are going where.</p>
  927. <p>Now that we’ve come to the end and you’re still hanging in there with me, let me just say that I hope you’ve enjoyed this little trip through various parts of CSS.  If you have any questions, feel free to drop them in the comments below.  I’ll do my best to respond in reasonable amounts of time, travel and such permitting.</p>
  929. <p><br />P.S. And one final note, as <a href="">Kai Ryssdal</a> would say: every bit of CSS I used here is covered in <a href=""><cite>CSS: The Definitive Guide, 4th Edition</cite></a>.  I turned to my print copy twice in the process of working all this out, as it happens, to remind myself of specific syntax (for custom properties) and whitespace requirements (for <code>calc()</code> operators).  It really feels good to have a thing I made be useful to me!</p>
  930. ]]></content:encoded>
  931. <wfw:commentRss></wfw:commentRss>
  932. <slash:comments>13</slash:comments>
  933. </item>
  934. </channel>
  935. </rss>
  936. <!-- 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