Chris’ Corner: Performance Talk

Category Image 052

We’ve zoomed right into 2023, so let’s keep up the pace and talk about making the web speedy.

– Chris Coyier, proffessional newsletter writer.

Uhm but anyway I do have some choice web performance links I’ve been saving up for you this week though.

Turns out HTML is good.

Perhaps my favorite performance-related post of 2022 was Scott Jehl’s Will Serving Real HTML Content Make A Website Faster? Let’s Experiment!. It makes logical sense that a website that serves all the HTML it needs to render upfront will load faster than a website that loads an HTML shell, then loads JavaScript, and the JavaScript makes subsequent requests for the data, which is turned into HTML and then rendered. But it’s nice to see it completely apples to apples. Scott took websites that serve no “useful HTML” up front, and used a new feature of WebPageTest called Opportunities & Experiments to re-run a performance test, but with manipulations in place (namely “useful HTML” instead of the shell HTML).

Serving Twitter with upfront HTML: 3.4 seconds to render. Without useful HTML upfront: 12.1 seconds.

The result is just a massive improvement in how fast the useful content renders. Server-side rendering (SSR) is just… better.

As always, Scott has a classy caveat:

Now, it’s very important to note that while the examples in this post helpfully display this pattern, the architectural decisions of these sites are made thoughtfully by highly-skilled teams. Web development involves tradeoffs, and in some cases a team may deem the initial performance impact of JS-dependence a worthy compromise for benefits they get in other areas, such as personalized content, server costs and simplicity, and even performance in long-lived sessions. But tradeoffs aside, it’s reasonable to suspect that if these sites were able to deliver meaningful HTML up-front, a browser would be able render initial content sooner and their users would see improvements as a result.

I suspect it’ll be rarer and rarer to see sites that are 100% client rendered. The best developer tooling we have includes SSR these days, so let’s use it.

Fortunately, there are all kinds of tools that point us in this direction anyway. Heavyweights like Next.js, which helps developers build sites in React, is SSR by default. That’s huge. And you can still fetch data with their getServerSideProps concept, retaining the dynamic nature of client-side rendering. Newer tech like Astro is all-in on producing HTML from JavaScript frameworks while helping you do all the dynamic things you’d want, either by running the dynamic stuff server-side or delaying client-side JavaScript until needed.

So if your brain goes well my app needs to make API requests in order to render, well now you have your answer. There are all kinds of tools to help you do those API requests server side. Myself, I’m a fan of making edge servers do those requests for you. Any request the client can do, any other server can do too, only almost certainly faster. And if that allows you to dunk the HTML in the first response, you should.

It’s all about putting yourself in that HTML-First Mental Model, as Noam Rosenthal says. Letting tools do that is a great start, but, brace yourself, not using JavaScript at all is the best possible option. I really like the example Noam puts in the article here. JavaScript libraries have taught us to do stuff like checking to see if we have data and conditionally rendering an empty state if not. But that requires manipulation of the DOM as data changes. That kind of “state” manipulation can be done in CSS as well, by hiding/showing things already in the DOM with the display property. Especially now with :has() (last week’s CodePen Challenge, by the way), this kind of state checking is getting trivial to do.

.dynamic-content-area {
  display: none;
}
.loader {
  display: block;
}

.dynamic-content-area:has(:first-child) {
  display: block;
}
.dynamic-content-area:has(:first-child) + .loader {
  display: none;
}

I like that kind of thinking.

The async attribute is the way.

Harry Roberts digs into a somewhat old JavaScript loading pattern in Speeding Up Async Snippets. Have you ever seen this?

<script>
  var script = document.createElement('script');
  script.src = 'https://third-party.io/bundle.min.js';
  document.head.appendChild(script);
</script>

We’re getting over a decade in major browsers where that pattern just isn’t needed anymore, and worse, it’s bad for performance, the very thing it’s trying to help with:

For all the resulting script is asynchronous, the <script> block that creates it is fully synchronous, which means that the discovery of the script is governed by any and all synchronous work that happens before it, whether that’s other synchronous JS, HTML, or even CSS. Effectively, we’ve hidden the file from the browser until the very last moment, which means we’re completely failing to take advantage of one of the browser’s most elegant internals… the Preload Scanner.

As Harry says:

…we can literally just swap this out for the following in the same location or later in your HTML:

<script src="https://third-party.io/bundle.min.js" async></script>

Gotta preserve that Aspect ratio on images before loading.

It’s worth shouting from the rooftops: put width and height attributes on your <img> tags in HTML. This allows the browser to preserve space for them while they load and prevent content from jerking around when they load. This is a meaningful performance benefit.

It’s actually just the aspect-ratio of those two numbers that actually matters. So even if you won’t actually display the image at the size indicated by the attributes (99% chance you won’t, because you’ll restrict the maximum width of the image), the browser will still reserve the correct amount of space.

Jake Archibald puts a point on all this.

You can achieve the same effect with aspect-ratio in CSS, but in practice, we’re talking about content <img>s here, which are usually of arbitrary size, so the correct place for this information is in the HTML. There is a little nuance to it as you might imagine, which Jake covers well.

JPEG XL, we hardly knew thee.

Speaking of images, it looks like Chrome threw in the towel on supporting the JPEG XL format for now. It was behind a flag to begin with, so no real ecosystem harm or anything. They essentially said: flags are flags, they aren’t meant to live forever. We would have shipped it, but it’s just not good enough to warrant the maintenance, and besides no other browser was that into it either.

That actually sounds pretty reasonable of Chrome at first glance. But Jon Sneyers has a full-throated response in The Case for JPEG XL to everything aside from the flags shouldn’t last forever thing. I’d consider these things pretty darn excellent:

  • JPEG XL can be used to re-encode any existing JPEG entirely losslessly and have it be 20% smaller on average. There are a boatload of JPEGs on the internet, so this seems big.
  • JPEG XL can do the progressive-loading thing, where once 15% of the data has arrived, it can show a low-res version of itself. The popularity of the “blur up” technique proves this is desirable.
  • JPEG XL is fast to encode. This seems significant because the latest hot new image format, AVIF, is quite the opposite.

So even if JPEG XL wasn’t much of a leap forward in compressed size, it still seems worth supporting. But Jon is saying “in the quality range relevant to the web”, JPEG is 10-15% better than even AVIF.

Of course, Cloudinary is incentivized to push for new formats, because part of its business model is helping people take advantage of new image formats.

395: The Most Hearted of 2022

Category Image 052

Marie and I hop on the show to discuss our recently released Most Hearted of 2022 Pens. We only did the calculations the day before, so this is more of a first reaction than a deep dive.

  • Congrats to Hyperplexed for #1 and a massive year on CodePen. Last year, just one entry on the Top 100, and this year, nine. “Full layouts” like this appeared a number of times, including Aysenur Turk, last year’s winner, at #13 with Liquid Transition Effect, and there were two NFT-themed landing pages (1, 2) in the Top 100.
  • A lot of Pens attract attention when they have that “I could use this” feel to them, demonstrated by Ryan Mulligan’s Logo Wall at #2!
  • High five to Greensock for taking #3 with a re-creation of Brian Cross’ lovely Pen. The tag “gsap” was used a ton in the Top 100.
  • Jon Kantner took #4 and 10 other spots making this the most appearances on the Top 100 list ever, and also took a spot with a Pen made on December 13th! Aaron Iker and Yoav Kadosh both had 4 spots.
  • Perhaps my favorite because of the deep CSS trickery involved was Scott Kellum’s Apple inspired pride clock. Scott has the oldest account of anyone in the list, over 10 years old! Huge fan of Steve Gardener’s joke, though as well.
  • 11 of the Top 100 were created for CodePen Challenges.

Time Jumps

  • 00:23 The rules of the game
  • 05:13 Grinch style hearting reminder
  • 06:34 Number one on the list
  • 10:24 Sponsor: Notion
  • 11:12 Logo wall
  • 12:52 Greensock scrolling site pen
  • 14:40 NFT landing pages
  • 16:25 11 appearances by John
  • 17:30 Shaw made the list
  • 19:09 Challenge pens made the list
  • 22:16 New CodePen members on the list
  • 23:25 Longest CodePen member on the list
  • 25:09 Elements that are popular
  • 27:44 Spider pens
  • 29:37 Snowball pen

Sponsor: Notion

Notion is an amazing collaborative tool that not only helps organize your company’s information but helps with project management as well. We know that all too well here at CodePen, as we use Notion for countless business tasks. Learn more and get started for free at notion.com. Take your first step toward an organized, happier team, today.

Create a Product Page with Interactive Colors in HTML, CSS3 & jQuery

Category Image 052

This post is originally published on Designmodo: Create a Product Page with Interactive Colors in HTML, CSS3 & jQuery

Create Product Page with Interactive Colors in HTML, CSS3 & jQuery

Topic: HTML / CSS3 / jQuery Difficulty: Intermediate Estimated Completion Time: 30 minutes In this tutorial, we are going to create a website product page using HTML, CSS3 and jQuery. You can use it for product presentations on your shop …

For more information please contact Designmodo

Mastodon Verification of CodePen Profiles

Category Image 052

TL;DR — If you link to your Mastodon profile from CodePen, and your CodePen profile from Mastodon, your Mastodon profile will display your CodePen profile as a verified link, proving ownership.

How does that work? It’s just HTML!

There is a rel attribute that can go on anchor (<a>) links. The values for rel have a variety of functionality. For example, you can tell search engines not to follow or rank a link and that it is user-generated:

<a 
  href="https://user-generated.com" 
  rel="nofollow ugc">
    User Link
</a>

There are safety and performance-gaining possibilities for using values like noreferrer and noopener as well.

Here’s another value: rel="me" (you can space-separate multiple values). The me value is a rather old-school Microformats thing. It’s pretty neat! The purpose is that you put it on links that point to other things that you own or control. Then, if the link you’re pointing to points directly back also with a rel="me" link that is a verification-of-ownership situation. As the wiki puts it:

Thus establishing a bi-directional rel-me link and confirming that the two URLs represent the same person.

The federated social networking site Mastodon (here’s me!) uses this exact setup to verify personal links. Here’s an image of my Mastodon profile:

Notice there are three links, the first two of which are highlighted with checkmarks and green:

Those “verified” links are verified because they follow the bi-directional rel="me" linking exactly as Mastodon requires.

On CodePen, we’re now adding that me value to all the links you add to your profile. Mastodon does the same, and thus verification is achieved. On my third link, that link to Amazon.com (obviously) doesn’t contain a link back to my Mastodon profile, so it doesn’t verify.

The Other Possible HTML to Verify

While CodePen is now properly putting the me value on profile URLs — that actually didn’t work for Mastodon verification on our first attempt. There were actually two problems:

  • CodePen profiles are client-side rendered, and the Mastodon crawler can only see server-side rendered HTML.
  • We needed to ensure the Mastodon crawler didn’t get trapped by the firewall.

With that second one taken care of via DevOps magic, we still needed a way to make sure the server-rendered HTML had something to verify against.

We aren’t yet server-rendering most of our React-rendered pages (we’ll get there), so the HTML that comes across that first request (and what Mastodon crawls) is essentially a shell page with minimal HTML. We could have tossed the <a rel="me" ...> links into the <body> of that first response, but that seems a little awkward to only have them ripped away by client-side rendering immediately. Instead, there is another equally valid way to provide rel="me" links, and that’s like this:

<head>
  <link rel="me" href="https://chriscoyier.net/">
  <link rel="me" href="https://front-end.social/@chriscoyier">

So we’re actually doing both the <head> links and the <a> links now, and good news, it works great.


Thanks to Will Boyd for asking about this and Amelia Bellamy-Royds for all the back-and-forth on Mastodon as we figured all this out.


Related writings:

Help choose the syntax for CSS Nesting

Category Image 052

CSS Nesting is making the rounds yet again. Remember earlier this year when Adam and Mia put three syntax options up for a vote? Those results were tallied and it wasn’t even even close.

Now there’s another chance to speak into the future of nesting, this time over at the WebKit blog. The results from the Adam and Mia’s survey sparked further discussion and two more ideas were added to the mix. This new survey lets you choose from all five options.

Jen Simmons has put together a thorough outline of those options, including a refresher on nesting, details on how we arrived at the five options, and tons of examples that show the options in various use cases. Let’s return the favor of all the hard work that’s being done here by taking this quick one-question survey.

To Shared LinkPermalink on CSS-Tricks


Help choose the syntax for CSS Nesting originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Holiday Snowtacular 2022

Category Image 052

We’ve got ourselves a real holiday treat! Join host Alex Trost from the Frontend Horse community for the Holiday Snowtacular 2022 this Friday, December 16.

There’s a lineup of 12 awesome speakers — including Chris Coyier, Cassidy Williams, Kevin Powell, and Angie Jones — each discussing various front-end and web dev topics. It’s like the 12 days of Christmas, but wrapped up in a four-hour session for web nerds like us.

It’s a real good cause, too. The event is free, but includes fundraising Doctors Without Borders with a goal of reaching $20,000. You can donate here any time and anything you give will be matched by the event’s sponors. So, come for the front-end fun and help a great cause in the process.

To Shared LinkPermalink on CSS-Tricks


Holiday Snowtacular 2022 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Move An Element from Any Website to CodePen

Category Image 052

Say you like how a particular element on a website looks and interacts. You can pluck it right off that site, HTML and CSS included, and pop it over to CodePen using the plugin CSS Pro. Watch me try it here:

The browser extension is not free, so you’d better be sure you’d use it! Exporting to CodePen is just one of many features. It seems like the core of it is more front-end developer-friendly inspection and alteration of sites.

There used to be a DevTools extension that would do this called SnappySnippet, but that appears to be dead now, so long live CSS Pro!

The post Move An Element from Any Website to CodePen appeared first on CodePen Blog.

Unreveal Effects for Content Previews

Category Image 052

Some time ago, we explored a cover page transition that would hide some initial content and show another level of content, i.e. “unreveal” it. Today I’d love to share some more ideas for showing another page or preview, including one that uses CSS clip-path to achieve the effect.

This is our initial view:

When clicking on an item, we hide the current content by covering it with an expanding circle. Then uncover the preview by expanding a clip-path. This is the next view:

And this is how it all looks in action:

There are three different effects. Hope you enjoy them and find them useful!

Thanks for checking by!

State Of CSS Survey: Influence The Future Of CSS

Category Image 052

This year, I joined the team and helped design the survey together with the community which led to a number of improvements. If you write CSS frequently, investing a few minutes to fill it in could come back to you hundredfold, since implementers make decisions on what to work on based on the developer pain points identified through the survey every year. In fact, Chrome is funding work on the survey for this very reason.

Past Surveys

So, how did past surveys help web developers? Let’s look at the impact in Chrome, as described to us by Nicole Sullivan, Product Manager for Chrome at Google:

“I showed the ‘Missing features’ section to my team before the pandemic and we got to work on it. Several things on that list are underway.”

Indeed, literally everything in that list is now being worked on or finished unless there was no (stable) specification for it:

  • Container queries
    Size queries have shipped in Chrome 106 , style queries behind a flag.
  • Parent selector/:has selector
    Shipped in Chrome 105.
  • Nesting
    Currently underway, delayed a bit due to discussions in the CSS Working Group about last minute changes to the syntax.
  • 🟡 Functions
    No specification to implement yet, but is being worked on in the CSS WG.
  • Scoping
    Experimental implementation in Chrome 105 behind a flag.
  • 🟡 Mixins
    No specification to implement yet, but ideas are being explored in the CSS WG.
  • Subgrid
    Implementation underway.

Let’s look at the corresponding section in the 2020 results. A lot of overlap, but some additional items:

The 2021 corresponding section includes roughly the same items, with one new thing: color functions. And lo and behold, the color functions for which there is a stable specification are being implemented in Chrome as we speak, and Chrome has funded specification work on the rest.

And it’s not just Chrome. The focus of Interop 2022 was largely shaped by these results.

What’s Next?

We’re taking on the world of styles and selectors to try and identify upcoming trends, and figure out what featurs and tools to learn next. What’s more, the survey results will also help browser vendors prioritize their roadmaps and work towards better compatibility between browsers.

What do you want to see more of in CSS? Better typography? New responsive layout features? New features to improve maintainability? Layout? Components? Something else? The sky is the limit! Make sure to share your CSS dreams with us in the survey, and they may well start coming true.

Smooth Panel Scroll Effects

Category Image 052

If you have browsed through our latest website roundup you might have seen the amazing website of Margot Priolet. I absolutely love the hero section effect when scrolling and I wanted to remake it and explore some variations including playing with transforms and filter effects.

So the initial view is a hero section like this:

When scrolling, an image section is revealed with an opacity effect. Here, there are many possibilities for variations.

After scrolling for a bit and triggering the effects on the images, we reach the final section.

This is how it all comes together:

This demo shows how to play with smaller images and the black and white filter.

Hope you enjoy this and find it useful!

Early Days of Container Style Queries

Featured Imgs 25

We’re still in suuuuuper early days with container queries. Too early for broad browser support, but Chromium already supports it, Safari started supporting it in version 16, and Firefox is presumably not far behind.

Most early days conversations revolving around container queries usually compare the syntax to media queries.

/* Stacked flex container */
.post {
  display: flex;
  flex-direction: column;
}

/* Change direction when viewport is 600px or wider */
@media(min-width: 600px) {
  .post {
    flex-direction: row;
  }
}

/* Define the container */
.posts {
  container-name: posts;
  container-type: inline-size;
}

.post {
  display: flex;
  flex-direction: column;
}

/* Query the container's min-width */
@container posts (min-width: 600px) {
  /* Change styles when `posts` container is 600px or wider */
  .post {
    flex-direction: row;
  }
}

Both of these are making queries for min-width: 600. The difference is that the media query is looking at the viewport’s width to trigger those style changes while the container query is looking at the computed width of the .posts element. Sweet!

But after listening to CSS Podcast Episode 59, Una and Adam poked at the future of container queries: style queries! The current working draft of the CSS Containment Module Level 3 spec defines container style queries:

container style query allows querying the computed values of the query container. It is a boolean combination of individual style features (<style-feature>) that each query a single, specific property of the query container.

But no examples on syntax just yet — only a brief description:

The syntax of a <style-feature> is the same as for a declaration, and its query is true if the computed value of the given property on the query container matches the given value (which is also computed with respect to the query container), unknown if the property or its value is invalid or unsupported, and false otherwise. The boolean syntax and logic combining style features into a style query is the same as for CSS feature queries. (See @supports.)

So, yes, given time we should expect to pull off something like this:

.posts {
  container-name: posts;
}

@container posts (background-color: #f8a100) {
  /* Change styles when `posts` container has an orange background */
  .post {
    color: #fff;
  }
}

That’s a pretty dumb example. One thing to note is that the container-type is no longer based on the container’s inline-size but by style. We could delcare that like so:

.posts {
  container-name: posts;
  container-type: style; /* unnecessary */
}

…but all container queries are style queries by default. Well. at least as it stands today. Miriam Suzanne has a nice outline of the possible issues that might pop up with that.

Where might querying a container’s styles come in handy? I don’t know yet! But my mind gos to a few places:

  • Custom property values: We’ve seen custom properties used like state indicators, such as the DRY-switching method Ana covered a while back. The value changes, and so do styles.
  • Alternate dark mode approach: Instead of basing it all on a body class change that re-assigns custom property values, maybe we can change an entire color palette if, say, the body background changes color.
  • More complex query conditions: Like, say, we want to apply styles when the size and style conditions for a container are met.

Una also mentioned in the CSS Podcast that container style queries could help prevent some awkward styling situations, like if we happen to have italicized text in an already italicized blockquote:

blockquote {
  container-name: quote;
}

@container quote (font-style: italic) {
  em, i, q, address {
    font-style: normal;
  }
}

Early Days of Container Style Queries originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

State of CSS 2022 Survey Now Open

Category Image 052

The State of CSS survey recently opened up. Last year, the survey confirmed everyone’s assumptions that TailwindCSS is super popular and CSS variables are mainstream. It also codified what many of us want from CSS, from Container Queries to a parent selector. (Spoiler alert, we now have both of ’em.)

While I wouldn’t say the results have been super surprising each year, this time I’m excited to start seeing more historical trends reveal themselves. The survey has been running since 2019, so that’s going to be four years (ancient in front-end years!) of data to see if certain frameworks came and went, specific features are gaining momentum, what general learning practices are out there, and just plain more context. It takes time for stuff to build up like this, so kudos to Sacha Greif for keeping this thing going.

And speaking of the team behind the survey, Lea Verou is new to the bunch and lead this year’s edition. Lea made some nice additions, including more open-ended comments, questions about browser inconsistencies, and a question that compares the amount of time you write CSS versus JavaScript.

Browsers actually use this stuff to help prioritize what features to work on — so definitely add your voice to the mix! The polls close on October 20.

To Shared LinkPermalink on CSS-Tricks


State of CSS 2022 Survey Now Open originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

CSS Rules vs. CSS Rulesets

Category Image 052

The latest spec:

style rule is a qualified rule that associates a selector list with a list of property declarations and possibly a list of nested rules. They are also called rule sets in CSS2.

Louis Lazaris:

As the above quote from W3C indicates, it seems like the W3C considers “rule set” to be a bit of an outdated term, preferring the term “style rule” (or possibly “rule” for short).

I never noticed that! “Rule set” is so gosh darned branded on my brain that it’s gonan take losing a lot of muscle memory to start using “style rule” instead. I didn’t see a specific note in the spec’s Changes section, but you can see the change in the table of contents between versions:

Side-by-side screenshot comparing the table of contents for both the CSS 2 and CSS 3 specifications.

Louis nicely sums up the parts of a style rule as well:

/* Everything below is a style rule (or rule set, or just rule) */
section { /* Everything between the braces is a declaration block */
  margin: 0 20px; /* This line is an individual declaration */
  color: #888; /* Another declaration */
}

I know nothing of the context and, at first, I was gonna poo-poo the change, but “style rule” really makes sense the more I sit with it. If the property:value pairs are declarations that sit in a declaration block, then we’ve got something less like a set of rules and more like one rule that defines the styles for a selector with a block of style declarations. 👌

Once again, naming things is hard.

To Shared LinkPermalink on CSS-Tricks


CSS Rules vs. CSS Rulesets originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.