Chris’ Corner: Resizing, Conditionals, and Initials

Category Image 052

Ahmad Shadeed recently wrote:

I like to think of CSS as a conditional design language.

It totally is! We tend to think of stuff like @media queries as the conditional part:

@media (max-width: 550px) {
  .grid {
    grid-template-columns: 1fr;
  }
}

That’s true, and new stuff like container and style queries are giving us more “conditional” stuff to work with. But it might be better to think of literally everything in CSS as conditional. Every selector you can write is conditional in some way. Just a sector like aside is conditional — it says, only style elements that match that selector. To grok CSS, you are grokking a massive set of conditions. As Ahmad indicated:

.alert p:empty {
  display: none;
}

This is a big logical if statement. IF the element is a paragraph. IF that paragraph is empty. IF it is a child of another element with a class of alert. All those IFs have to be true for the styles to apply.


You could take conditional CSS another step up though, meaning conditions by which to load the entire .css file at all.

Vadim Makeev wrote up some interesting experiments around all this. Say you do:

<link rel="stylesheet" href="style.css" media="print">

The browser is smart enough not to load that CSS file at all (unless you’re printing, natch).

You can also do this:

<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="mobile.css"
  media="(max-width: 767px)"
>

Butttttt, the browser will actually load both of those files regardless if the media matches or not. So no obvious immediate benefit, but that’s where Vadim’s research comes in. While all the files with non-matching media (queries) still load, the browser is smart enough to make the non-matching stylesheets load with a lower priority. At least in Chrome and Firefox — Safari has some bug that makes the priority levels not provide the perf benefits.

Pretty cool I think. Doing this kind of work by hand feels onerous though, I’d love to see build processes deal with it automatically.


Ya know I was scared for Mozilla & Firefox for a while. Those big layoffs in 2020 included many browser engine engineers and it seemed like it would be hard to continue to be a viable browser engine alternative without a strong team there. But I was essentially wrong. Since then they’ve shipped plenty of important web platform features at a decent pace, including the ever-important Container Queries and new color formats. Putting MDN on GitHub happened after the layoffs too and that seems like a massive thing to get shipped.

Last year WIRED asked Is Firefox OK? There wasn’t really an answer there, but some good information. We know Google provides the bulk of their income, but they showed really strong growth with their own products and services, saying 14% of all revenue was that back in 2021. They’ve clearly been trying new stuff to increase that, so things look on the right track to me.

I like to see little stories like this: Mozilla fixed an 18-year old CSS bug in the Firefox browser. So they aren’t just playing catch up, they are getting details right along the way too. Better late than never. This one was a weird bug with ::first-letter, the real ticket for doing drop caps:

They said it was kind of a bandaid for now but still cool. Speaking of drop caps though… ::first-letter was always fraught for this purpose. Much better would be to support initial-letter. C’mon Firefox, you can do it!


Michelle Barker on Resizing with CSS:

One drawback is the resize control is only positioned in the bottom right corner of the element, and it’s not possible to style it. It would be nice to have this customiseable ability, and increase the area of the resize control.

Yes!

That’s literally my opening thing in Things CSS Could Still Use Heading Into 2023. Just imagine the CodePen editors. So many things resize, and the ability to do that in HTML and CSS alone would be super sweet. But probably with JavaScript callbacks so we can do stuff like save/persist what has changed in the UI.

And ya know, that makes me think about how we only just got a scrollend event in JavaScript, maybe we should get a resizeend event too.

Chris’ Corner: More Like Hypography

Category Image 052

CSS hyphenation support is pretty good — just a -webkit- prefix left for Safari I’d love to see them yank off. Toss it on a parent, let it cascade, and you’ll see text hug the ragged edge a little closer and a little more consistently. You don’t have to use it, it’s a bit of an aesthetic choice.

I was thinking about this because I saw Hyphenopoly.js — a polyfill for hyphenation in JavaScript that’s come out in the last few months. I kinda don’t get it with the browser support being so good, but it does work in Node which might be interesting, and I suppose this would be extensible to written languages where hyphenation isn’t supported yet.

Update from Mathias Nater:

Hyphenopoly.js came out 2018 and its predecessor – Hyphenator.js –  around 2008, some time before hyphens:auto; was available.
There are still many languages that are not supported natively in all browsers.

Hyphenopoly.js supports 72 languages and, yep, it is extensible: we’ll just need hyphenation patterns (the same patterns TeX uses) or a huge list of pre-hyphenated words where I can compute the patterns from.

(I was under the impression it had just come out in the last few months!)

There is a ton more to the CSS art of controlling where words break through. One of the most comprehensive reads on the subject is Will Boyd’s Deep Dive into Text Wrapping and Word Breaking.

Pen

While we’re on type for a second, I do need you to know that Stabby exists:


More good news (in a sec). You know how the content of a page can shift around when a custom font loads after a fallback font has rendered? This is one of the great tradeoffs of display websites right now. Delay rendering until the custom font is ready means no layout shift (good!), but then you’re… delaying rendering (bad!). To my great surprise, the web has shifted toward not delaying rendering, largely thanks to CSS’ font-display: swap;

It is possible to have your cake and eat it too have non-shifting custom font loading without delayed rendering through CSS trickery. It involves using a font loader so that you know when the custom font loads and can adjust CSS to make sure none/little layout shift happens. The tricks were adjusting things like font-size, letter-spacing, and those classics.

The good news is that that old slightly hacky way of dealing with font fallbacks is out and a new school way of dealing with font fallbacks is in. Here’s Katie Hempenius’ recent article:

This article is a deep dive into font fallbacks and the size-adjustascent-overridedescent-override, and line-gap-override APIs. These APIs make it possible to use local fonts to create fallback font faces that closely or exactly match the dimensions of a web font. This reduces or eliminates layout shifts caused by font swapping.

Improved font fallbacks

Four new things just for fallbacks! Wow. Say you’re loading a custom font called Poppins, it ends up looking like this:

body {
  font-family: Poppins, "fallback for poppins";
}

@font-face {
  font-family: "fallback for poppins";
  src: local("Times New Roman");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;
}

My brain immediately went uhmmmmm wouldn’t these metrics totally depend on the combination of the custom font and the fallback font? Apparently not though!

Because font metric overrides are calculated using measurements that come from the metadata of the web font (and not the fallback font), they stay the same regardless of which font is used as the fallback font.

That’s really great. So you can basically figure out (or look up) the overrides for your custom font, put them in place, and you’re straight up good to go. That’s a good API.


Welp I didn’t really intend for this whole issue to be about typography stuff, but here we are. You gotta see Adam Argyle’s Text Replace Transitions!

You could code any number of ways. But Adam did it using the new View Transitions API (so you’ll only be able to see the demo in Chrome Canary). It’s such a fun way to play with animating things because the API is so tidy: call document.startViewTransition, change the DOM, let it animate (control with CSS if you want). Hopefully, the CSS properties will be all that is needed entirely from cross-page View Transitions (I think that’s the case, I just haven’t seen it really work well yet).

Chris’ Corner: Gradients, Generators, and Glows

Category Image 052

Radial gradients do represent a bit of a leap up in complexity compared to linear gradients in CSS. With linear gradients, you sorta pick a direction and plop some stops on there. The default direction, to bottom, you don’t even have to include if that’s the direction you want, and two color stops with no additional values just mean “all the way at the top to all the way at the bottom”. Something like this linear-gradient(darkblue, blue).

Good news: radial gradients do maintain making most parameters optional, so radial-gradient(darkblue, blue) is still functional and half-decently-useful. But the complexity goes up from there.

  • Radial gradients need to be told to behave like a circle if that’s the shape you want, not the default ellipse.
  • You can tell a radial gradient where to stop, before you even get to the color stops.
  • You can choose a starting position for the radial gradient, it doesn’t have to be dead center.
  • There are keywords that tell radial gradients to extend to certain relevant points of the container, like closest-side and furthest-corner and such.

It was enough for Patrick Brosset to ask Do you really understand CSS radial-gradients?, which, ya know, fair.

human eyes drawn with css radial gradients.

There is no built-in way to generate a random number in CSS. Maybe there should be, as there are countless demos that use some other technology to feed random numbers into CSS. The use case is often generative art or decorative effects, but there is so much of that and the results can be so cool, it’s almost shame we don’t have it. So what do we do to get random numbers in CSS?

  • We use the random function in a CSS processor (e.g. random() works in Sass) — but then it’s only random at build time.
  • We use a random number created in JavaScript, then set a --custom-property with it. Maybe even Houdini.
  • We use user input somehow to make a value feel random.

Kacper Kula’s Randomness in CSS kinda gets into all three of those. He uses a hand-built random number generator in Sass based on prime numbers. The @property syntax is used to ensure a custom property is an integer and is sometimes used as a seed that comes in via JavaScript.

Demo Pen

Let me leave you this week with just a tiny classy snippet of CSS from CodyHouse:

.component {
  /* inner glow 👇 */
  box-shadow: 
    inset 0 0 0.5px 1px hsla(0, 0%, 100%, 0.075),

  /* shadow ring 👇 */
    0 0 0 1px hsla(0, 0%, 0%, 0.05),

  /* multiple soft shadows 👇 */
    0 0.3px 0.4px hsla(0, 0%, 0%, 0.02),
    0 0.9px 1.5px hsla(0, 0%, 0%, 0.045),
    0 3.5px 6px hsla(0, 0%, 0%, 0.09);
}
Demo Pen

That’s just a nice look right there.

Classless CSS library Almond.css

Category Image 091

From Alvaro Montoro: almond.css

This is one of those “classless” CSS libraries — CSS that you apply to semantic HTML to apply a nice look. You apply no classes or any other selectors — it totally removes that mental exercise. The only selectors it uses are HTML elements. A perfect sort of choice for things like “I just need to style this one-pager of HTML quick”, Markdown output, or dare I say, a demo Pen.

(Saw via Louis Lazaris‘ article Top Front-End Tools Of 2022 on Smashing Mag. It is interesting how these libraries are always quite popular in the context of Louis’ newsletter.)

There are other CSS libraries in this category that come to mind, like: Water.css, MVP.css, new.css, and AttriCSS.

Almond.css takes a cool approach that I haven’t seen before: it allows you to customize everything from adjusting --custom-properties at the root level.

So you can use it “totally raw”, like this:

Or customize stuff likes fonts, spacing, and colors like this:

:root {
  --font-family: system-ui;
  --font-weight-normal: 300;
  --font-weight-bold: 600;
  --line-height: 2;
  --heading-margin: 3rem 0 1rem 0;
  --primary: orangered;
}

The post Classless CSS library Almond.css appeared first on CodePen Blog.

Chris’ Corner: Font Size, Document Hierarchy, and Dialog

Category Image 052

How about some accessibility quick hits!


It’s a bit hard to keep track of when using certain CSS value types is bad. For a while, using pixel (px) values in media queries was considered a bad practice as the breakpoints didn’t trigger as expected when a user zoomed in. But then that changed, and media queries do now, and using pixels for media queries isn’t really a bad practice any more.

But is using px still a bad practice in other cases? Yes, says Josh Collingsworth.

… when or if the user changes their preferred font size, if you’re using em and rem, all the text on your website will change accordingly, like it should. 2rem is still double that font size; 0.5rem is still half of it.

By contrast, px values are static20px is just 20px, regardless of the container’s, browser’s, or user’s font size. No matter how large or small the user’s font preference may be, when you set a value in static pixels, it clobbers that choice and overrides it with the exact value you specified.

Critically, that means if your stylesheet uses px to set font-size anywhere in it, any and all text based on that value will be impossible for the user to change.


Did you know that it was, up until fairly recently, specced that heading elements (e.g. <h1>, <h2>, etc) would “reset” inside of a new <section> (and similar) elements? I admit I thought that was kind of a neat idea. For example, if you’re building a site with HTML partials, and one of those as a little <aside> that I plunked into a sidebar or something, that I could have an isolated set of headings that would be valid and squoosh into the proper hierarchy going on on the rest of the page, without knowing or caring about headers scattered around the rest of the page.

Well, despite being specced, and despite general liking of that idea, no browser ever implemented it, and it was removed from the spec. Pour one out for the Document Outline Algorithm.

Doesn’t make me want to hold my breath for browsers implementing a tab order fixer-upper that follows the visual order of grid or flex items, like has been tossed around a bit.


Léonie Watson:

… you may be surprised to learn that there is no way for authors to design the aural presentation of web content, in the way they can design the visual presentation.

Why we need CSS Speech

All the major browsers now have “listening” features built right into them, and still no way to control that experience.

The good news is that there is a spec for CSS speech. Léonie thinks it’s too old and too big, so offered to take it on and trim it down (hopefully into something browsers will take on). Looks like that’s starting to happen based on the names on the spec.


This is a wild story: Safari’s date-picker is the cause of 1/3 of our customer support issues.

Shortly after I read it, I had to use this exact date picker a number of times while filling out online forms on an iPad at a doctor office and I friggin get it. Using that date picker for birthdays is horrible. Even knowing exactly how to do it, I tripped up several times in a row.

The danger of all this is companies, sometimes rightfully, going “screw it we’ll just build our own”, and having that home-grown picker perhaps solve this one UX issue, but cause accessibility issues that harm another group of people.


A smidge of good news. We can Use the dialog element (reasonably) says Scott O’Hara. There have been some recent updates that solve some the focus handling issues that apparently gave it a red flag before. I’m glad about this, as I think it suffers from exactly what I described above: people build dialogs in-house instead and get some (if not most) of the accessibility requirements wrong. Focus-trapping alone is brutally difficult to get right, and it’s just a freebie with <dialog>.

Blaze Slider

Category Image 091

Gotta love a good slider component! There have been so many over the years. I made my own back in the day, using jQuery, called the AnythingSlider. I remember the Pei Wei website used it for a while and I knew I had made it haha.

I think we see so many of these because they are a microcosm of the web itself. It’s a semantic challenge, an accessibility challenge, a performance challenge, a developer ergonomics challenge, a UX challenge, a design challenge, and even a marketing challenge.

Anyway, I’m usually a Flickity guy myself (basic demo), but Blaze Slider also looks great.

I like how it requires no framework at all, but if you’re using one, they have all the most common documented.

The post Blaze Slider appeared first on CodePen Blog.

398: DevOops

Featured Imgs 23

Stephen and I hop on the podcast to chat about some of our recent tooling, local development, and DevOps work. A little while back, we cleaned up our entire monorepo’s circular dependency problems using Madge and elbow grease. That kind of thing usually isn’t the biggest of deals and the kind of thing a super mature bundler like webpack deals with, but other bundlers might choke on. Later, we learned that we had more dependency issues like inter-package circular dependencies (nothing like production deployments to keep you honest) and used more tooling (shout out npx depcheck) to clean more of it up. Workspaces in a monorepo can also paper over missing dependencies — blech.

Another change was moving off using a .dev domain for local development, which oddly actually caused some strange and hard-to-diagnose DNS issues sometimes. We’re on .test now, which should never be a public TLD.

Time Jumps

  • 00:26 Dev ops spring cleaning
  • 01:25 Local dev with .dev, wait, no, .test
  • 06:58 Sponsor: Notion
  • 07:54 Circular dependency
  • 11:41 Monorepo update
  • 13:35 Interpackage and unused packages
  • 16:25 TypeScript
  • 17:54 Upgrading packages
  • 20:35 Hierarchy of packages

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.

Chris’ Corner: Dreamy, Folded, Bendy CSS

Typography Definitions Cover

Yuan Chuan with a funny blog post opener commenting about how much they liked their friend’s photos:

I was attracted by their slight blur and the subtle glowing effects, and wondered what kind of filter function was used. But then she told me it’s just because the camera lens wasn’t wiped clean.

Turns out you can get that same kind of “dreamy” effect with some fancy dancing with filters.


Semantic HTML? Pffffft. Why bother? Unicode is all you really need.

Terence Eden says he is very sorry for this.

I probably should have just copied the unicode above into this email rather than screenshotting it, but it made me too nervous for some reason. Partially because I’d worry it looks like spam to some email servers.


Here’s a nice walkthrough of 3D in CSS by Brad Woods.

One of the demos has you grabbing the corner of an element with regular text in it, and as you drag it folds back in space, with, you guessed it 3D in CSS.

Seeing text in 3D is somehow extra satisfying for me, perhaps because it’s more rare to see. And hey, that reminds me of Codrops recent On-Scroll Typography Animations which are very very cool. Make sure to scroll far enough to see the “Unfolding” one which is my favorite.


I always though that the math behind calculating the perfect nested border-radius would be complex somehow. But Paul Hebert has it figured out for us:

outerRadius - gap = innerRadius

Gotta get this right folks! See how awkward it can be on the left vs. fixed on the right.

Rive

Category Image 091

I’ve had the animation tool Rive on my list of bookmarks to check out for a while. I recently got around to making an account and giving it a shot.

I was immediately interested in what the final output/export is. Because, of course, I want to know how I can use it… to connect it to my own web work. I’m not sure what I expected. Maybe SVG output with a bunch of inline JavaScript to control it? It’s not that, though. Ultimately you get a .riv file.

Then you use one of their runtime libraries to ultimately display the animation. I opened one of their demos, exported the animation, and here I am using the JavaScript runtime and CodePen Asset Hosting to display the animation:

They have loads of interesting use cases and demos on their website. For the web, it ultimately ends up as a <canvas>. I don’t know much about canvas and accessibility, but I imagine you’re kind on your own there to do the best you can do.

Anywho — just a 10-second glance here. The big takeaway here is that their Get Started button is the GOAT:

Some Best-Ofs

Featured Imgs 23

Our Top Pens of 2022 has been out a few weeks now and it’s loads of fun.

We tweeted and tooted the Top 10 to show them some extra love.


I noticed Steve Gardner has put together a Hall of Fame Collection with some of the greatest Pens of All Time, and I gotta say I agree with him on this list.

There are so many more, though! There are some massive heavy hitters. isladjan’s Parallax scroll animation has the most hearts of all time as I write. And there are unusual ones, like the freeCodeCamp test template, which is nothing to look at but has helped a zillion learners.


And speaking of curated best-of lists, GreenSock put together their favorites of 2022 — of Pens that use the GSAP framework. Really unbelievably beautiful interactive stuff in there, and of course, presented in a beautifully interactive way.

The web is cool.

Chris’ Corner: Relatively Recent Great CSS Writing

Category Image 073

Chen Hui Jing, So your designer wants stuff to overlap

Love that title. Elements in HTML don’t just overlap each other by default. In fact, they intentionally push other elements around so that they don’t. You’ll need CSS to force elements to overlap if you need them to. The traditional ways:

  • negative margins
  • transform translate
  • absolute positioning

But Chen Hui Jing makes sure we don’t forget about grid! It might not come to mind immediately as we mostly think about making a grid and placing individual elements in individual grid cells. But grid cells don’t care! You can put as many elements as you want in a grid cell (or multiple grid cells). They are really just placement coordinates, not slots that only take one element.

Michelle Barker, Quick Tip: Negative Animation Delay

This is one of my favorite classic CSS tricks because it’s so obvious… but only after you’ve learned it. The point is mainly staggered animations. If you want animations to all be at different points along the same animation when they start animating, you can use animation-delay. But if you use a positive time value, the animation won’t start for the first time until that delay (duh). So instead, you use a negative value. The animation starts immediately, but backed up to where it needs to be to have the beginning of the animation hit once the negative delay elapses.

Charlotte Dann, Fancy Frames with CSS

Awesome research from Charlotte, covering lots of ways to make interesting “framed” shapes like these:

So is there one obvious clear best path forward to do this in CSS (and friends)? No — haha. Charlotte explores using 1️⃣ multiple gradient backgrounds (very complicated to construct, limitations with transparency), 2️⃣ border-image (one of the weirder CSS properties, but does help with placing gradients, or SVGs), 3️⃣ mask-border which I’m not sure I’ve ever even looked at in my life (no Firefox support), and finally, 4️⃣ Houdini which has no Firefox or Safari support, but does bring interesting JavaScript-powered opportunities into the mix.

Just to throw another one in the mix here… I happened to be playing with Open Props the other day and it has a “Mask Corner Cuts” section. It just uses mask (or -webkit-mask, as apparently the vendor-prefixed version alone gets the best support).

Scott Vandehey, The Power of CSS Blend Modes

Scott is inspired by other-Scott’s Pen (which happens to be #91 on the Top Pens of 2022 list) and breaks down exactly how it works. It’s a combination of filtering and blending layers. that’s just cool as heck.

You gotta go check out the article to see how Scott was able to stretch the idea to other effects, like a halftone filter.

Kate Rose Morley, Tree views in CSS

This is entirely doable in just semantic HTML and CSS alone:

The trick is putting all the list items that have a sub-list with a <details> element. The text of that <li> becomes whatever the <summary> is. Then you can style the ::marker of the details elements to have the plus-and-minus look rather than the default triangle. I appreciated Kate’s usage of :focus-visible too which keeps the focus styles away from mouse clicks.

397: User-Generated Content Saftey

Featured Imgs 23

I was asked about the paradoxical nature of CodePen itself recently. CodePen needs to be safe and secure, yet we accept and gleefully execute user-authored code, which is like don’t-do-that 101 in web security. Marie and I hop on the show to talk this through as an update from quite a long time ago. It’s wonderfully-terribly complicated. Part of what complicates it is that there are many different kinds of worrisome code, from malicious, to distasteful, to spam, and they all need different treatment. This is a daily and never-ending war.

Time Jumps

  • 00:27 Listener question
  • 04:09 Browsers have gotten safer
  • 06:18 Sandboxing
  • 09:31 Sound in the browser
  • 11:19 Sponsor: Notion
  • 12:21 It’s not always bad actors, but sometimes it is
  • 15:35 SEO spam
  • 19:27 The threat of Google blocking
  • 20:31 Tooling to stop bad behaviour

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.

The post 397: User-Generated Content Saftey appeared first on CodePen Blog.

Don’t Miss Editor Settings!

Featured Imgs 23

Louis Lazaris has made a ton of Pens, often in support of one of his newsletters Web Tools Weekly. And yet, like a lot of folks, has never really dug into the Editor Settings of CodePen. Here’s a recent newsletter where he finds those settings and digs into them.

I haven’t really messed around too much with CodePen’s settings other than laying out the editor to display the code panels on the left.

Maybe you also use CodePen a lot. If you do, it’s good to know there’s a specific page where you can modify editor-specific settings to suit your own needs and maybe be more in line with what’s in your primary IDE.

Check out the page for yourself and toggle the “Sticky Preview” to “On” to view any changes in real-time.

For now, this Editor Settings area is the one place you can change your editor font and syntax highlighting theme (we have lots of both of them), and do things like set up your preferred defaults.

You know what I think the most important one is?

Format on Save

Having Prettier format your code on each save is a very satisfying experience and I have a hard time coding without it now.

The post Don’t Miss Editor Settings! appeared first on CodePen Blog.

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.

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:

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.

Making a CodePen Embed Resizable is Easy!

Category Image 091

Just a little CSS. If you use the default recommended HTML embed code, the <iframe> that is ultimately the CodePen Embed itself is wrapped in a <div>:

<div class="cp_embed_wrapper">
  <iframe ... ></iframe>
</div>

That outer <div> gives you an opportunity to make embeds resizeable or do whatever other styling you might want. You could also put your own wrapper around it, whatever floats your boat.

The very easiest bit of CSS to apply to your page to make the embed resizble:

.cp_embed_wrapper {
    overflow: hidden;
    resize: horizontal;
}

Wanna resize both ways?

.cp_embed_wrapper {
    overflow: hidden;
    resize: both;
}
.cp_embed_wrapper > iframe {
    height: 100%;
}

Here’s a version that stays centered and has a little bonus styling. As an embed, so meta!

The post Making a CodePen Embed Resizable is Easy! appeared first on CodePen Blog.