Articles by
Chris Coyier

Founder, writer, designer, spam-deleter, email personality

CSS Animations and Transitions in Email

We don't generally think of CSS animations or transitions inside of email, or really any movement at all outside of an awkward occasional GIF. But there is really no reason you can't use them inside HTML emails, particularly if you do it in a progressive enhancement-friendly way. Like, you could style a link with a hover state and a shaking animation, but if the animation (or even the hover) doesn't work, it's still a functional link. Heck, you can use CSS grid in email, believe it or not.

Jason Rodriguez just wrote Understanding CSS Animations in Email: Transitions and Keyframe Animations that covers some of the possibilities. On the supported list of email clients that support CSS transitions and keyframe animations is Apple Mail, Outlook, and AOL mail, among others.

Other things to look at:

Keyboard-Only Focus Styles

Like Eric Bailey says, if it's interactive, it needs a focus style. Perhaps your best bet? Don't remove the dang outlines that focusable elements have by default. If you're going to rock a button { outline: 0; }, for example, then you'd better do a button:focus { /* something else very obvious visually */ }. I handled a ticket just today where a missing focus style was harming a user who relies on visual focus styles to navigate the web.

But those focus styles are most useful when tabbing or otherwise navigating with a keyboard, and less so when they are triggered by a mouse click. Now we've got :focus-visible! Nelo writes:

TLDR; :focus-visible is the keyboard-only version of :focus.

Also, the W3C proposal mentions that :focus-visible should be preferred over :focus except on elements that expect a keyboard input (e.g. text field, contenteditable).

(more…)

CSS and Network Performance

JavaScript and images tend to get the bulk of the blame for slow websites, but Harry explains very clearly why CSS is equally to blame and harder to deal with:

  1. A browser can’t render a page until it has built the Render Tree;
  2. the Render Tree is the combined result of the DOM and the CSSOM;
  3. the DOM is HTML plus any blocking JavaScript that needs to act upon it;
  4. the CSSOM is all CSS rules applied against the DOM;
  5. it’s easy to make JavaScript non-blocking with async and defer
    attributes;
  6. making CSS asynchronous is much more difficult;
  7. so a good rule of thumb to remember is that your page will only render as quickly as your slowest stylesheet.

There are lots of options to do better with this, including some interesting things that HTTP/2 unlocks.

Check out Šime Vidas's takeaways as well. It's all fascinating, but the progressive rendering stuff is particularly cool. I suspect many CSS-in-JS libraries could/should help with doing things this way.

A Bunch of Options for Looping Over querySelectorAll NodeLists

A common need when writing vanilla JavaScript is to find a selection of elements in the DOM and loop over them. For example, finding instances of a button and attaching a click handler to them.

const buttons = document.querySelectorAll(".js-do-thing");
// There could be any number of these! 
// I need to loop over them and attach a click handler.

There are SO MANY ways to go about it. Let's go through them.

(more…)

Why Browsers Download Stylesheets with Non-Matching Media Queries

Say you have a stylesheet linked up like this:

<link href="mobile.css" rel="stylesheet" media="screen and (max-width: 600px)">

But as the page loads, you're on a desktop browser where the screen is 1753px wide. The browser should just skip loading that stylesheet entirely, right? It doesn't. Thomas Steiner explains:

it turns out that the CSS spec writers and browser implementors are actually pretty darn smart about this:

The thing is, the user could always decide to resize their window (impacting width, height, aspect ratio), to print the document, etc., and even things that at first sight seem static (like the resolution) can change when a user with a multi-screen setup moves a window from say a Retina laptop screen to a bigger desktop monitor, or the user can unplug their mouse, and so on.

What browsers do do (heh, 💩) is apply a Lowest download priority.

The ironic inaccessibility of a11y

This resonated with me:

Because I bet it took me a year after seeing that acronym ("numeronym", I guess) for the first time to know that was just a stand-in for the word "accessibility". I'm only now just understanding that "i18n" means "Internationalization" and "l10n" means "Localization". I wonder how many conversations or articles I've missed because I just assumed the weird moniker was referring to something that had nothing to do with me. On the flip side, I wonder what good has come from having these cool words form a banner to rally under.

Lots of good conversation in that thread. I don't know enough to have an opinion about whether anyone else should or shouldn't use it, but remembering my own confusion, I think I'll avoid it around here.

When’s the last time you SFTP’d (or the like) into a server and changed a file directly?

In the grand tradition of every single poll question I've ever posted, the poll below has a has a fundamental flaw. In this case, there is no option between "In the last month" and "Never" but, alas, the results are interesting:

(more…)

Get References from HTML Built with Template Literals

One thing JavaScript template literals are great at is little blocks of HTML. Like:

// Probably from some API or whatever
const data = {
  title: "Title",
  content: "Content"
};

const some_html = `
  <div class="module">
    <h2>${data.title}</h2>
    <p>${data.content}</p>
  </div>
`;

But that's still just a string. It's not ready to append to the DOM just yet. And what if we need references to those elements inside somehow?

(more…)

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag