These snippets are my attempt to save and organize various bits of code, best practices, and resources relating to web development and design. They also function as a to do list of sorts, for things I want to implement in my own code, but haven’t yet. The concept is inspired by Jeremy Keith’s links and CSS-Tricks, among other things. Enjoy.

CSS Writing Modes

You can use a little-known, yet important and powerful CSS property to make text run vertically.

A screenshot of a page featuring a photo of Octavia Butler, with the text "Octavia Butler" running down the right edge, starting at the top and going down the page.

Or instead of running text vertically, you can layout a set of icons or interface buttons in this way. Or, of course, with anything on your page.


If you do want a bit more of a taste, look at this example that adds text-orientation: upright; to the mix — turning the individual letters of the latin font to be upright instead of sideways.

A collage of photos of a dog on the right, with the text "winter" running down the left side, with letters stacked one on top of another.


h1 {
  writing-mode: vertical-rl;
  text-orientation: upright;
  text-transform: uppercase;
  letter-spacing: -25px;


Don't Re-Create Browser Features (Text resize widgets, etc.)

I built text sizing widgets for years, every damn site. I was so proud of them too. It was a way of showing I care about users. It was all ego. As soon as I could start tracking clicks on those widgets I found they were not used. Even on sites I built for low vision communities.

Instead, a good design with non-hardcoded typefaces that is responsive and does not disable zoom was all I needed. In short, good development techniques and best practices. That handled most of my edge cases just fine. For the remainder, a little documentation in the form of simple, contextual help text.

Notice I am not referencing assistive technology. For the most part, those users don’t need your widgets, they have already obtained tools to work around a non-inclusive web.


Instead of custom widget, maybe help educate users on how to use their own web browser. Perhaps link to, or offer as pop-up help, quick instructions on how to scale text in the user’s current browser.

Now you will have educated a user. You will have armed a user to have a better experience across the whole of the web. You will have stopped selfishly building a widget for just your users and contributed to empowering all users.

What could be more inclusive than that?


Fun with Staggered Transitions - Cloud Four

I was prototyping a sliding view transition between nested levels of navigation:

While this sort of transition had worked well for past projects, it didn’t feel quite right for this one. I wanted it to have a little more personality, to feel like it was organically reacting to the item you selected.

I thought it might be cool to stagger the animation, so the selected item began moving first, with its siblings following as if tethered together:


Fluid Type on CodePen Blogs

It became more popular to “go fully responsive” with layouts, where widths were largely in percentages, so that you get to use as much room is available at any given screen size. To a point, anyway.

You can also “go fully responsive” with typography, in a sense. There are a number of Pens by Mike Riethmuller that tackle things like fluid type size, fluid modular scale, and even fluid vertical rhythm.

It’s worth reading up on Mike’s technique here, but a distilled Sass version is like:


@function strip-unit($value) {
  @return $value / ($value * 0 + 1);
@mixin fluid-type($min-vw, $max-vw, $min-font-size, $max-font-size) {
  $u1: unit($min-vw);
  $u2: unit($max-vw);
  $u3: unit($min-font-size);
  $u4: unit($max-font-size);
  @if $u1 == $u2 and $u1 == $u3 and $u1 == $u4 {
    & {
      font-size: $min-font-size;
      @media screen and (min-width: $min-vw) {
        font-size: calc(#{$min-font-size} + #{strip-unit($max-font-size - $min-font-size)} * ((100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)}));
      @media screen and (min-width: $max-vw) {
        font-size: $max-font-size;
$min_width: 320px;
$max_width: 1200px;
$min_font: 16px;
$max_font: 24px;
$mod_1: 1.2; // mobile
$mod_2: 1.5; // desktop
html {
  @include fluid-type($min_width, $max_width, $min_font, $max_font);
h1 {  
  font-size: $mod_1*$mod_1*$mod_1*$mod_1 *1rem; 
  @include fluid-type($min_width, $max_width, $mod_1*$mod_1*$mod_1 *$min_font, $mod_2*$mod_2*$mod_2 *$min_font);
h2 {  
  font-size: $mod_1*$mod_1*$mod_1 *1rem; 
  @include fluid-type($min_width, $max_width, $mod_1*$mod_1*$mod_1 *$min_font, $mod_2*$mod_2*$mod_2 *$min_font);
h3 { 
  font-size: $mod_1*$mod_1 *1rem;
  @include fluid-type($min_width, $max_width, $mod_1*$mod_1 *$min_font, $mod_2*$mod_2 *$min_font);


Jessica's Client Email Helper

Negotiating incoming project terms over email is difficult for even the well-seasoned professional. I’ve created this handy tool to help you say “no” to free and low-budget work and to help ask for more favorable contract terms before the start of a project. I tried to make it as comprehensive and flexible as possible, but every creative industry is a bit different so feel free to adapt my words to best suit your personal situation.

A screenshot of Jessica’s Client Email Helper, showing the different options for client and budget, along with the resulting email template.


JavaScript loading: Prefer DEFER Over ASYNC

ASYNC and DEFER are similar in that they allow scripts to load without blocking the HTML parser which means users see page content more quickly. But they do have differences:

  • Scripts loaded with ASYNC are parsed and executed immediately when the resource is done downloading. Whereas DEFER scripts don’t execute until the HTML document is done being parsed (AKA, DOM Interactive or performance.timing.domInteractive).
  • ASYNC scripts may load out-of-order, whereas DEFER scripts are executed in the order in which they appear in markup. (Although there’s a bug that makes DEFER’s execution order questionable in IE⇐9.)

Even though ASYNC and DEFER don’t block the HTML parser, they can block rendering. This happens when they’re parsed and executed before rendering is complete and take over the browser main thread. There’s nothing in the spec that says they have to wait until rendering is complete. ASYNC scripts execute immediately once they finish downloading, and DEFER scripts execute after DOM Interactive.


DEFER always causes script execution to happen at the same time as or later than ASYNC. Presumably, scripts are made DEFER or ASYNC because they are less important for the critical content on the page. Therefore, it’s better to use DEFER so that their execution happens outside of the main rendering time.

DEFER scripts can never block synchronous scripts, while ASYNC scripts might depending on how quickly they download. Synchronous scripts are typically made synchronous because they are important for the critical content on the page. Therefore, it’s better to use DEFER so that synchronous scripts are not blocked from executing and their critical work is completed more quickly.


GPU Animation: Doing It Right

Most people now know that modern web browsers use the GPU to render parts of web pages, especially ones with animation. For example, a CSS animation using the transform property looks much smoother than one using the left and top properties. But if you ask, “How do I get smooth animation from the GPU?” in most cases, you’ll hear something like, “Use transform: translateZ(0) or will-change: transform.”

These properties have become something like how we used zoom: 1 for Internet Explorer 6 (if you catch my drift) in terms of preparing animation for the GPU — or compositing, as browser vendors like to call it.

But sometimes animation that is nice and smooth in a simple demo runs very slowly on a real website, introduces visual artefacts or even crashes the browser. Why does this happen? How do we fix it?


  • Watch out for the number and size of composite layers from the very beginning — especially ones created by implicit compositing. The “Layers” panel in your browser’s development tools is your best friend.
  • Modern browsers make heavy use of compositing not just for animation but to optimize the painting of page elements. For example, position: fixed and the iframe and video elements use compositing.
  • The size of compositing layers is likely be more important than the number of layers. In some cases, the browser will try to reduce the number of composite layers (see the “Layer Squashing” section of “GPU Accelerated Compositing in Chrome“); this prevents so-called “layer explosion” and reduces memory consumption, especially when layers have large intersections. But sometimes, such optimization has a negative impact, such as when a very large texture consumes much more memory than a few small layers. To bypass this optimization, I add a small, unique translateZ() value to each element, such as translateZ(0.0001px), translateZ(0.0002px), etc. The browser will determine that the elements lie on different planes in the 3D space and, thus, skip optimization.
  • You can’t just add transform: translateZ(0) or will-change: transform to any random element to virtually improve animation performance or to get rid of visual artifacts. GPU compositing has many drawbacks and tradeoffs to be considered. When not used sparingly, compositing will decrease overall performance at best, and crash browsers at worst.

Allow me to remind you of the big disclaimer: There is no official specification for GPU compositing, and each browser solves the same problems differently. Some sections of this article may become obsolete in a few months.


CSS Shorthand Syntax Considered an Anti-Pattern

Typically we would view shorthand syntax as a benefit: fewer keystrokes, fewer lines of code, less data over the wire. Sounds great! However, it comes with a rather troublesome side effect: it often unsets other properties that we never intended to modify.

When we write something like:


.btn {
  background: red;

…we’re likely to get a red background colour applied to our button. But what we’re really saying is this:


.btn {
  background-image: initial;
  background-position-x: initial;
  background-position-y: initial;
  background-size: initial;
  background-repeat-x: initial;
  background-repeat-y: initial;
  background-attachment: initial;
  background-origin: initial;
  background-clip: initial;
  background-color: red;

Simply by using the shorter syntax, we have implicitly decided that we want no image to start top-left, repeat x and y, to scroll with the element, and so on…

Nearly every problem, bug, or regression in CSS at scale is happens because we did too much too soon, and further down the line we’re being affected by that. What this basically comes down to is the fact that, with CSS, you should only ever do as little as you need to do and nothing more.

Misusing shorthand syntax is a surefire way to do too much too soon, as thus it should be avoided. CSS is a lot harder to undo than it is to do.