With the rise of very high density “super retina” displays in the newest high-end devices, capping image fidelity to 2x leads to a big improvement in terms of rendering speed, and no perceivable quality loss for your users. Here’s a new best practice on how to do that.

Image for post
Image for post
Apple and Google devices with 3x HiDPI displays (excluding “Max” versions)

Images x screen densities

In June 2010, Apple introduced the first Retina display on the iPhone 4. “Retina” is just a fancy name to describe a HiDPI display, which has 2x the pixels horizontally and 2x vertically.

Image for post
Image for post
A “Load more” button at the end of a list of images

Cumulative Layout Shift (CLS) is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts — a low CLS helps ensure that the page is delightful.

What you might not know is:

  • CLS is measured continuously. In fact, its value is also updated while your users scroll your page, if the scroll generates some layout movement
  • CLS measurement is paused for 500ms whenever a user interaction like a click or a keyboard event occurs

Long story short, Cumulative Layout Shift measures every unexpected layout movement occurring while your users interact with the page, including while they scroll down. …

In this article we explain how we at YOOX NET-A-PORTER optimized the Chloé website for a couple of Core Web Vitals: Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS).

Web vitals

Web Vitals is an initiative by Google to provide unified guidance for quality signals that are essential to delivering a great user experience on the web.

Core Web Vitals

Core Web Vitals are the subset of Web Vitals that apply to all web pages, should be measured by all site owners, and will be surfaced across all Google tools. …

After we updated our iPhones to iOS 13.4, we found that Apple introduced a bug in the rendering of boxes with specific CSS properties for the box-shadow rule.

After we found the problem on some websites, we created a new Codepen to isolate and identify the problem. Here’s what we found out.

TL;DR: A black bar appears when applying a box-shadow rule with an inset value and a large negative spread-radius.

The spread-radius is the fourth length value. Positive values will cause the shadow to expand and grow bigger, negative values will cause the shadow to shrink. If not specified, it will be 0, so the shadow will be the same size as the element. …

On April 6th 2019, Addy Osmany wrote about native image lazy-loading. Two days later Yvain, a front-end developer from Paris, asked me if my vanilla-lazyload could be a loading attribute polyfill, inspiring me to develop and release version 12 of the script, which features a new use_nativeoption to enable native lazy-loading where supported. You can already use it today.

Wait… what?

In case you missed Addy Osmani’s article, it will be possible to natively lazy load images through the loading="lazy" attribute on images and iframes, and it’s already possible on Chrome 75 (currently Canary).

<img loading="lazy" src="...">
<iframe loading="lazy" src="...">

Browsers will initially fetch a tiny bit of the images (~2kb) in order to get some initial information (e.g. size), then fetch the rest when they are about to enter the viewport. …

How to make a potentially wide table fit on small devices, without losing readability and accessibility? Here are simple solutions to make tables look like lists, lists look like tables, in responsive and accessible design.

So let’s say you have an HTML <table> containing some orders, each one having:

  1. a picture
  2. a description
  3. a price

And you need to make it:

  • look like a list on small viewports, typically smartphones
  • look like a table on larger viewports, like tablets and computers
  • accessible (see accessibility), e.g. to blind users

Table markup

Here’s the markup of the table you’ve got.

<th scope="col">Photo</th>
<th scope="col">Description</th>
<th scope="col">Price</th>
<td><img src="https://via.placeholder.com/70x100&text=Product"></td>
<td>EUR 12.345</td>
<td><img src="https://via.placeholder.com/70x100&text=Product"></td>
<td>EUR 12.345</td> …

What would you do if somebody asked you to load a DOM element (like an image, or a video) only if it stays inside the viewport for a given time?

This is exactly what the GitHub community asked for as new feature in vanilla-lazyload, to avoid loading elements which users skipped by scrolling fast beyond them.

Image for post
Image for post
Man fast scrolling over images on a smartphone

There are a couple of ways of doing this. The first one is check the element’s posistion over time, the second one leverages theIntersectionObserver API.

The (slow) way without IntersectionObserver

This way is much slower that using IntersectionObserver because it implies:

  • watching browser’s scroll and resize events to call a (throttled)…


Andrea Verlicchi

Web performance geek. Front-end architect at YOOX NET-A-PORTER GROUP. Author of vanilla-lazyload.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store