Developer News

Linearly Scale font-size with CSS clamp() Based on the Viewport

Css Tricks - Fri, 09/25/2020 - 4:24am

Responsive typography has been tried in the past with a slew of methods such as media queries and CSS calc().

Here, we’re going to explore a different way to linearly scale text between a set of minimum and maximum sizes as the viewport’s width increases, with the intent of making its behavior at different screen sizes more predictable — All in a single line of CSS, thanks to clamp().

The CSS function clamp() is a heavy hitter. It’s useful for a variety of things, but it’s especially nice for typography. Here’s how it works. It takes three values: 

clamp(minimum, preferred, maximum);

The value it returns will be the preferred value, until that preferred value is lower than the minimum value (at which point the minimum value will be returned) or higher than the maximum value (at which point the maximum will be returned).

In this example, the preferred value is 50%. On the left 50% of the 400px viewport is 200px, which is less than the 300px minimum value that gets used instead. On the right, 50% of the 1400px viewport equals 700px, which is greater than the minimum value and lower than the 800px maximum value, so it equates to 700px.

Wouldn’t it just always be the preferred value then, assuming you aren’t being weird and set it between the minimum and maximum? Well, you’re rather expected to use a formula for the preferred value, like:

.banner {   width: clamp(200px, 50% + 20px, 800px); /* Yes, you can do math inside clamp()! */ }

Say you want to set an element’s minimum font-size to 1rem when the viewport width is 360px or below, and set the maximum to 3.5rem when the viewport width is 840px or above. 

In other words:

1rem   = 360px and below Scaled = 361px - 839px 3.5rem = 840px and above

Any viewport width between 361 and 839 pixels needs a font size linearly scaled between 1 and 3.5rem. That’s actually super easy with clamp()! For example, at a viewport width of 600 pixels, halfway between 360 and 840 pixels, we would get exactly the middle value between 1 and 3.5rem, which is 2.25rem.

What we are trying to achieve with clamp() is called linear interpolation: getting intermediate information between two data points.

Here are the four steps to do this:

Step 1

Pick your minimum and maximum font sizes, and your minimum and maximum viewport widths. In our example, that’s 1rem and 3.5rem for the font sizes, and 360px and 840px for the widths.

Step 2

Convert the widths to rem. Since 1rem on most browsers is 16px by default (more on that later), that’s what we’re going to use. So, now the minimum and maximum viewport widths will be 22.5rem and 52.5rem, respectively.

Step 3

Here, we’re gonna lean a bit to the math side. When paired together, the viewport widths and the font sizes make two points on an X and Y coordinate system, and those points make a line.

(22.5, 1) and (52.5, 3.5)

We kinda need that line — or rather its slope and its intersection with the Y axis to be more specific. Here’s how to calculate that:

slope = (maxFontSize - minFontSize) / (maxWidth - minWidth) yAxisIntersection = -minWidth * slope + minFontSize

That gives us a value of 0.0833 for the slope and -0.875 for the intersection at the Y axis.

Step 4

Now we build the clamp() function. The formula for the preferred value is:

preferredValue = yAxisIntersection[rem] + (slope * 100)[vw]

So the function ends up like this:

.header {   font-size: clamp(1rem, -0.875rem + 8.333vw, 3.5rem); }

You can visualize the result in the following demo:

CodePen Embed Fallback

Go ahead and play with it. As you can see, the font size stops growing when the viewport width is 840px and stops shrinking at 360px. Everything in between changes in linear fashion.

What if the user changes the root’s font size?

You may have noticed a little flaw with this whole approach: it only works as long as the root’s font size is the one you think it is — which is 16px in the previous example — and never changes.

We are converting the widths, 360px and 840px, to rem units by dividing them by 16 because that’s what we assume is the root’s font size. If the user has their preferences set to another root font size, say 18px instead of the default 16px, then that calculation is going to be wrong and the text won’t resize the way we’d expect.

There is only one approach we can use here, and it’s (1) making the necessary calculations in code on page load, (2) listening for changes to the root’s font size, and (3) re-calculating everything if any changes take place.

Here’s a useful JavaScript function to do the calculations:

// Takes the viewport widths in pixels and the font sizes in rem function clampBuilder( minWidthPx, maxWidthPx, minFontSize, maxFontSize ) {   const root = document.querySelector( "html" );   const pixelsPerRem = Number( getComputedStyle( root ).fontSize.slice( 0,-2 ) );   const minWidth = minWidthPx / pixelsPerRem;   const maxWidth = maxWidthPx / pixelsPerRem;   const slope = ( maxFontSize - minFontSize ) / ( maxWidth - minWidth );   const yAxisIntersection = -minWidth * slope + minFontSize   return `clamp( ${ minFontSize }rem, ${ yAxisIntersection }rem + ${ slope * 100 }vw, ${ maxFontSize }rem )`; } // clampBuilder( 360, 840, 1, 3.5 ) -> "clamp( 1rem, -0.875rem + 8.333vw, 3.5rem )"

I’m deliberately leaving out how to inject the returned string into the CSS because there are a ton of ways to do that depending on your needs and whether your are using vanilla CSS, a CSS-in-JS library, or something else. Also, there is no native event for font size changes, so we would have to manually check for that. We could use setInterval to check every second, but that could come at a performance cost.

This is more of an edge case. Very few people change their browser’s font size and even fewer are going to change it precisely while visiting your site. But if you want your site to be as responsive as possible, then this is the way to go.

For those who don’t mind that edge case

You think you can live without it being perfect? Then I got something for you. I made a small tool to make make the calculations quick and simple.

All you have to do is plug the widths and font sizes into the tool, and the function is calculated for you. Copy and paste the result in your CSS. It’s not fancy and I’m sure a lot of it can be improved but, for the purpose of this article, it’s more than enough. Feel free to fork and modify to your heart’s content.

How to avoid reflowing text

Having such fine-grained control on the dimensions of typography allows us to do other cool stuff — like stopping text from reflowing at different viewport widths.

This is how text normally behaves.

It has a number of lines at a certain viewport width… …and wraps it’s lines to fit another width

But now, with the control we have, we can make text keep the same number of lines, breaking on the same word always, on whatever viewport width we throw at it.

Viewport width = 400px Viewport width = 740px

So how do we do this? To start, the ratio between font sizes and viewport widths must stay the same. In this example, we go from 1rem at 320px to 3rem at 960px.

320 / 1 = 320 960 / 3 = 320

If we’re using the clampBuilder() function we made earlier, that becomes:

const text = document.querySelector( "p" ); = clampBuilder( 320, 960, 1, 3 );

It keeps the same width-to-font ratio. The reason we do this is because we need to ensure that the text has the right size at every width in order for it to be able to keep the same number of lines. It’ll still reflow at different widths but doing this is necessary for what we are going to do next. 

Now we have to get some help from the CSS character (ch) unit because having the font size just right is not enough. One ch unit is the equivalent to the width of the glyph “0” in an element’s font. We want to make the body of text as wide as the viewport, not by setting width: 100% but with width: Xch, where X is the amount of ch units (or 0s) necessary to fill the viewport horizontally.

To find X, we must divide the minimum viewport width, 320px, by the element’s ch size at whatever font size it is when the viewport is 320px wide. That’s 1rem in this case.

Don’t sweat it, here’s a snippet to calculate an element’s ch size:

// Returns the width, in pixels, of the "0" glyph of an element at a desired font size function calculateCh( element, fontSize ) {   const zero = document.createElement( "span" );   zero.innerText = "0"; = "absolute"; = fontSize;   element.appendChild( zero );   const chPixels = zero.getBoundingClientRect().width;   element.removeChild( zero );   return chPixels; }

Now we can proceed to set the text’s width:

function calculateCh( element, fontSize ) { ... } const text = document.querySelector( "p" ); = clampBuilder( 320, 960, 1, 3 ); = `${ 320 / calculateCh(text, "1rem" ) }ch`; Umm, who invited you to the party, scrollbar?

Whoa, wait. Something bad happened. There’s a horizontal scrollbar screwing things up!

When we talk about 320px, we are talking about the width of the viewport, including the vertical scrollbar. So, the text’s width is being set to the width of the visible area, plus the width of the scrollbar which makes it overflow horizontally.

Then why not use a metric that doesn’t include the width of the vertical scrollbar? We can’t and it’s because of the CSS vw unit. Remember, we are using vw in clamp() to control font sizes. You see, vw includes the width of the vertical scrollbar which makes the font scale along the viewport width including the scrollbar. If we want to avoid any reflow, then the width must be proportional to whatever width the viewport is, including the scrollbar.

So what do we do? When we do this: = `${ 320 / calculateCh(text, "1rem") }ch`;

…we can scale the result down by multiplying it by a number smaller than 1. 0.9 does the trick. That means the text’s width is going to be 90% of the viewport width, which will more than account for the small amount of space taken up by the scrollbar. We can make it narrower by using an even smaller number, like 0.6.

function calculateCh( element, fontSize ) { ... } const text = document.querySelector( "p" ); = clampBuilder( 20, 960, 1, 3 ); = `${ 320 / calculateCh(text, "1rem" ) * 0.9 }ch`; So long, scrollbar!

You might be tempted to simply subtract a few pixels from 320 to ignore the scrollbar, like this: = `${ ( 320 - 30 ) / calculateCh( text, "1rem" ) }ch`;

The problem with this is that it brings back the reflow issue! That’s because subtracting from 320 breaks the viewport-to-font ratio.

Viewport width = 650px Viewport width = 670px

The width of text must always be a percentage of the viewport width. Another thing to have in mind is that we need to make sure we’re loading the same font on every device using the site. This sounds obvious doesn’t it? Well, here’s a little detail that could throw your text off. Doing something like font-family: sans-serif won’t guarantee that the same font is used in every browser. sans-serif will set Arial on Chrome for Windows, but Roboto on Chrome for Android. Also, the geometry of some fonts may cause reflow even if you do everything right. Monospaced fonts tend to yield the best results. So always make sure your fonts are on point.

Check out this non-reflowing example in the following demo:

CodePen Embed Fallback Non-reflowing text inside a container

All we have to do is now is apply the font size and width to the container instead of the text elements directly. The text inside it will just need to be set to width: 100%. This isn’t necessary in the cases of paragraphs and headings since they’re block-level elements anyway and will fill the width of the container automatically.

CodePen Embed Fallback

An advantage of applying this in a parent container is that its children will react and resize automatically without having to set their font sizes and widths one-by-one. Also, if we need to change the font size of a single element without affecting the others, all we’d have to do is change its font size to any em amount and it will be naturally relative to the container’s font size.

CodePen Embed Fallback

Non-reflowing text is finicky, but it’s a subtle effect that can bring a nice touch to a design!

Wrapping up

To cap things off, I put together a little demonstration of how all of this could look in a real life scenario.

CodePen Embed Fallback

In this final example, you can also change the root font size and the clamp() function will be recalculated automatically so the text can have the right size in any situation.

Even though the target of this article is to use clamp() with font sizes, this same technique could be used in any CSS property that receives a length unit. Now, I’m not saying you should use this everywhere. Many times, a good old font-size: 1rem is all you need. I’m just trying to show you how much control you can have when you need it.

Personally, I believe clamp() is one of the best things to arrive in CSS and I can’t wait to see what other usages people come up with as it becomes more and more widespread!

The post Linearly Scale font-size with CSS clamp() Based on the Viewport appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Web Technologies and Syntax

Css Tricks - Thu, 09/24/2020 - 8:47am

JavaScript has a (newish) feature called optional chaining. Say I have code like:

const name =;

If person happens to not exist on Data, I’m going to get a hard, show-stopping error. With optional chaining, I can write:

const name = Data.person?.name;

Now if person doesn’t exist, name becomes undefined instead of throwing an error. That’s quite useful if you ask me. In a way, it makes for more resilient code, since there is less possibility of a script that entirely bombs out. But there are arguments that it actually makes for less resilient code, because instead of fixing the problem at the root level (bad data), you’re putting a band-aid on the problem.

Jim Nielsen makes the connection to optional chaining and !important in CSS. Errors of “undefined properties” are perhaps the most common of all JavaScript errors and optional chaining is a quick workaround. Styles that don’t cascade the way you want is (maybe?) the most common of all CSS issues and !important is a quick workaround.

Anyone familiar with CSS knows that using !important doesn’t always fix your problems. In fact, it might just cause you more problems. Ditto for optional chaining in JavaScript, it might cause you more problems than it fixes (we just don’t know it yet since it hasn’t been around long enough).

I like that take.

Sweeping negative hot takes about new features are just clickbait silliness, but sometimes there are good things buried in there to think about. I’ll bet optional chaining settles into some nice patterns in JavaScript, just like !important has in CSS to some degree. Most chatter I hear about !important in CSS lately is about how you should use it when you really mean it (not for getting out of a jam).

Direct Link to ArticlePermalink

The post Web Technologies and Syntax appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

The Empty Box

Css Tricks - Wed, 09/23/2020 - 12:34pm

When I was in high school, we learned about “The Black Box” which is concept in theater. If memory serves me right, the approach was a simple and elegant one: that you can take any space, any black box, and make it come to life with a story. I liked the idea that it’s possible to convey anything, tell any story, and create any reality — all in the confines of what equates to a black box, a simple room that requires a curtain and very little else.

It’s an exciting concept. You see something extremely polished like a studio-produced movie. One might think, “No way I could do that.” All the scripts, the actors, the production, animation, set, props, everything. Where do you even begin?

But looking at things through The Black Box model, we distill the movie down to its essence, the story. We can see it as some folks telling a story in a stark, empty room. Take Thor: Ragnarok, a movie I really enjoy. It has incredible special effects, bits of humor, tension, relationships and stories that are well told. Sibling rivalry? Most of us know of or have seen something like that. Someone confronting you and you’d like to escape? We have all likely dealt with a challenge like that.

Those are the stories. The special effects and polished production? Those merely dress up the stories but aren’t necessary to convey the story. But still, how do you get from a black box to a large scale production?

Or, put in a different context: how do we get from an idea to a full-fledged website or app? You see all of these incredible sites around you and could easily fall into a trap of thinking anything you put out needs to meet the same scale and production. But let’s pull the curtain back on that and play with the idea that…

Apps are the box

Programmers are literal creatures, so instead of a “black box,” which has different connotations in tech, I’ll switch it up and call it an “empty box” — even though that also has roots in other metaphors, such as a the “tabula rasa” (clean slate) in art, which is a very similar concept.

If you look at an apps like Notion, Airbnb, or Etsy as newcomers to the industry, the yes, it might seem impossible how you might get from learning basic CRUD operations to working on an application at the same scale, state and complexity as those apps. But what happens if we flip the script? Instead of thinking about building the entire universe from scratch, maybe we start with an empty box, one that only holds the core use case or problem that’s being solved. We can decide what we’re going to create with this small bit of space we have in the world.

It’s a nice way to dial back the scope. Of course, people might use our sites in myriad ways, but when you peel back every usage, every feature, and compare what else is out there, what is the purpose? Sometimes we work at big companies with lots of competing priorities — so many that if you ask different folks, you’ll likely get a wide range of answers. And certainly any app with any level of complexity has to cater to many user needs.

However, I wonder if it might serve us to be able to answer that question with clarity. Particularly when we’re just starting out.

You have an empty box. What can you build in that space? You can engage people all around the world instantly in any way. You can create any interaction. What is that interaction and what is it trying to convey? What is going to make it relatable? What’s going to get the message across?

Forget about all the production and complexity you could build. What’s the purpose you want to convey at the core? What are you most excited about? What the solution to the problem right in front of you?

The post The Empty Box appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Jamstack Conf

Css Tricks - Tue, 09/22/2020 - 8:38am

Here’s an important detail here: It’s free!

Jamstack Conf Virtual is coming up October 6th and 7th, 2020. The sessions are on October 6th. That’s the free part (register here). Then on October 7th there are a variety of workshops (they all look great to me) that are $100 USD each. That’s the classic conference one-two punch. Sessions are for getting a broad sense of what’s happening and will very likely open your eyes to some new concepts; workshops are for deep learning and walking away with some new skills.

The speaker lineup is top-notch!

I’ve been to several Jamstack Conf’s myself, and I’m a fan. Some of my most favorite conferences ever are ones that are focused around a technological idea at the rise of their relevance. That’s exactly what’s happening here and I’m excited to check it out. You can even watch videos from the 2019 conference to see just how awesome of an experience it is.

Direct Link to ArticlePermalink

The post Jamstack Conf appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Accessible Web Animation: The WCAG on Animation Explained

Css Tricks - Tue, 09/22/2020 - 4:56am

It’s true, web animation can be accessible! Sometimes it just takes a little extra effort to make sure that it is. There are strategic things we can do to make sure our animations have a positive impact on accessibility, like planning how they contribute to the overall UX and ease of use of our site. There are also more tactical considerations for making sure the animations on our site are accessible, and that’s where the Web Content Accessibility Guidelines (WCAG) comes in.

While different contexts can affect the details of what you need to do, the WCAG provides a number of recommendations for animated content and interactions. These include guidelines for when to provide pause and play controls, limits for blinking or flashing the screen, and advice on when to provide reduced motion options for users with motion sensitivities. If you haven’t looked at it in a while, the specification has been updated to version 2.1, and now has even more useful guidance on how we can design web animations that are accessible. 

Let’s dig into each of those recommendations in more detail to see how we can apply them to our work on the web:

Pause, Stop, Hide 

The first of the WCAG recommendations that applies specifically to animation is Pause, Stop, Hide. For this one, the title gives a pretty big clue into what the recommendation is all about. It states:

For any moving, blinking or scrolling information that (1) starts automatically, (2) lasts more than five seconds, and (3) is presented in parallel with other content, there is a mechanism for the user to pause, stop, or hide it unless the movement, blinking, or scrolling is part of an activity where it is essential; […]

The recommendation specifically applies to motion initiated by the web page without user interaction, and it might sound like something that doesn’t apply to UI animation work at first. Most of the durations we might use in UI animation work are far under this five second threshold individually. But there are some common patterns where this would apply. For example: auto-advancing carousels or slideshows, animated backgrounds, or animated illustrations. While each individual animation within these patterns might still be very short, the overall motion that is created often plays out over more than five seconds. This is especially true when these are designed to play on an infinite loop, which is most definitely longer than five seconds.

How to meet the Pause, Stop, Hide criteria

If you have some of these longer playing animations, you’ll need to add some kind of pause and play controls that allow users to control the motion and/or auto playing behaviour. The WCAG specification doesn’t dictate what these controls need to look like though, you have complete design control over that.

A good example of this in practice is how the article series “Dark Side of The Grid” handles the example animations. Each animated figure loops infinitely once it starts, so they provide a play/stop button for readers to play the animation when they want to see it, and stop it when they’re done. Other more decorative or illustrative animations in the article play once and then present a button to replay them, if users want to. The placement and design of the buttons also fits the aesthetic of the overall design of the article which makes them both functional and aesthetically pleasing. 

Animated GIFs are something to look out for too. If you’ve got a looping animated GIF, that’s going to need some sort of pause/play controls to successfully meet this criteria. Both of the techniques mentioned in this post are helpful for pulling that off. 

There are some exceptions for this recommendation, as noted by the WCAG. One exception specifically worth noting is loaders and preloaders.

Three flashes or below threshold 

This recommendation is one that probably has the most research behind it because it stems from the days of broadcast TV. The main reason behind this recommendation is that significant flashing on screen has been known to trigger seizures.

In short three flashes or below threshold states: 

Web pages do not contain anything that flashes more than three times in any one second period, or the flash is below the general flash and red flash thresholds.

How to meet the three flashes or below threshold criteria

The WCAG provides details on the size, ratio and viewing angle thresholds under which flashing the screen could be considered safe. But for most of us, it’s probably easiest to avoid anything that flashes more than three times in one second. I don’t think many UX designers set out to flash the screen excessively on purpose, but it can happen. For example, a design that’s going for a video game sort of feel or a glitchy vibe might involve some screen flashing that happens more frequently than three times in a second. 

One specific example of a design that includes a significant amount of flashing is this article from the Huffington Post, pictured below. It’s a highly stylized piece on how millennials have a tougher go at things like jobs and saving for retirement than previous generations. Its  glitchy 8-bit video game design is very on point with the theme of the article. Design-wise, it’s a great choice for the subject matter and is well executed. But there are times, as you can see from the frame-by-frame stills below, where the text color flashes more than three times a second. 

This amount of flashing could be problematic for people with epilepsy or other physical reactions triggered by flashing. To their credit, the Huffington Post also provided a text-only version of the article for anyone sensitive to flashing, as Eileen mentions in this post, as well as advanced warning of the potential flashing hazard.

In general, avoiding effects that require frequent flashing is the safest way to meet this criteria. However, If you can’t avoid flashing animations in your project the WCAG provides detailed instructions around the safe thresholds for flashing the screen. Also, providing advanced warning of flashing content and an alternate version of the content without the flashing effect (like the example above) is a good thing to do as well.  

The A, AA, and AAA levels of the WCAG 

The WCAG has multiple levels of criteria and conformance, which is why each recommendation has a notation of what level it falls under. Level A compliance is the minimum level of conformance. Level AA is the middle level of conformance and indicates that the criteria for both level A and AA have been met. Level AAA is the highest level of conformance and requires satisfying the criteria from level A, AA and AAA. Typically, the guidelines found in level AAA require additional effort to meet. (If you want to learn more about these levels and what’s included in them outside of the animation-related recommendations we’re covering here, I’ve put together a list of helpful resources at the end of this article.) 

In general, most people are aiming for level AA compliance when they say they are making an accessible website. This is also the level you might see requested in an RFP or project brief. The last two guidelines we discussed fall under the level AA criteria and, therefore, must be met to claim level AA compliance. The next guideline, however, is part of the level AAA criteria. Even though it’s outside of the typical level of conformance, it’s a very useful recommendation to take into consideration if your project relies significantly on animation. I highly recommend implementing it in your work.

Animation from interactions 

This guideline covers a different kind of animation than the previous two. While the first two are generally applied to animation that’s initiated by the web page itself, this one applies to animation initiated by user interaction. More specifically, it states: 

Motion animation triggered by interaction can be disabled, unless the animation is essential to the functionality or the information being conveyed.

At first read, the term “motion animation” can be confusing since we typically use the terms “motion” and “animation” interchangeably. It might seem overly specific at first, but it makes sense to get this specific in this case. The WCAG defines motion animation as animation that is used to ”create the illusion of movement”, and specifies that “motion animation does not include changes of color, blurring or opacity.”

Essentially, the term motion animation is used to indicate that certain types of animation create the sense of movement, while others do not. It’s those animations that create a sense of movement that concerns this guideline. It’s important to keep that distinction in mind when discussing animation and accessibility to help make sure you focus your efforts efficiently. If we were to express this distinction in a very eyeball-like Venn Diagram, it would look  like this:

Over the last few years, we’ve come to realize that some types of motion on screen, even as part of an interface, can cause people with motion sensitivities to become physically ill. So this is why we might want to consider creating a reduced motion mode in our  work. I wrote more about the kinds of motion effects that are most likely to be triggering in this article, and this post from the WebKit blog covers some examples in detail.

How to meet the animation from interactions criteria

The WCAG suggests we avoid unnecessary animation, provide a control for users to turn off any non-essential motion, or take advantage of the reduced motion setting in operating systems and user agents. Let’s look at each of these in a bit more detail. There are a few different things we can do to help avoid exposing people to animation that might make them dizzy, nauseous, or worse.

Avoid unnecessary animation

Context and expectations also play a role here. The amount of motion you might reasonably expect to encounter on a website for a movie or video game is very different from what you might reasonably expect to encounter on say a government site or construction company’s site. The same amazing effects that might fit in just fine on a video game’s site would feel unnecessary or out of place on, say, a government website. Consider the context and expectations that apply to your site and whether the amount of animation you’re using in your design fits that context. 

Provide a way for users to turn off potentially problematic motion animation

If you have motion in your product that might be a trigger for folks with motion sensitivities, providing a way for users to avoid those triggering animations is the responsible thing to do. Based on the WCAG’s definition, any effect that could be considered motion animation should be one that includes a reduced version. 

Parallax effects are a good example. Those are universally problematic for folks with motion sensitivities based on my own research, yet it’s also still a very popular technique. While it wouldn’t be realistic to call for an end to all parallax effects entirely, implementing parallax responsibly requires giving your users some level of control to turn off that triggering motion. 

Typically, this is interpreted as including a toggle, setting, or preference for users to indicate their preference for reduced motion, and providing reduced versions of those motion animation effects when it’s activated. The Netlify 1 Million Devs site is one example of a motion toggle in action, and the official Animal Crossing site has one too.

Take advantage of the reduce motion feature 

Sites or apps that don’t rely heavily on large amounts of motion might find that a custom toggle isn’t the right strategy for them, and instead use the prefers-reduced-motion media query on its own. This allows you to provide a reduced version of highly animated content when that preference is present globally via the user’s operating system. It’s also a setting they can set in one place and have it affect a variety of content they encounter. That makes it a great tool for us to use to detect and respond to a user’s need for reduced motion. 

I’ve written about using prefers-reduced-motion in detail over at Smashing Magazine, and it’s also been covered by other articles on this site. In short, it allows us to access someone’s OS-level motion preference via a media query. We can access it in CSS or JavaScript and use the returned value to provide a reduced motion experience for those who want it. For example, we could do this to create a reduced motion variation of a bouncing CSS animation:  

/* A constant bouncing motion effect applied to the title */ h2 { animation: bouncing 1.5s linear infinite alternate; } /* Replace it with a safer effect when prefers-reduced-motion returns true */ @media (prefers-reduced-motion: reduce) { h2 { animation: fade 0.5s ease-in both; } } CodePen Embed Fallback

Some sites opt to use both a custom toggle and reduced motion preferences together. If you go to the site with reduced motion requested in your operating system settings, you automatically get the reduced motion mode. This two-pronged approach is a great strategy for sites with large amounts of motion. Marcy Sutton covers the basics of how to set up this approach in her course, as well as in this CodePen demo

Use these guidelines for your next animation project

There you have it, everything the WCAG says about animation explained in one place. I hope this article will help you to confidently make your web animation work accessible. Sometimes it takes a little extra effort, but that extra effort is totally worth it when it means you’ve expanded the number of people who can meaningfully interact with your site.

This article focused on the recommendations specific to animation, but animation isn’t the only place in our work where accessibility considerations can make a big impact. There are some great resources on accessibility out there that cover a more holistic view on accessibility. One of my favorites is the book Accessibility for Everyone by Lara Kalbag. Sites like WebAIM and the A11y Project are great ones to check out for a wealth of resources. If you’re doing a lot of your animation work with SVG, Heather’s SVG accessibility article is a good resource as well. I highly recommend checking out these resources if you haven’t already. 

The post Accessible Web Animation: The WCAG on Animation Explained appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.


Css Tricks - Tue, 09/22/2020 - 4:56am

Super cool project from Bennett Feely! It makes any web type into 3D lettering with a mouseover effect that moves the 3D objects in space. It’s reminiscent of Zdog, but for type. It works its magic by stacking a bunch of copies of the glyphs on top of each other that are offset by some translateZ, then using some perspective and rotateX/rotateY on a parent element to do the interactive stuff.

The effect is extremely fun. I can’t believe Fisher-Price hasn’t already implemented it site-wide.

Accessibility-wise, I have some questions. Even in the <h1> on the website, it turns into eight <h1> elements, which I can’t image is super great for screen readers, not to mention the slew of <span> elements inside. I’d think you could mitigate some of the problem with a single parent wrapper using an aria-label, yes?

Copy and paste also has weird results. If I copy, like, straight across a word, I tend to get just what I want. But if I copy from before the word to after it, I’ll get all the extra copies, which I definitely do not want. Maybe that’s fixable with some user-select: none; dancing.

It’s not just type, either! Bennet’s example on an <img> is neat in how it makes like printing a photo on (real world) canvas and stretching it around the frame so that even the edges have color.

My favorite is how it looks on <svg> though. So cool.

CodePen Embed Fallback

Direct Link to ArticlePermalink

The post ztext.js appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Thinking About Power Usage and Websites

Css Tricks - Mon, 09/21/2020 - 12:18pm

Gerry McGovern asked if I had any insight into energy consumption and websites. He has a book, after all, about the digital costs on the planet. He was wondering about the specifics of web tech, like…

If you do this in HTML it will consume 3× energy but if you do it in JavaScript it will consume 10×.

I would think if you really looked, and knew exactly how to measure it, you could find examples like that. Say I wanted to move an element across the screen. If I wrote a setInterval loop in JavaScript that incremented the left position on the relative-positioned element by one millisecond, I’m 99% sure that takes more literal electricity to do than if you were to do a CSS @keyframes animation over the same time where you changed the transform: translateX() value. In that example, usually, we’re thinking about performance moreso than energy consumption, but that’s interesting right away: does good performance map to lower energy usage? Probably.

Researches have looked into this.

We discover a statistically significant negative correlation between performance scores and the energy consumption of mobile web apps (with medium to large effect sizes), implying that an increase of the performance score tend to lead to a decrease of energy consumption.

They were testing mobile web apps on Android using Lighthouse scores. I can guess that maps pretty well to other platforms and other performance metrics.

I’m glad the research so far maps to what I would logically expect to be true. Things that lead to poor performance are things that take energy. Imagine images. You’ll be dinged on performance scores for serving too large or unoptimized images. Imagine the performance implications of that. There are two images sitting on a server, a large one and a small one. Which one takes more electricity to travel to some user’s computer? The large one. Which one takes more processing power to parse and display? The large one. Which one occupies more memory (which uses electricity) for the duration of it’s life on screen? The large one.

The less across the network, the less electricity.

The less your browser has to do, the less electricity.

Some ad that auto-refreshes itself every few seconds? Not only is it annoying, but it’s bandwidth-wasteful and thus wasteful with electricity. Whenever you have to resort to polling (i.e. making a network request over and over) rather than something event-based like web sockets? That’s using electricity that you may not have needed to use.

We know that CDNs are good for performance too. Rather than a file (like an image) needing to travel across the world, it comes from a server much geographically closer on a server designed for that job. This is where things get a little more murky to me.

With performance as our goal: objective achieved. With low-energy consumption as our goal, are we there?

It has been studied, but unfortunately, I can’t tell what the conclusion is from the abstract alone. In my mind, things are complicated by the fact that servers around the world are storing copies of these assets, and when the assets change, it’s not just one server where they update, but again, servers around the world. There has got to be a balance between the propagation and duplicative storage as far as the savings that would be realized by the efficiency of saving requests.

Speaking of storage efficiency, I’m certain that storage just sitting on disk takes a lot less electricity than files being sent over networks — but it still has a cost. Say you saved a copy of every file every time you changed it. Say you saved a complete copy of your website every time you deployed it. Useful? Sure. Does that cost electricity? It must. There must be some balance to strike there.

Gerry was asking me about particular technologies though. I can think of another big deal thing in CSS land: dark mode! Yet again, it’s been studied. Dark mode saves power.

Dark Mode can indeed reduce the display power draw by up to 58.5% at full brightness for the set of popular Android apps that we tested! In terms of whole phone battery drain reduction, that translates into 5.6% to 44.7% savings at full brightness and 1.8% to 23.5% savings at 38% brightness.

And what about comparing technologies? I suspect it’s far more about what that technology (or language) is doing than the language itself. For example, I can build a little area that opens and closes in HTML with a <details> element. Is that more energy-efficient than creating that area by attaching a click handler on a button that toggles the class of an element that visually opens and closes it? I kinda doubt it. I’d bet the electricity being used in the re-paint/re-render steps that the browser is doing and the languages behind it are less relevant. And yet! If I made the browser download a 50 KB JavaScript library just to implement my little open/close element, then yes, it does matter, and the JavaScript version is less efficient.

In that way, just as good performance generally maps to less energy consumption, I’d bet that adhering to the rule of least power generally maps to less energy consumption as well.

Sick of me guessing at stuff? Fair enough.

Jack Lenox’s article “How Improving Website Performance Can Help Save The Planet” on Smashing is a better deep dive. He points to websites that will test your site. Website Carbon Calculator is one example and it states:

Calculating the carbon emissions of website is somewhat of a challenge, but using five key pieces of data we can make a pretty good estimate:

1. Data transfer over the wire
2. Energy intensity of web data
3. Energy source used by the data centre
4. Carbon intensity of electricity
5. Website traffic

The testing code is open source.

The post Thinking About Power Usage and Websites appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.


Css Tricks - Mon, 09/21/2020 - 10:57am

Nova is a new (vehemently macOS-only) code editor from Panic, the folks behind Coda. It’s like “Coda 3” except this was such a major re-write that they gave it a whole new name.

I played with some of the betas as they were building it. I got a little discount as it went live, so I bought it and am using it here and there. Here’s my thought dump!

Like a lot of other people, I’m on the VS Code train. VS Code is very good and free. I work on a team where everyone else also uses VS Code. It’s going to be hard to dislodge my VS Code muscle memory. I’ve written about switching code editors before. The short story:

  1. Nothing can be obnoxious up front. As in, I can re-learn things after the transition.
  2. There has to be some killer feature that makes it appealing.

I really, really like Prettier and Emmet. If I couldn’t have those, I’d be out for sure. Fortunately, they are some of the top extensions.

I picked out a few I know I’ll want.

The default expansion for Emmet is Ctrl-E though, and it doesn’t work with Tab expansion (as far as I can tell), which isn’t my favorite. It does have all the extra fancy things Emmet can do though, which you can map to whatever keys you want.

The key binding setup is great. I was able to map all the things I’m used to, like setting Command-T to “Open Quickly” which is like the “Go to file…” setup in VS Code.

I have nearly 30 VS Code extensions activated. They all add some little nicety to VS Code for me specifically. I haven’t missed any of them yet. It would be a bonus to me if the default behavior of Nova was so good off the shelf that it didn’t need as many third-party tweaks (aside from the two biggies I already mentioned). For example, I don’t need a plugin to make my indendations all rainbow-ified because they already are!

But notice the JSX isn’t particularly well highlighted even though it’s on the right syntax.

“Find-in-project” is something I do at least a dozen times a day, so that’s something that needs to work tremendously well for me. My only issue so far is that it seems get stuck on “Indexing Files…” for me quite a bit (or feels stuck because it gets the ol’ fan spinning). That said, it seems to return good search results.

The Mac-ness of Nova is very, very strong. Scoping the “find-in-project” search results (say to only return *.js files) requires creating a new search scope. I can save that scope with a custom name which is a neat idea, but it has the very verbose UI-heavy search scoping from the MacOS Finder rather than a quick input field where I can quickly type *.js to scope results. In other words, it just feels like an example of emphasizing Mac-y-ness over usefulness.

Another mega Mac-y-ness thing is right-clicking a folder to open the file browser: it’s exactly like right-clicking a folder in the Finder. It’s comforting in a way, because that menu has a lot of powerful things in it.

But it also lacks things that might be contextually useful. For example, I miss an option to “Open this folder in a terminal window.”

The UI details are very nice. Selecting of coding font preferences is wonderful. The minimap looks great with little colored rectangles representing your code. The window and editor themes are very well done. Everything about the UI is just super classy.

It’s still a successor to Coda, so if you need to SFTP into remote servers and do direct editing, that’s there. I just had to do it the other day to edit a file I intentionally keep out of git, so that feature is still handy at times.

That’s a remote file system.

I otherwise would have used Coda for that, and didn’t even have to set it up for Nova because Panic Sync brought over all that auth info.

I do kind of dig that there is a built-in browser (Safari, of course). I’m wondering if I can get the muscle memory to be able to work within just this one application only without having to do much window-juggling. That means file browser, code editor, terminal, browser, and DevTools.

It’s a lot to see at once, but… kinda cool? I wish it had the option to use Chromium built-in as I happen to be more familiar with those DevTools There are some rough edges too, like my little tmux session in the terminal doesn’t respond to click events.

It’s interesting that Swift isn’t a built-in language. I would have guessed Panic even wrote at least parts of Nova in Swift given its Mac-y-ness.

If nothing else, you should check out the Nova landing page for all the CSS trickery! The animated clip-path on the image illustrating Nova’s themes is super cool (I heard clip-path animations are hardware accelerated in Safari, which is great!). It’s just some images stacked on top of each other all sharing the same animation, staggered out:

@keyframes wipe { 0% { clip-path: polygon(-50% 0%, 0% 0%, -50% 101%, -100% 101%) } 100% { clip-path: polygon(150% 0%, 200% 0%, 150% 101%, 100% 101%) } } /* ... */ img#interface1 { animation-delay: -17000ms; } img#interface2 { animation-delay: -15000ms; } img#interface3 { animation-delay: -13000ms; } img#interface4 { animation-delay: -11000ms; }

The <hr> though… that’s just gorgeous:

CodePen Embed Fallback

Oh, and check out the use of the display-p3 color format!

The post Nova appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Vue 3

Css Tricks - Fri, 09/18/2020 - 1:55pm

It’s out! Congrats to the Vue team for getting it done, I know it was a massive effort and a long time coming. All new docs, as well.

I like it’s still a priority that Vue can be used with just a <script> tag with no build process at all. But it’s ready for build processes too.

Vue 3.0 core can still be used via a simple <script> tag, but its internals has been re-written from the ground up into a collection of decoupled modules. The new architecture provides better maintainability, and allows end users to shave off up to half of the runtime size via tree-shaking.

If you specifically want to have a play with Vue Single File Components (SFCs, as they say, .vue files), we support them on CodePen in our purpose-built code editor for them. Go into Pen Settings > JavaScript and flip Vue 2 to Vue 3.

The train keeps moving too. This proposal to expose all component state to CSS is an awfully cool idea. I really like the idea of CSS having access to everything that is going on on a site. Stuff like global scroll and mouse position would be super cool. All the state happening on any given component? Heck yeah I’ll take it.

The post Vue 3 appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Enforcing performance budgets with webpack

Css Tricks - Fri, 09/18/2020 - 4:59am

As you probably know, a single monolithic JavaScript bundle — once a best practice — is no longer the way to go for modern web applications. Research has shown that larger bundles increase memory usage and CPU costs, especially on mid-range and low-end mobile devices.

webpack has a lot of features to help you achieve smaller bundles and control the loading priority of resources. The most compelling of them is code splitting, which provides a way to split your code into various bundles that can then be loaded on demand or in parallel. Another one is performance hints which indicates when emitted bundle sizes cross a specified threshold at build time so that you can make optimizations or remove unnecessary code.

The default behavior for production builds in webpack is to show a warning when an asset size or entry point is over 250KB (244KiB) in size, but you can configure how performance hints are shown and size thresholds through the performance object in your webpack.config.js file.

Production builds will emit a warning by default for assets over 250KB in size

We will walk through this feature and how to leverage it as a first line of defense against performance regressions.

First, we need to set a custom budget

The default size threshold for assets and entry points (where webpack looks to start building the bundle) may not always fit your requirements, but they can be configured to.

For example, my blog is pretty minimal and my budget size is a modest 50KB (48.8KiB) for both assets and entry points. Here’s the relevant setting in my webpack.config.js:

module.exports = {   performance: {     maxAssetSize: 50000,     maxEntrypointSize: 50000,   } };

The maxAssetSize and maxEntrypointSize properties control the threshold sizes for assets and entry points, respectively, and they are both set in bytes. The latter ensures that bundles created from the files listed in the entry object (usually JavaScript or Sass files) do not exceed the specified threshold while the former enforces the same restrictions on other assets emitted by webpack (e.g. images, fonts, etc.).

Let’s show an error if thresholds are exceeded

webpack’s default warning emits when budget thresholds are exceeded. It’s good enough for development environments but insufficient when building for production. We can trigger an error instead by adding the hints property to the performance object and setting it to 'error':

module.exports = {   performance: {     maxAssetSize: 50000,     maxEntrypointSize: 50000,     hints: 'error',   } }; An error is now displayed instead of a warning

There are other valid values for the hints property, including 'warning' and false, where false completely disables warnings, even when the specified limits are encroached. I wouldn’t recommend using false in production mode.

We can exclude certain assets from the budget

webpack enforces size thresholds for every type of asset that it emits. This isn’t always a good thing because an error will be thrown if any of the emitted assets go above the specified limit. For example, if we set webpack to process images, we’ll get an error if just one of them crosses the threshold.

webpack’s performance budgets and asset size limit errors also apply to images

The assetFilter property can be used to control the files used to calculate performance hints:

module.exports = {   performance: {     maxAssetSize: 50000,     maxEntrypointSize: 50000,     hints: 'error',     assetFilter: function(assetFilename) {       return !assetFilename.endsWith('.jpg');     },   } };

This tells webpack to exclude any file that ends with a .jpg extension when it runs the calculations for performance hints. It’s capable of more complex logic to meet all kinds of conditions for environments, file types, and other resources.

The build is now successful but you may need to look for a different way to control your image sizes. Limitations

While this has been a good working solution for me, a limitation that I’ve come across is that the same budget thresholds are applied to all assets and entry points. In other words, it isn’t yet possible to set multiple budgets as needed, such as different limits for JavaScript, CSS, and image files.

That said, there is an open pull request that should remove this limitation but it is not merged yet. Definitely something to keep an eye on.


It’s so useful to set a performance budget and enforcing one with webpack is something worth considering at the start of any project. It will draw attention to the size of your dependencies and encourage you to look for lighter alternatives where possible to avoid exceeding the budget.

That said, performance budgeting does not end here! Asset size is just one thing of many that affect performance, so there’s still more work to be done to ensure you are delivering an optimal experience. Running a Lighthouse test is a great first step to learn about other metrics you can use as well as suggestions for improvements.

Thanks for reading, and happy coding!

The post Enforcing performance budgets with webpack appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Optimizing CSS for faster page loads

Css Tricks - Thu, 09/17/2020 - 12:18pm

A straightforward post with some perf data from Tomas Pustelnik. It’s a good reminder that CSS is a crucial part of thinking web performance, and for a huge reason:

Any time [the browser] encounters any external resource (CSS, JS, images, etc.) it will assign it a download priority and initiate its download. Priorities are important because some resources are critical to render a page (eg. main stylesheet and JS files) while others may be less important (like images or stylesheets for other media types).

In the case of CSS, this priority is usually high because stylesheets are necessary to create CSSOM (CSS Object Model). To render a webpage browser has to construct both DOM and CSSOM.

That’s why CSS is often referred to as a “blocking” resource. That’s desirable to some degree: we wouldn’t want to see flash-of-unstyled-websites. But we get real perf gains when we make CSS smaller because it’s quicker to download, parse, and apply.

Aside from the techniques in the post, I’m sure advocates of atomic/all-utility CSS would love it pointed out that the stylesheets from those approaches are generally way smaller, and thus more performant. CSS-in-JS approaches will sometimes bundle styles into scripts so, to be fair, you get a little perf gain at the top by not loading the CSS there, but a perf loss from increasing the JavaScript bundle size in the process. (I haven’t seen a study with a fair comparison though, so I don’t know if it’s a wash or what.)

Direct Link to ArticlePermalink

The post Optimizing CSS for faster page loads appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Weaved Webs

Css Tricks - Wed, 09/16/2020 - 12:16pm

There is a bit of an irony with Jamstack.

The concept is simple: you put pre-rendered, static files on web hosting (a CDN) designed to do that well. That’s it. If you need to do more, anything you do from there is done with client-side JavaScript, which is likely talking to serverless functions because that’s the spiritual partner to Jamstack on the back end. I heard Guillermo Rauch say at Smashing Conf the other day that it isn’t exactly a “stack” in that it’s almost entirely non-prescriptive in what you do. While I like the word Jamstack, that also feels fair.

The irony is that while the concept is simple, that simplicity can be the cause of complexity.

Netlify, the company largely behind Jamstack, knows this. They know that without a back-end server with back-end languages, something like a basic contact form gets complicated. Instead of being in no-brainer solved-problem territory, we have to figure out another way to process that form. So, they solve that problem for you (among others, like auth and serverless functions). But there are tons of other companies that want to be that cog in your machine.

That’s just one potential complication. What do you use for a CMS or other data storage? What is your build process like? How do you see previews of content changes? How do you do auth? What if you need some fancy calendar widget? What if you want to sell something? Anything a website can do, Jamstack has an answer for — it’s just that combining all those answers can feel disjointed and potentially confusing.

Dave recently played with Eleventy + Tailwind + Netlify CMS (which is Jamstack-y) and said it felt like cattle herding:

So my little mashup, which was supposed to be just 3 technologies ended up exposing me to ~20 different technologies and had me digging into nth-level dependency source code after midnight. If there’s an allegory for what I don’t like about modern-day web development, this is it. You want to use three tools, but you have to know how to use twenty tools instead. If modules and components are like LEGO, then this is dumping out the entire bin on the floor just to find one tiny piece you need.

“The tangled webs we weave,” indeed.

In a conversation between Richard MacManus and Matt Mullenweg¹, Richard quotes Matt:

You can patch together a dozen services, each with its own account and billing, for hundreds of dollars a month, to get a similar result you’d have for a few dollars a month using WordPress on shared hosting,” he said. “And it would be more fragile, because the chain is only as strong as its weakest link. You are chaining together different toolsets, logins, billing, hosting… any part of it going down can break the entire flow.

If I was considering Jamstack for a particular project, and the grand total really was twelve services, I probably would reconsider, particularly if I could reach for a tool like WordPress and bring it down to one. There are plenty of other fair criticisms of Jamstack, particularly since it is early-days. The story of “CMS with Preview” isn’t particularly great, for example, which is a feature you don’t even think about with WordPress because, duh, obviously it has that.

And Jamstack can do some things that are very ahead of the game that I cherish. Git-based deployment? All websites should have that. Previews of my pull requests? Hot damn. Sub -100-millisecond first requests? Yes please. Not having to diddle with cache? Sweet. Catch up, other stacks.

I’m saying there are baby bear choices to be made here. You get there by doing what you’re probably already doing anyway: putting your adult pants on, thinking about what your project needs, and choosing the best option.

I have production WordPress sites. Like this one! It’s great!

I have production Jamstack sites. Like this one! It’s not a complicated web of services. It’s a static site generator with content in the GitHub repo deployed with Netlify. While CSS-Tricks can do about 100 things that this site can’t, it has a few tricks up its sleeve that CSS-Tricks can’t do, like accept pull requests on content.

I feel like I’ve chosen pretty well in all my cases.

  1. While Matt is clearly incentivized to defend the WordPress approach, it feels to me the opinions here are genuine; in part because Automattic invests in alternative stack approaches, and that WordPress and Jamstack are not mutually exclusive. I enjoyed responses to this, like Ohad Eder-Pressman’s open letter, which is also full of incentivized-but-genuine thoughts.

The post Weaved Webs appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Lessons Learned from Sixty Days of Re-Animating Zombies with Hand-Coded CSS

Css Tricks - Wed, 09/16/2020 - 4:56am

Caution: Terrible sense of humor ahead. We’ll talk about practical stuff, but the examples pretty much all involve zombies and silly jokes. You have been warned.

I’ll be linking to individual Pens as I discuss the lessons I learned, but if you’d like to get a sense of the entire project, check out 60 days of Animation on Undead Institute. I started this project to end on August 1st, 2020, coinciding with the publication of a book I wrote featuring CSS animation, humor, and zombies — because, obviously, zombies will destroy the world if you don’t brandish your web skills and stop the apocalypse. Nothing puts the hurt on the horde like a HTML element on the move!

I had a few rules for myself throughout the project. 

  1. I would hand-code all CSS. (I’m a masochist.)
  2. The user would initiate all of the animation. (I hate coming upon an animation that’s already halfway through.) 
  3. I would use JavaScript as little as possible and never for animation. (I only ended up using JavaScript once, and that was to start audio with the final animation. I have nothing against JavaScript, it’s just not what I wanted to do here.)
Lesson 1: Eighty days is a long time.

Uh, doesn’t the title say “sixty” days? Yes, but my original goal was to do eighty days and as day one approached with less than twenty animations prepared and a three day average for each production, I freaked out and switched to sixty days. That gave me both twenty more days till the beginning date and twenty fewer pieces to do.

Lesson 1A: Sixty days is still a long time.

That’s a lot of animation to do with a limited amount of time, ideas, and even more limited artistic skills. And while I thought of dropping to thirty days, I’m glad I didn’t. Sixty days stretched me and forced me to go deeper into how CSS animation — and by extension, CSS itself — works. I’m also proudest of many of the later pieces I did as my skills increased, and I had to be more innovative and think harder about how to make things interesting. Once you’ve used all the easy options, the actual work and best results begin. (And yes, it ended up being sixty-two days because I started on June 1 and wanted to do a final animation on August 1. Starting June 3 just felt icky and wrong.)

So, the real Lesson 1: stretch yourself.

Lesson 2: Interactive animations are hard, and even harder to make responsive. 

If you want something to fly across the screen and connect with another element or appear to start another element’s move, you must use either all standard, inflexible units or all flexible units. 

Three variables determine when and where an animated element will be during any animation: duration, velocity, and distance. The duration of the animation is set in the animation property and cannot be changed in relation to screen size. The animation timing function determines the velocity; screen size can’t change that either. Thus, if the distance varies with the screen size, the timing will be off everywhere except a specific screen width and height. 

Look at Tank!. Run the animation at wide and narrow screen sizes. While I got the timing close, if you compare the two, you’ll see that the tank is in a different place relative to the zombies when the last zombies fall.

To avoid these timing issues, you can use fixed units and a large number, like 2000 or 5000 pixels or more, so that the animation will cover the width (or height) of the screen for all but the largest monitors.  

Lesson 3: If you want a responsive animation, put everything in (one of the) viewport units. 

Going halfsies on unit proportions (e.g. setting width and height in pixels, but location and movement with viewport units) will lead to unpredictable results. Don’t use both vw and vh either but one or the other; whichever will be the dominant orientation. Mixing vh and vw units will make your animation go “wonky” which I believe is the technical term. 

Take Superbly Zomborrific, for instance. It mixes pixel, vw, and vh units. The premise is that the Super Zombie is flying upward as the “camera” follows. Super Zombie smashes into a ledge and falls as the camera continues, but you wouldn’t understand that if your screen was sufficiently tall.

That also means that if you need something to come in from the top — like I did in Nobody Here But Us Humans —you must set the vw height high enough to ensure that the ninja zombie isn’t visible at most aspect ratios.

Lesson 3A: Use pixel units for movements within an SVG element. 

All that said, transforming elements within an SVG element should not use viewport units. SVG tags are their own proportional universe. The SVG “pixel” will stay proportional within the SVG element to all the other SVG element children while viewport units will not. So transform with pixel units within an SVG element, but use viewport units everywhere else.

Lesson 4: SVGs scale horribly at runtime.

For animations, like Oops…, I made the SVG image of the zombie scale up to five times his size, but that makes the edges fuzzy. [Shakes fist at “scalable” vector graphics.]

/* Original code resulting in fuzzy edges */ .zombie {   transform: scale(1);   width: 15vw; } .toggle-checkbox:checked ~ .zombie {   animation: 5s ease-in-out 0s reverseshrinkydink forwards; } @keyframes reverseshrinkydink {   0% {     transform: scale(1);   }   100% {     transform: scale(5);   } }

I learned to set their dimensions to the final dimensions that would be in effect at the end of the animation, then use a scale transform to shrink them down to the size for the start of the animation. 

/* Revised code */ .zombie {   transform: scale(0.2);   width: 75vw; } .toggle-checkbox:checked ~ .zombie {   animation: 5s ease-in-out 0s reverseshrinkydink forwards; } @keyframes reverseshrinkydink {   0% {     transform: scale(0.2);   }   100% {     transform: scale(1);   } }

In short, the revised code moves from a scaled-down version of the image up to the full width and height. The browser always renders at 1, making the edges crisp and clean at a scale of 1. So instead of scaling from 1 to 5, I scaled from 0.2 to 1.

Lesson 5: The axis Isn’t a universal truth. 

An element’s axes stay in sync with the element, not the page. A 90-degree rotation before a translateX will change the direction of the translateX from horizontal to vertical. In Nobody Here But Us Humans… 2, I flipped the zombies using a 180-degree rotation. But positive Y values move the ninjas towards the top, and negative ones move them towards the bottom (the opposite of normal). Beware of how a rotation may affect transforms further down the line.

Lesson 6. Separate complex animations into concentric elements to make easier adjustments.

When creating a complex animation that moves in multiple directions, adding wrapper divs, or rather parent elements, and animating each one individually will cut down on conflicting transforms, and prevent you from becoming a weepy mess.

For instance, in Space Cadet, I had three different transforms going on. The first is the zomb-o-naut’s moving in an up and down motion. The second is a movement across the screen. The third is a rotation. Rather than trying to do everything in a single transform, I added two wrapping elements and did one animation on each element (I also saved my hair… at least some of it.) This helped avoid the axis issues discussed in the last lesson because I performed the rotation on the innermost element, leaving its parent’s and grandparent’s axes in place.

Lesson 7: SVG and CSS transforms are the same. 

Some paths and groups and other SVG elements will already have transforms defined on them. It could be from an optimization algorithm, or perhaps it’s just how the illustration software generates the code. If a path, group, or whatever element in an SVG already has an SVG transform on it, removing that transform will reset the element, often to a bizarre location or size compared to the rest of the drawing. 

Since SVG and CSS transforms are the same, any CSS transform you do replaces the SVG transform, meaning your CSS transform will start from that bizarre location or size rather than the location or size that is set in the the SVG.

You can copy the transform from the SVG element to your CSS and set it as the starting position in CSS (updating it to the CSS syntax first, of course). You can then modify it in your CSS animation.

For instance, in Uhhh, Yeah…, my tribute to Office Space, Undead Lumbergh’s right upper arm (the #arm2 element) had a transform on it in the original SVG code.

<path id="arm2" fill="#91c1a3" fill-rule="nonzero" d="M0 171h9v9H0z" transform="translate(0 -343) scale(4 3.55)"/>

Moving that transform to CSS like this:

<path id="arm2" fill="#91c1a3" fill-rule="nonzero" d="M0 171h9v9H0z"/> #arm2 {   transform: translate(0, -343px) scale(4, 3.55); }

…I could then create an animation that doesn’t accidentally reset the location and scale:

.toggle-checkbox:checked ~ .z #arm2 {    animation: 6s ease-in-out 0.15s arm2move forwards; } @keyframes arm2move {   0%, 100% {     transform: translate(0, -343px) scale(4, 3.55);   }   40%, 60% {     transform: translate(0, -403px) scale(4, 3.55);   }   50% {     transform: translate(0, -408px) scale(4, 3.55);   } } 

This process is harder when the tool generating the SVG code attempts to “simplify” the transform into a matrix. While you can recreate the matrix transform by copying it into the CSS, it is a difficult task to do. You’re a better developer than me — which might be true anyway — if you can take a matrix transform and manipulate it to scale, rotate, or translate in the exact way you want.

Alternatively, you can recreate the matrix transform using translation, rotation, and scaling, but if the path is complex, the likelihood that you can recreate it in a timely manner without finding yourself in a straight jacket is low. 

The last and probably easiest option is to wrap the element in a group (<g>) tag. Add a class or ID to it for easy CSS access and transform the group itself, thus separating out the transforms as discussed in the last lesson. 

Lesson 8: Keep your sanity by using transform-origin when transforming part of an SVG

The CSS transform-origin property moves the point around which the transform happens. If you’re trying to rotate an arm — like I did in Clubbin’ It —  your animation will look more natural if you rotate the arm from the center of the shoulder, but that path’s natural transform origin is in the upper-left. Use transform-origin to fix this for smoother, more natural feel… you know that really natural pixel art look…

Transforming the origin can also be useful when scaling, like I did in Mustachioed Oops, or when rotating mouth movements, such as the dinosaur’s jaw in Super Tasty. If you don’t change the origin, the transforms will use an origin point at the upper left corner of the SVG element. 

Lesson 9: Sprite animations can be responsive

I ended up doing a lot of sprite animations for this project (i.e., where you use multiple, incremental frames and switch between them fast enough that the characters seem to move). I created the images in one wide file, added them as a background image to an element the size of a single frame, used background-size to set the background image to the width of the image, and hid the overflow. Then I used background-position and the animation timing function, step(), to walk through the images; for example: Post-Apocalyptic Celebrations.

Before the project, I always used inflexible images. I’d scale things down a little so that there would be at least a little responsive give, but I didn’t think you could make it a fully flexible width. However, if you use SVG as the background image you can then use viewport units to scale the element along with the changing screen size. The only problem is the background position. However, if you use viewport units for that, it will stay in sync. Check that out in Finally, Alone with my Sandwich…

CodePen Embed Fallback Lesson 9A: Use viewport units to set the background size of an image when creating responsive sprite animation

As I’ve learned throughout this project, using a single type of unit  is almost always the way to go. Initially, I’d set my sprite’s background size using percentages. The math was easy (100% * (number of steps + 1)) and it worked fine in most cases. In longer animations, however, the exact frame tracking could be off and parts of the wrong sprite frame might display. The problem grows as more frames are added to the sprite. 

I’m not sure the exact reason this causes an issue, but I believe it’s because of rounding errors that compound over the length of the sprite sheet (the amount of the shift increases with the number of frames). 

For my final animation, It Ain’t Over Till the Zombie Sings, I had a dinosaur open his mouth to reveal a zombie Viking singing (while lasers fired in the background plus there was dancing, accordions playing and zombies fired from cannons, of course). Yeah, I know how to throw a party… a nerd party.

The dinosaur and viking was one of the longest sprite animations I did for the project. But when I used percentages to set the background size, the tracking would be off at certain sizes in Safari. By the end of the animation, part of the dinosaur’s nose from a different frame would appear to the right and a similar part of the nose would be missing on the left.

The dinosaur on the left is missing part of his left cheek and growing a new one next to his right cheek.

This was super frustrating to diagnose because it seemed to work fine in Chrome and I’d think I fixed it in Safari only to look at a slightly different screen size and see the frame off again. However, if I used consistent units — i.e. vw for background-size, frame width, and background-position — everything worked fine. Again, it comes down to working with consistent units!

Lesson 10: Invite people into the project.

While I learned tons of things during this process, I beat my head against the wall for most of it (often until the wall broke or my head did… I can’t tell). While that’s one way to do it, even if you’re hard-headed, you’ll still end up with a headache. Invite others into your project, be it for advice, to point out an obvious blind spot you missed, provide feedback, help with the project, or simply to encourage you to keep going when the scope is stupidly and arbitrarily large. 

So let me put this lesson into practice. What are your thoughts? How will you stop the zombie hordes with CSS animation? What stupidly and arbitrarily large project will you take on to stretch yourself?

The post Lessons Learned from Sixty Days of Re-Animating Zombies with Hand-Coded CSS appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Inclusive Design 24

Css Tricks - Wed, 09/16/2020 - 4:55am

Totally free.

No sign-up. No registration. All sessions are streamed live and publicly on the Inclusive Design 24 YouTube channel – see the entire playlist for the event.

Quite the lineup.

I’ve got a couple of other accessibility links burning a hole in my pocket as well:

Direct Link to ArticlePermalink

The post Inclusive Design 24 appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Editing HTML Like A Boss In VS Code

Css Tricks - Wed, 09/16/2020 - 4:50am

Here’s a seven minute video from Caleb Porzio that focuses on some of Emmet‘s HTML editing features. You might think of Emmet as that thing that expands abbreviations like table.stats>tr*3>td*3 into glorious, expanded, and perfect HTML. But Emmet has other HTML editing trickery up its sleeve. My favorite is “wrap with abbreviation” (which happens to be Cmd/Ctrl + Shift + A on CodePen), but there are more, like expanding your selection inward and outward and tag changing.

If you haven’t seen it, the Emmet 2 preview on CodePen is pretty neeeeat. It shows you what you’re about to expand into before you do it:

Direct Link to ArticlePermalink

The post Editing HTML Like A Boss In VS Code appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

What is the Value of Browser Diversity?

Css Tricks - Tue, 09/15/2020 - 9:36am

In 2018, Rachel Nabors made the point that browser diversity is similar to biological ecosystem diversity. There are literal advantages to more diversity. That article was before the Edge engines were shut, and now the big shakeups at Mozilla have the topic of browser diversity on people’s minds again.

I really like Dave’s take on the matter. The diversity of browser engines makes web tech slow. Frustratingly slow, to many, but that slowness can bring value.

There’s a lot of value in slow thinking. You use the non-lizard side of your brain. You make more deliberate decisions. You prioritize design over instant gratification. You can check your gut instincts and validate your hypothesis before incurring mountains of technical debt.

I’d bet you a dollar that the less engines we have, the faster things get. Fast can be satisfying in the moment, but doesn’t make for the best brisket.

If we do see a major reduction in browser diversity, I think we lose the intentional slowness and the cooperation mechanisms we have in place. Who knows what will happen, but my hope is that just like iron can sharpen iron, maybe chromium can sharpen chromium.

Direct Link to ArticlePermalink

The post What is the Value of Browser Diversity? appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Virtual Event Registrations with Wufoo Forms

Css Tricks - Tue, 09/15/2020 - 5:10am

(This is a sponsored post.)

We’ve seen many events shift from in-person to online this year. That may have required a huge change to how you collect attendee registrations in the past, but with a paid Wufoo account and Zoom — along with a sprinkle of Zapier — it’s easier than ever to go virtual.

First, set up a Zoom call

It doesn’t have to start right now but can be scheduled in advance so we have something to connect to. In Zoom, that’s just a click of the giants “Schedule” button on the welcome screen once the app has been launched.

“New Meeting” will launch something right away, whereas “Schedule” will set a call up in advance to start at a fitter date and time. Next, we need a registration form

We’re talking about Wufoo’s bread and butter: making online forms! We can create one from scratch, of course, but Wufoo makes it even easier with a set of pre-made options that are specifically designed for registration.

Any of these can be used as-is, or as a starting point to make your own.

Whether you start with a clean slate or a template, the key things you’re going to want to collect are:

  • Name
  • Email address

Seriously, that’s it. Anything else is icing on the cake that can be used to collect additional information about attendees, like their age, gender, shirt size, allergies, or whatever else you think will be helpful to make a better event.

Is this a paid event?

Many events are! If you want to charge a fee for the event, Wufoo integrates with Stripe, Square, PayPal and a slew of other payment gateways that make collecting payments rather trivial. Plus, transactions are protected by 256-bit SSL encryption that’s super secure and PCI-compliant.

Purchasing a single ticket is pretty straightforward, but let’s say you want to allow folks to purchase multiple tickets at a time or have multiple tiers of ticket pricing. Not a problem at all in Wufoo! For example, it’s possible to set prices by the answer provided in a field.

Now, when someone selects an option in the “Number of Tickets” field, a price will calculated. Is there a maximum number of “seats” available?

You may be cool with an unlimited number of attendees. But if you need to limit the head count, check out Wufoo’s Max Quantity feature, which is like creating a pool of tickets that each registration subtracts from. This is especially useful to create a more “intimate” presentation for, say, workshops or group activities.

The “Max Quantities” feature can restrict the number of people who can register for a specific workshop. Connect to Zoom

We’re using Zoom in this example, but Wufoo is capable of connecting to other video services, including, GoToMeeting, and Cisco Webex.

Wufoo’s integrations come by way of Zapier. If you’re new to it, Zapier is this thing that basically connects apps together, establishing communication between their APIs so that they interact with each other when something happens. In this case, when someone signs up for the virtual event, we want to add them as a guest on the Zoom call.

So, go into your Zapier account (or set one up for free). From there, we’ll create a new “zap” which Zapier’s slang for a new app connection. That means we select Wufoo as the first app we want to use and Zoom as the app we want to connect to.

Once the apps have been chosen, Zapier provides options for what to “watch for” in Wufoo (a form submission, or “New Entry” in this case) and actions we want to take place in Zoom when that trigger happens (“Create Webinar Registrant” in this case).

Click the “Use Zap” button and Zapier will walk through the rest of the steps, including what form to use in this integration and which scheduled Zoom webinar to create registrants.

Watch the registrations roll in!

Well, yes. We are technically done at this point, but we’ll want to do some housecleaning before we can actually start collecting registrations:

  • Finish designing the form. Wufoo has a lot of nice design options, and even takes custom CSS to fine-tune the way things look.
  • Embed the form. The form needs to go somewhere if we want folks to use it. A Wufoo form can be embedded just about anywhere (hey, we use on on our own Contact page). Or, simply link it up and use the public URL Wufoo generates for the form.
  • Customize the receipt email. Once a transaction is made, the user will get a receipt emailed to their inbox. It’s a good idea to give it a little love so it’s personalized.
  • Create a reminder email. Sending a reminder a few days before the event is a nice way to give folks a heads up that the event is coming up. Wufoo also integrates with both Mailchimp and Campaign Monitor, both of which can be used in a zap that adds attendees to an email list and sends triggered and automated messages.

There you go, a registration flow for a virtual event that is powerful and doesn’t require any code! If you don’t have a Wufoo account already, get one now — it’s free and worth exploring all the interesting things it can do.

Direct Link to ArticlePermalink

The post Virtual Event Registrations with Wufoo Forms appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Form design

Css Tricks - Tue, 09/15/2020 - 5:04am

A very digestable guide from Geri Reid on building forms. Not the code, but the design and UX principles that should guide the code.

Working on a design system for a bank has taught [me] a lot about forms. I’ve watched testing in our labs. I’ve worked alongside experts from specialist accessibility organisations. I’ve seen forms tested by disabled people and users of assistive technology. I’ve also read a lot of research.

From all this learning I’ve formed my own forms best-practice guidelines. 

I always think about one code-related thing when it comes to general form advice: all inputs need an attached label.

<label for="name">Name:</label> <input type="text" id="name" name="name"> <!-- or --> <label> Name: <input type="text" name="name"> </label>

It’s HTML 101 stuff, but so many forms fail to do it. I once heard a story about blind college-bound high school students who were unable to apply to college specifically because they couldn’t figure out what the inputs wanted on a form. They started second-guessing if they could do college on their own after that experience.

You know how The Onion prints the article “‘No Way To Prevent This,’ Says Only Nation Where This Regularly Happens” literally every single time there is a mass shooting? I feel like someone should make a website that publishes an article pointing to every single website that fails this one test with a headline like “‘No Way To Prevent This’, Says Website Where The Fix Would Be Typing A Handful Of Characters.”

Direct Link to ArticlePermalink

The post Form design appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Winamp Skin Museum

Css Tricks - Mon, 09/14/2020 - 1:42pm

65,000 skins, they say. That’s extraordinary, especially considering how creative and well done many of them are. MySpace was an even bigger creative explosion of customization.

What’s the next product that will inspire this kind of user ownership through theming? Allowing it isn’t terribly difficult. You allow people to write (or link up) their own CSS and, ideally, give them sensible selectors to hook onto.

Be careful you don’t open up any XSS holes. The much harder trick is building something that people want to skin. Once you’re over that hump, it’s about having enough people theming it that it starts to inspire other people to do the same.

Direct Link to ArticlePermalink

The post Winamp Skin Museum appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

content-visibility: the new CSS property that boosts your rendering performance

Css Tricks - Mon, 09/14/2020 - 11:28am

Una Kravets and Vladimir Levin:

[…] you can use another CSS property called content-visibility to apply the needed containment automatically. content-visibility ensures that you get the largest performance gains the browser can provide with minimal effort from you as a developer.

The content-visibility property accepts several values, but auto is the one that provides immediate performance improvements.

The perf benefits seems pretty big:

In our example, we see a boost from a 232ms rendering time to a 30ms rendering time. That’s a 7x performance boost.

It’s manual work though. You have to “section” large vertical chunks of the page yourself, apply content-visibility: auto; to them, then take a stab at about how tall they are, something like contain-intrinsic-size: 1000px;. That part seems super weird to me. Just guess at a height? What if I’m wrong? Can I hurt performance? Can (or should) I change that value at different viewports if the height difference between small and large screens is drastic?

Seems like you’d have to be a pretty skilled perf nerd to get this right, and know how to look at and compare rendering profiles in DevTools. All the more proof that web perf is its own vocation.

Direct Link to ArticlePermalink

The post content-visibility: the new CSS property that boosts your rendering performance appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Syndicate content
©2003 - Present Akamai Design & Development.