A tutorial on using WebPageTest to identify and troubleshoot design instability issues.

In a previous post I wrote about measure cumulative design change (CLS) in WebPageTest. CLS is an aggregation of all design changes, so in this post I thought it would be interesting to go deep and inspect each individual design change on a page to try to understand what might be causing the instability and really try to fix the problem (s ).

Measurement of design changes

Usando la APIConcepto de API¿Qué es una API?Una API, siglas de Application Programming Interface o Interfaz de Programación de Apps, es un recopilatorio de código que se puede emplear para que varias apps se comuniquen entre ellas. Es algo que realiza una tarea equivalente a la interfaz de usuario al momento de promover la interacción entre persona y programa, solo que aplicado única y exclusivamente dentro del entorno del software.Aún cuando suene plus de Layout Inestabilidad, podemos obtener una lista de todos los eventos de cambio de diseño en una página:

new Promise(resolve => {
new PerformanceObserver(list => {
resolve(list.getEntries().filter(entry => !entry.hadRecentInput));
}).observe({type: "layout-shift", buffered: true});
}).then(console.log);

This produces a series of design changes that are not preceded by input events:

[
{
"name": "",
"entryType": "layout-shift",
"startTime": 210.78500000294298,
"duration": 0,
"value": 0.0001045969445437389,
"hadRecentInput": false,
"lastInputTime": 0
}
]

In this example, there was a single very small change from 0.01% at 210ms.

Knowing the time and severity of the change is useful to help narrow down what may have caused the change. Let's go back to WebPageTest for a lab environment to perform further testing.

Measurement of layout changes in WebPageTest

De manera similar a medir CLS en WebPageTest, medir cambios de diseño individuales requerirá una métrica personalizada. Afortunadamente, el proceso es más fácil ahora que Chrome 77 es estable. La API de Layout Inestabilidad está habilitada de forma predeterminada, por lo que debería poder ejecutar ese fragmento JS en cualquier sitio web dentro de Chrome 77 y obtener resultados de inmediato. En WebPageTest, puede usar el browserUn navegador (además: browser) es una herramienta informática que te permite ver documentos y datos y navegar por la red. Los navegadores pueden mostrar distintos tipos de recursos de información; principalmente documentos HTML, a pesar de todo, además son posibles otros tipos de archivos y contenido multimedia, como PDF, JPEG, MPEG, GIF o el lenguaje de meta marcado. A través el uso de complementos especiales y la configuración respectivo, los plus Chrome predeterminado y no tener que preocuparse por los indicadores de la línea de comandos o usar Canary.

So let's modify that script to produce a custom metric for WebPageTest:

[LayoutShifts]
return new Promise(resolve => {
new PerformanceObserver(list => {
resolve(JSON.stringify(list.getEntries().filter(entry => !entry.hadRecentInput)));
}).observe({type: "layout-shift", buffered: true});
});

The promise in this script resolves to a JSON representation of the array instead of the array itself. This is because custom metrics can only produce primitive data types such as strings or numbers.

The website I will use for the test is ismyhostfastyet.com, a site I created to compare the load performance of web servers in the real world.

Identify the causes of design instability

At results we can see that the custom metric LayoutShifts has this value:

[
{
"name": "",
"entryType": "layout-shift",
"startTime": 3087.2349999990547,
"duration": 0,
"value": 0.3422101449275362,
"hadRecentInput": false,
"lastInputTime": 0
}
]

In short, there is a unique design change from the 34.2% to 3087ms. To help identify the culprit, let's use WebPageTest's filmstrip view.

layout-shift1-2742295
Two cells in the filmstrip, showing screenshots before and after the layout change.

Scrolling to the ~ 3 second mark on the filmstrip shows us exactly what is causing the 34%'s design change: the colorful table. The website asynchronously retrieves a JSON file and then converts it to a table. The table is initially empty, so waiting to fill it when the results are loaded is causing the change.

layout-shift2-9850265
Web font header appearing out of nowhere.

But that is not all. When the page visually completes in ~ 4.3 seconds, we can see that the <h1> from the page "Is my host fast?" appears out of nowhere. This happens because the site uses a web font and has not taken any steps to optimize the rendering. Actually, the layout doesn't seem to change when this happens, but it's still a bad user experience to have to wait so long to read the title.

Fix design instability

Ahora que sabemos que la tabla generada de forma asincrónica está provocando que un tercio de la ventana gráfica se desplace, es hora de solucionarlo. No conocemos el contentsEl contenido puede ser muy difícil de definir con precisión. Es una definición que se refiere a las declaraciones contenidas en un documento o publicación de cualquier tipo y puede incluir las tecnologías de la información y la comunicación. Esto cubre todos los tipos de medios como imágenes y texto. A parte de esto, en el campo de la optimización de motores de búsqueda, los términos duplicar contenido, contenido único, plus de la tabla hasta que se cargan los resultados JSON, pero aún podemos completar la tabla con algún tipo de placeholder data so that the layout itself is relatively stable when the DOM is rendered.

Here is the code to generate placeholder data:

function getRandomFiller(maxLength) {
var filler = '█';
var len = Math.ceil(Math.random() * maxLength);
return new Array(len).fill(filler).join('');
}

function getRandomDistribution() {
var fast = Math.random();
var avg = (1 - fast) * Math.random();
var slow = 1 - (fast + avg);
return [fast, avg, slow];
}


window.data = [];
for (var i = 0; i < 36; i++) {
var [fast, avg, slow] = getRandomDistribution();
window.data.push({
platform: getRandomFiller(10),
client: getRandomFiller(5),
n: getRandomFiller(1),
fast,
avg,
slow
});
}
updateResultsTable(sortResults(window.data, 'fast'));

The placeholder data is randomly generated before being sorted. Includes the character "█" repeated a random number of times to create visual placeholders for the text and a randomly generated distribution of the three main values. I also added some styles to desaturate all the colors in the table to make it clear that the data is not fully loaded yet.

The appearance of the placeholders you use does not matter for layout stability. The purpose of placeholders is to assure users that content it is comes and the page is not broken.

This is what the placeholders look like while loading the JSON data:

layout-placeholder-7909400
The data table is represented with placeholder data.

Tackling the problem of web fonts is much easier. Because the site uses Google Fonts, we only need to pass the display = swap propiedad en la solicitud CSSConcepto de CSS¿Qué es el CSS?CSS es un lenguaje de programación que se usa para definir el estilo y el aspecto de un documento que se ha escrito mediante de un lenguaje de etiquetas, como HTML. Conocido además como hojas de estilo en cascada, es el que se emplea para dar colores, indicar tipos de letra o inclusive resaltar aspectos como el espacio entre items para dotar de estilo a plus. Eso es todo. La API de fuentes agregará font-display: swap style in the font declaration, allowing the browser to render the text in an alternate font immediately. Here is the corresponding markup with the correction included:

<link href="httpsHTTPS (protocolo de Transferencia de Hiper-Texto) es un protocolo que permite determinar una conexión segura entre el servidor y el cliente, que no puede ser interceptada por personas no autorizadas. En resumidas cuentas, es la versión segura de el http (Hyper Text Transfer Protocol) Cómo funciona Una conexión HTTP estándar en Internet puede ser fácilmente secuestrada por partes no autorizadas. El propósito de una conexión HTTPS es evitar esto: encriptar plus://fonts.googleapis.com/css?family=Chivo:900&ampConcepto de AMP¿Qué es el AMP o Accelerated Mobile Pages?El AMP, abreviatura de Accelerated Mobile Pages, es una propuesta que empezó a tomar forma en el año 2016 con la finalidad de mejorar la usabilidad, lectura y, en general, la experiencia de los usuarios de teléfono celular dentro de cualquier página web. Emprendida por Google con un aperturismo total (es de código abierto), lleva en activo desde entonces para facilitar plus;display=swap" rel="stylesheet">

Checking the optimizations

After rerunning the page through WebPageTest, we can generate a before and after comparison to visualize the difference and measure the new degree of design instability:

layout-comparison-2278210
WebPageTest filmstrip showing both sites loading side by side with and without layout optimizations.

[
{
"name": "",
"entryType": "layout-shift",
"startTime": 3070.9349999997357,
"duration": 0,
"value": 0.000050272187989256116,
"hadRecentInput": false,
"lastInputTime": 0
}
]

According to the custom metric, there is still a design change at 3071ms (roughly the same time as before) but the severity of the change is a lot of lower: 0.005%. I can live with this.

It is also clear from the filmstrip that the <h1> The font immediately reverts to a system font, allowing users to read it earlier.

conclusion

Complex websites will likely experience many more design changes than in this example, but the remediation process remains the same: add design instability metrics to WebPageTest, cross-reference results with visual loading filmstrip to identify the culprits and implement a solution using placeholders to reserve screen space.

(One more thing) Measurement of design instability experienced by real users

It's nice to be able to run WebPageTest on a page before and after an optimization and see an improvement in a metric, but what really matters is that the user experience is improving. Isn't that why we are trying to improve the site in the first place?

So what would be great if we started measuring actual user design jitter experiences alongside our traditional web performance metrics. This is a crucial piece of the optimization feedback loop because having field data tells us where the problems are and if our fixes made a positive difference.

In addition to collecting your own design instability data, see the Chrome UX Report, which includes cumulative design change data from actual user experiences across millions of websites. It lets you know how you (or your competitors) are performing, or you can use it to explore the state of design instability on the web.