Today I Learned...

The cite element is about the source, not the author

March 25, 2020

I assumed the correct way to structure a blockquote was something like:

<blockquote>
  "There's never enough time to do all the nothing you want."
  <cite>Bill Watterson</cite>
</blockquote>

Turns out I’ve never read the actual spec for the cite element:

The cite element represents the title of a work (e.g. a book, a paper, an essay, a poem, a score, a song, a script, a film, a TV show, a game, a sculpture, a painting, a theatre production, a play, an opera, a musical, an exhibition, a legal case report, a computer program, etc). This can be a work that is being quoted or referenced in detail (i.e. a citation), or it can just be a work that is mentioned in passing.

A person’s name is not the title of a work — even if people call that person a piece of work — and the element must therefore not be used to mark up people’s names. 

A better route? Both figcaption and footer are suitable for the task.

<blockquote>
  "There's never enough time to do all the nothing you want."
  <footer>Bill Watterson</footer>
</blockquote>

Or, we can cite the source while attributing the quote:

<blockquote>
  "There's never enough time to do all the nothing you want."
  <footer>Bill Watterson, <cite>Calvin and Hobbes</cite></footer>
</blockquote>

This is all different from inline quotes, of course, which are wrapped in the q element:

<q>"There's never enough time to do all the nothing you want,"</q> he said with a wistful look upon his face.

Wrapping elements in an anchor tag is an a11y no-no.

March 11, 2020

That’s what Chris says by way of Adrian Roselli. I’m certainly guilty of that right here on this site, so perhaps I need to re-think that approach.

Apparently, targeting the ::after pseudo-element of a link is off limits, too, due to text selection.

.card {
  position: relative;
}

.card h2 a::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

I have to admit: that certainly looks tempting. Hetdon Pickering offers a JavaScript alternative that’s even more tempting — and accessible for that matter:

const cards = document.querySelectorAll('.card');  
Array.prototype.forEach.call(cards, card => {  
  let down, up, link = card.querySelector('h2 a');
  card.onmousedown = () => down = +new Date();
  card.onmouseup = () => {
    up = +new Date();
    if ((up - down) < 200) {
      link.click();
    }
  }
});

No matter the approach, it’s a sticky situation. Perhaps Chris is right that linking the actual content is a better way to go. If something is a link, make it look like a link, right? I could see an argument that calls cards as links an anti-pattern.

How to connect a Roomba up to Siri commands

February 16, 2020

First off, I didn’t even realize it was possible.

Secondly, it’s not nearly as difficult as I would have thought. In fact, it takes three components:

  • IFTTT
  • A Roomba API key
  • Siri shortcuts

I could detail it all here, but why do that when there’s already a full post that spells it out, step-by-step.

Having this configured is so helpful. In a first-world sorta way, but so helpful nonetheless.

A few neat little Safari developer tools

January 23, 2020

First off, there’s the keyboard shortcut to activate responsive mode: ^++R. I love the way devices are presented along the top of the screen.

Clicking each one changes the layout orientation, including split windows. 😮

Secondly, I noticed that Safari’s responsive mode can replicate other browsers and browser versions. I doubt that’s new, but my blonde brain finally noticed it.

Lastly, I saw Manuel’s little Safari-related pro-tip that there’s a tiny setting that forces the scroll bar to always be visible. What a great way to debug spacing issues during development without having to first interact with the page!

Chrome hates “Hoefler Text”

January 17, 2020

I was working on a slap-dash sorta project and setting up a WordPress site with a Twenty Nineteen child theme to bash it out. While I was testing my work in Chrome, I got this:

What’s up with those gross symbols in the text field?

This only affected Chrome, but I admittedly hadn’t tested it further in Opera or Edge, which both use the same Chromium engine. I thought it could be a server-side encoding issue, but I couldn’t confirm it and couldn’t find anything in a hasty (non-Google) search.

I inspected element and saw that Twenty Nineteen explicitly defines a font-family on text fields:

button, input, select, optgroup, textarea {
  "NonBreakingSpaceOverride", "Hoefler Text", "Baskerville Old Face", Garamond, "Times New Roman", serif;
}

Ugh. I mean, it’s cool and all to use a different font for form elements, but it’s certainly something that flies under the radar pretty easily, especially when creating a child theme off of it.

I commented out “NonBreakingSpaceOverride” and nothing. Then “Hoefler Text”. Bingo!

All I had to do from there was override the declaration with one of my own, using the same System Font stack the rest of the site uses. Boom.

That selecting the first child of a child element when the parent is hovered in CSS is weird.

January 4, 2020

It might be the weirdest line of CSS I’ve ever written.

.site-footer__nav a:hover > svg ellipse:first-child {
  fill: var(--primary-color);
}

You’ve gotta use aria-label when there is no discernible label for a link

January 2, 2020

I wrapped an element in an &lt;a> tag. That element had text in it, but that content was not directly related to the parent anchor. Google’s Measure tool was dinging my accessibility score because of it. I was able to wipe things clean by adding an aria-label on the anchor.

<a href="/contact" aria-label="My contact form">
  <article>
    <h3>Contact Me</h3>
  </article>
</a>

How to clear a WordPress WebSocket error from the console

December 31, 2019

This kept popping up in the console:

WebSocket connection to 'wss://public-api.wordpress.com/pinghub/wpcom/me/newest-note-data' failed: Unexpected response code: 403

Turns out it’s from Jetpack. I hadn’t used it on my site before, but wanted to give it a spin this time around. Simply deactivating and reactivating the plugin did the tricks and cleared the error.

How to display the WordPress post date and modified date, if modified

Had to look this up, but it makes a lot of sense when it’s typed out. Grab the current date and the post date, then compare the two. If the difference is zero, then only show the post date. If the difference is one or higher, show both.

<div class="post-single__date">
  <?php 
  $j_time = get_the_time('j');
  $j_modified_time = get_the_modified_time('j');
  if ($j_modified_time >= $j_time + 1) { 
    echo the_date('F j, Y');
    echo "Updated: "; the_modified_time('F j, Y');
  } else {
    echo the_date('F j, Y');
  } ?>
</div>

How to quickly spin up a dark theme

It’s easier than I thought it would be. Use CSS custom properties to define a color palette on the :root element, then use the prefers-color-scheme media query to swap those colors for others when the media query is set to dark.

Here’s how my variables file looks:

:root {
  --red: #fd1e1e;
  --orange: #fd5a1e;
  --gray-lightest: #f7f2f1;
  --gray-lighter: #e8e3e1;
  --gray-light: #cabdb9;
  --gray: #b0a3a0;
  --gray-medium: #7d7472;
  --gray-dark: #615a58;
  --gray-darker: #463e3b;
  --gray-darkest: #221d1b;
  --white: #fff;
  --black: #000;


  --primary-color: var(--orange);
  --text-color: var(--gray-darkest);
  --background: var(--gray-lightest);
  --site-title: var(--gray-dark);
  --border-color: var(--gray);
  --link-border: var(--primary-color);
  --link-color: var(--text-color);
  --link-hover: var(--white);
  --link-current: var(--gray-darkest);
  --code-blocks: var(--white);
  --error-color: var(--red);
  --table-background: var(--gray-lightest);

  @media (prefers-color-scheme: dark) {
    --text-color: var(--white);
    --background: var(--gray-darkest);
    --site-title: var(--gray);
    --border-color: var(--gray-lightest);
    --link-color: var(--white);
    --link-current: var(--white);
    --code-blocks: var(--black);
    --table-background: var(--gray-darker);
  }
}