<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="en">
	<title>Andrea Verlicchi</title>
	<subtitle>Making the web faster and more user-friendly</subtitle>
	<link href="https://andreaverlicchi.eu/en/feed/feed.xml" rel="self"/>
	<link href="https://andreaverlicchi.eu/"/>
	<updated>2026-07-27T00:00:00Z</updated>
	<id>https://andreaverlicchi.eu/</id>
	<author>
		<name>Andrea Verlicchi</name>
		<email>andrea.verlicchi@gmail.com</email>
	</author>
	
	<entry>
		<title>Claude vs Gemini: My Use Cases</title>
		<link href="https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/"/>
		<updated>2026-07-27T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/</id>
		<content type="html">&lt;p&gt;There&#39;s a lot of hype and noise out there regarding Claude and Anthropic, especially after the announcement of Fable 5 and lately Opus 5. I definitely use Claude, I&#39;m not saying I don&#39;t! But for many things, I still prefer &lt;strong&gt;Gemini 3.6 Flash&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The reason is simple: although my company has fully adopted Claude and strongly encourages its use, being in close contact with Google and other Google developers through the &lt;strong&gt;GDE (Google Developer Experts)&lt;/strong&gt; program means I hear enthusiastic feedback about Gemini as well. So I want to keep testing and using both.&lt;/p&gt;
&lt;p&gt;I&#39;m not saying they are completely equivalent for me, but there are specific use cases where I prefer one over the other. Here is how I split them in my daily workflow:&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/vflIjejSBt-648.webp 648w, https://andreaverlicchi.eu/img/vflIjejSBt-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/vflIjejSBt-648.jpeg 648w, https://andreaverlicchi.eu/img/vflIjejSBt-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Thoughtful Andrea with speech bubbles showing Anthropic Claude and Google Gemini logos.&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/vflIjejSBt-648.jpeg&quot; width=&quot;1296&quot; height=&quot;723&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Claude or Gemini? The speech bubbles represent my daily AI choices.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;claude-in-claude-desktop&quot; tabindex=&quot;-1&quot;&gt;Claude in Claude Desktop &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/#claude-in-claude-desktop&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complex multi-tool tasks&lt;/strong&gt;: Long tasks that involve reading and writing across multiple workplace tools, including company Slack, Hex, or other integrations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;claude-in-claude-code&quot; tabindex=&quot;-1&quot;&gt;Claude in Claude Code &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/#claude-in-claude-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complex code development&lt;/strong&gt;: For heavy coding tasks (the ones requiring a good amount of reasoning, like major release refactoring), I rely on &lt;em&gt;Fable 5, Opus 4.8, or Sonnet 5&lt;/em&gt;. Often these tasks involve direct integrations via CLI with GitLab (&lt;code&gt;glab&lt;/code&gt;), Google Cloud (&lt;code&gt;gcloud&lt;/code&gt;), or our internal MCP servers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git troubleshooting (with Haiku)&lt;/strong&gt;: Getting out of tricky &lt;code&gt;git&lt;/code&gt; situations (like moving recent commits mistakenly pushed to &lt;code&gt;main&lt;/code&gt; over to a feature branch, or force-pushing the current feature branch to &lt;code&gt;staging&lt;/code&gt; overriding what was already there — don&#39;t judge me: I almost never use &lt;code&gt;git&lt;/code&gt; from the command line, I&#39;m lazy!).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gemini-in-antigravity-antigravity-ide&quot; tabindex=&quot;-1&quot;&gt;Gemini in Antigravity / Antigravity IDE &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/#gemini-in-antigravity-antigravity-ide&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Medium-complexity coding tasks&lt;/strong&gt;: For medium-to-large feature implementations, I use &lt;strong&gt;Gemini 3.6 Flash (high)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DevTools &amp;amp; Performance Analysis&lt;/strong&gt;: For tasks involving DevTools for Agents and deep web performance profiling, I use &lt;strong&gt;Gemini 3.6 Flash (medium)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blog Maintenance &amp;amp; Enhancements&lt;/strong&gt;: For various work on this blog (e.g., recently translating it entirely into Italian, creating custom skills to write new posts, etc.), I use &lt;strong&gt;Gemini 3.6 Flash (medium/high)&lt;/strong&gt;. Spoiler: this very blog post, including its cover image, was generated right here using Antigravity and Gemini 3.6 Flash (Medium)!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gemini-web-desktop-personal-account&quot; tabindex=&quot;-1&quot;&gt;Gemini (web / desktop) – Personal Account &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/#gemini-web-desktop-personal-account&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For questions about life, the universe, and everything (the answer to which is always &lt;a href=&quot;https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy&quot;&gt;42&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kitten care&lt;/strong&gt;: How to welcome two kitten puppies when you&#39;ve never had pets before (a long chat still active after a month!).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Diet &amp;amp; Nutrition&lt;/strong&gt;: Advice on diet and meal planning (monthly chats generated using Gems as blueprint, for over a year).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Home projects&lt;/strong&gt;: Correctly sizing a photovoltaic solar system (a pinned chat I&#39;ll need very soon).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gemini-web-desktop-work-account&quot; tabindex=&quot;-1&quot;&gt;Gemini (web / desktop) – Work Account &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/#gemini-web-desktop-work-account&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For strictly work-related queries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Code analysis&lt;/strong&gt;: Analyzing minified JS libraries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SQL optimization&lt;/strong&gt;: Comparing complexity and execution cost of SQL queries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error debugging&lt;/strong&gt;: Analyzing unclear Python or JavaScript stack traces and errors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Slack workflows&lt;/strong&gt;: Advanced Slack automation, app setup, and workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gemini-web-desktop-both-accounts&quot; tabindex=&quot;-1&quot;&gt;Gemini (web / desktop) – Both Accounts &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/claude-vs-gemini-my-use-cases/#gemini-web-desktop-both-accounts&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cross-cutting use cases where Gemini is my go-to choice across both personal and work profiles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Persistent web searches&lt;/strong&gt;: Web searches whose results I want saved in an accessible history, rather than lost forever &lt;em&gt;like tears in rain&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Document &amp;amp; File analysis&lt;/strong&gt;: Uploading files to extract structured information.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tech questions &amp;amp; setup&lt;/strong&gt;: Resolving technical doubts, configuring tools, making services talk to each other, or understanding AI model internals.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brainstorming &amp;amp; Presentations&lt;/strong&gt;: Generating ideas and structuring content for presentations.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;In conclusion: there is no single absolute &amp;quot;winner&amp;quot; for every need. Experimenting with both lets me leverage the best of both ecosystems and choose the right tool for each specific task!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Should we stop using the word &quot;Responsive&quot; for design?</title>
		<link href="https://andreaverlicchi.eu/en/blog/should-we-stop-using-the-word-responsive-for-design/"/>
		<updated>2026-07-07T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/should-we-stop-using-the-word-responsive-for-design/</id>
		<content type="html">&lt;p&gt;Back in 2010, Ethan Marcotte coined the term &lt;a href=&quot;https://ethanmarcotte.com/books/responsive-web-design/&quot;&gt;Responsive Web Design&lt;/a&gt;. Since then, we&#39;ve used &amp;quot;responsive&amp;quot; to describe a website that adapts its layout to the viewport size. Fluid grids, flexible images, media queries.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Xu114XHN6q-648.webp 648w, https://andreaverlicchi.eu/img/Xu114XHN6q-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/Xu114XHN6q-648.jpeg 648w, https://andreaverlicchi.eu/img/Xu114XHN6q-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A pensive developer looking at screens showing responsive websites and adaptive apps, wondering about the terminology.&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Xu114XHN6q-648.jpeg&quot; width=&quot;1296&quot; height=&quot;723&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Should we use &quot;adaptive&quot; for layouts and &quot;responsive&quot; for performance?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;For a while, we tried to separate it from &amp;quot;adaptive&amp;quot; design. Back then, &amp;quot;adaptive&amp;quot; websites had a bit of a bad reputation because they usually relied on server-side device detection and user-agent sniffing to serve completely different HTML and CSS to the browser (remember Aaron Gustafson&#39;s book?). Because UA sniffing was brittle and prone to breaking, the web community wanted to distance itself from it. Ethan&#39;s responsive model served the exact same code to everyone, letting the browser do the work. &amp;quot;Responsive&amp;quot; won the vocabulary war, and &amp;quot;adaptive&amp;quot; became a word associated with outdated, server-detected layouts.&lt;/p&gt;
&lt;p&gt;But fast-forward to today, and these terms have split in ways that are causing real confusion.&lt;/p&gt;
&lt;h2 id=&quot;the-mobile-definition-of-adaptive-android-and-ios&quot; tabindex=&quot;-1&quot;&gt;The mobile definition of &amp;quot;adaptive&amp;quot; (Android and iOS) &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/should-we-stop-using-the-word-responsive-for-design/#the-mobile-definition-of-adaptive-android-and-ios&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you look at modern mobile app development — both Android and iOS — the word &lt;strong&gt;&amp;quot;adaptive&amp;quot;&lt;/strong&gt; is the standard.&lt;/p&gt;
&lt;p&gt;Google heavily uses it for Android app design. With the rise of foldable phones and tablets, apps can&#39;t just stretch to fit. They need to completely restructure. In their &lt;a href=&quot;https://developer.android.com/design/ui/mobile/guides/layout-and-content/adapt-layout&quot;&gt;guide on adaptive layouts&lt;/a&gt;, the focus is entirely on &amp;quot;adaptive&amp;quot; layouts (changing layout structures based on breakpoints and fold states), while &amp;quot;responsive&amp;quot; concepts (like fluid sizing) are just seen as a foundation.&lt;/p&gt;
&lt;p&gt;Apple follows a similar logic. In their &lt;a href=&quot;https://developer.apple.com/design/human-interface-guidelines/layout&quot;&gt;Human Interface Guidelines for Layout&lt;/a&gt;, they frame layout adjustments around the concept of &lt;strong&gt;&amp;quot;Adaptability&amp;quot;&lt;/strong&gt; rather than &amp;quot;Responsiveness.&amp;quot; They guide developers to build interfaces that adapt seamlessly to different devices, screen sizes, and orientations using size classes and adaptive structures.&lt;/p&gt;
&lt;p&gt;So, in the mobile app world, adapting to screen sizes is consistently called &lt;em&gt;adaptive&lt;/em&gt; design.&lt;/p&gt;
&lt;h2 id=&quot;the-web-performance-definition-of-responsiveness&quot; tabindex=&quot;-1&quot;&gt;The web performance definition of &amp;quot;responsiveness&amp;quot; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/should-we-stop-using-the-word-responsive-for-design/#the-web-performance-definition-of-responsiveness&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At the same time, in the web performance space — where I spend a lot of time — the word &amp;quot;responsive&amp;quot; has taken on a completely different meaning.&lt;/p&gt;
&lt;p&gt;When performance engineers say they want to make a page &amp;quot;responsive,&amp;quot; they aren’t talking about viewports or media queries at all. They are talking about &lt;strong&gt;interactivity&lt;/strong&gt;. Specifically, how fast the browser reacts to user inputs.&lt;/p&gt;
&lt;p&gt;With Google&#39;s &lt;a href=&quot;https://web.dev/inp/&quot;&gt;Interaction to Next Paint (INP)&lt;/a&gt; metric, &amp;quot;responsiveness&amp;quot; is measured in milliseconds. If a user taps a button and the page freezes for 300ms, the website has poor responsiveness.&lt;/p&gt;
&lt;h2 id=&quot;the-terminology-collision&quot; tabindex=&quot;-1&quot;&gt;The terminology collision &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/should-we-stop-using-the-word-responsive-for-design/#the-terminology-collision&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This has created a confusing mess.&lt;/p&gt;
&lt;p&gt;If a product manager says: &lt;em&gt;&amp;quot;We need to make this website more responsive.&amp;quot;&lt;/em&gt;
What do they mean?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do we need to adjust our CSS media queries for foldables and tablets?&lt;/li&gt;
&lt;li&gt;Or do we need to break up long JavaScript tasks to improve our INP?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are using the exact same word to mean &amp;quot;adapts to screen size&amp;quot; and &amp;quot;reacts fast to user input.&amp;quot;&lt;/p&gt;
&lt;p&gt;And this confusion is only going to grow. If you talk to developers who just entered the industry, or if you ask an AI coding agent to &amp;quot;make this UI more responsive&amp;quot;, what will they actually do? Will they start writing &lt;code&gt;@media&lt;/code&gt; rules in CSS, or will they fire up Chrome DevTools to profile main thread blocking times? Honestly, either path is a valid interpretation of the word.&lt;/p&gt;
&lt;h2 id=&quot;a-proposal-split-the-terminology&quot; tabindex=&quot;-1&quot;&gt;A proposal: Split the terminology &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/should-we-stop-using-the-word-responsive-for-design/#a-proposal-split-the-terminology&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Maybe it&#39;s time to let the word &amp;quot;responsive&amp;quot; go, at least when we talk about screen sizes.&lt;/p&gt;
&lt;p&gt;What if we started using &lt;strong&gt;&amp;quot;adaptive&amp;quot;&lt;/strong&gt; for everything related to layout adjustment (both on the web and in native apps), and reserved &lt;strong&gt;&amp;quot;responsive&amp;quot;&lt;/strong&gt; purely for web performance?&lt;/p&gt;
&lt;p&gt;Under this model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;adaptive&lt;/strong&gt; website or app is one that adjusts its layout to the viewport (mobile, desktop, foldable).&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;responsive&lt;/strong&gt; website or app is one that is fast to respond to user interactions (low INP, no frozen main thread).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To put it in simple terms, if I had to explain this concept to my mother, I would say that a layout &lt;em&gt;adapts&lt;/em&gt; to screen sizes, not that it &amp;quot;responds&amp;quot; to them. It is just a much more natural way to describe it.&lt;/p&gt;
&lt;p&gt;It feels cleaner, more logical, and it solves the vocabulary overlap. But is the web community ready to drop Ethan Marcotte&#39;s 2010 definition? Or is &amp;quot;responsive design&amp;quot; too deeply engraved in our brains?&lt;/p&gt;
&lt;p&gt;I&#39;m curious to hear what you think. Does this distinction make sense, or is it too late to change? Feel free to &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out&lt;/a&gt; and let me know!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk: &quot;Ehi Gemini, sistema il CSS!&quot; at CSS Day Bologna</title>
		<link href="https://andreaverlicchi.eu/en/blog/css-day-bologna-talk-chrome-devtools-agents/"/>
		<updated>2026-06-11T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/css-day-bologna-talk-chrome-devtools-agents/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/c9_tY4rLn0-648.webp 648w, https://andreaverlicchi.eu/img/c9_tY4rLn0-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/c9_tY4rLn0-648.png 648w, https://andreaverlicchi.eu/img/c9_tY4rLn0-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Ehi Gemini, sistema il CSS!&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/c9_tY4rLn0-648.png&quot; width=&quot;1296&quot; height=&quot;728&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Talk: &quot;Ehi Gemini, sistema il CSS!&quot; at CSS Day Bologna&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On &lt;time datetime=&quot;2026-06-11&quot;&gt;Thursday, June 11th, 2026&lt;/time&gt;, I had the pleasure of presenting at the &lt;a href=&quot;https://cssday.it/&quot;&gt;CSS Day&lt;/a&gt; conference in Bologna.&lt;/p&gt;
&lt;p&gt;Have you ever wondered how much time we waste every day right-clicking to &amp;quot;Inspect&amp;quot;, changing the viewport size 50 times, or hunting down that one CSS rule overriding our styles? Traditional AI programming assistants are outstanding, but they are &amp;quot;blind&amp;quot; to the live browser environment: they cannot see the in-memory DOM, network traffic, or console errors.&lt;/p&gt;
&lt;p&gt;In this talk from CSS Day, we explore &lt;strong&gt;Chrome DevTools for Agents&lt;/strong&gt; (also known as DTA), a tool released in version 1.0 in May during Google I/O. Thanks to the &lt;strong&gt;Model Context Protocol&lt;/strong&gt; (MCP), this tool exposes the native capabilities of DevTools directly to AI agents (such as Gemini, Claude Code, Cursor, or Antigravity).&lt;/p&gt;
&lt;p&gt;The result? The AI can navigate, inspect stylesheets, fill out forms, and perform real debugging on our behalf.&lt;/p&gt;
&lt;h2 id=&quot;watch-the-video&quot; tabindex=&quot;-1&quot;&gt;Watch the video &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-day-bologna-talk-chrome-devtools-agents/#watch-the-video&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Ol2Xo29Z3tE&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; loading=&quot;lazy&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;slides&quot; tabindex=&quot;-1&quot;&gt;Slides &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-day-bologna-talk-chrome-devtools-agents/#slides&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can download or view the presentation slides here:
&lt;a href=&quot;https://andreaverlicchi.eu/pdf/ehi-gemini-sistema-il-css-chrome-devtools-for-agents-css-day-2026.pdf&quot;&gt;🔗 Download presentation slides (PDF)&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Google Antigravity 2 &amp; Gemini 3.5 Flash: this AI duo changed my dev workflow... again</title>
		<link href="https://andreaverlicchi.eu/en/blog/google-antigravity-2-gemini-35-flash/"/>
		<updated>2026-05-22T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/google-antigravity-2-gemini-35-flash/</id>
		<content type="html">&lt;p&gt;It has only been a few days since I started using it, but I’m already incredibly enthusiastic. The speed, the precision, the planning process, and the final results obtained are simply outstanding.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/IzZVtZKqba-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The Google Antigravity logo featuring the text &#39;Experience liftoff&#39;.&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/IzZVtZKqba-648.png&quot; width=&quot;648&quot; height=&quot;367&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Google Antigravity 2 is here, and it&#39;s a complete game-changer.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Let me take a step back. Antigravity 1 was essentially a VS Code shell with a built-in chat. It felt quite similar to the VS Code + Copilot setup, but with a highly interesting twist: &lt;strong&gt;Planning Mode&lt;/strong&gt;. Before executing any changes, the chat would pause, reflect back what it understood, show you a detailed step-by-step implementation plan, and ask for explicit confirmation. It was very similar to Claude&#39;s planning mode but packaged in a much cleaner, easier-to-read, and commentable user interface.&lt;/p&gt;
&lt;p&gt;With &lt;strong&gt;Antigravity 2&lt;/strong&gt;, they’ve taken a bold step. They’ve completely removed the code editor mode (or they’ve hidden it so well that I haven&#39;t found it yet!). Instead, it is a pure, distraction-free chat interface focused entirely on the agentic workflow, while keeping that wonderfully convenient Planning Mode from version 1 completely intact.&lt;/p&gt;
&lt;h2 id=&quot;seamless-multi-project-workflows&quot; tabindex=&quot;-1&quot;&gt;Seamless Multi-Project Workflows &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-antigravity-2-gemini-35-flash/#seamless-multi-project-workflows&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What makes Antigravity 2 so powerful is how it operates in the background:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-Project Support&lt;/strong&gt;: It runs seamlessly across your active workspace projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parallel Chats&lt;/strong&gt;: Each project can have multiple concurrent chats running in parallel.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git Worktrees&lt;/strong&gt;: Each independent chat can run directly on your local branch or inside its own dedicated Git worktree, allowing the agent to write code and run builds in isolation without locking up your main working tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I recommend using it side-by-side with your favorite traditional IDE. In my day-to-day work, I constantly jump between Antigravity 2 and &lt;strong&gt;JetBrains PyCharm&lt;/strong&gt;. I use Antigravity to run agent tasks, plan refactoring, and modify code, and then I switch over to PyCharm to run, test, and handle everything else just like I did before. It’s the perfect hybrid workspace.&lt;/p&gt;
&lt;h2 id=&quot;under-the-hood-gemini-3-5-flash-is-fire&quot; tabindex=&quot;-1&quot;&gt;Under the Hood: Gemini 3.5 Flash is Fire &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-antigravity-2-gemini-35-flash/#under-the-hood-gemini-3-5-flash-is-fire&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Antigravity 2 supports both Gemini 3.5 and Claude. If you have a Google account, you get a generous free tier of Gemini 3.5 included right out of the box, which I highly recommend trying. If you prefer Claude, you can simply connect your Anthropic account and go.&lt;/p&gt;
&lt;p&gt;I’ve personally tested almost every major model out there—from OpenAI&#39;s o3, to Gemini 2.5 Pro, to Claude Sonnet 3.7 and Opus 4.6. Over time, I’ve consistently found myself appreciating the quality and relevance of Gemini&#39;s answers the most.&lt;/p&gt;
&lt;p&gt;And &lt;strong&gt;Gemini 3.5 Flash&lt;/strong&gt;? It is absolute fire (or as we say in Italy, &lt;em&gt;una bomba&lt;/em&gt;). It is blisteringly fast, incredibly accurate, and highly intelligent. You really have to try it yourself to understand the speed difference.&lt;/p&gt;
&lt;h2 id=&quot;what-are-you-waiting-for&quot; tabindex=&quot;-1&quot;&gt;What Are You Waiting For? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-antigravity-2-gemini-35-flash/#what-are-you-waiting-for&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By the time you&#39;ve finished reading this paragraph, you could have already &lt;a href=&quot;https://antigravity.google/download&quot;&gt;downloaded it&lt;/a&gt;. And in the time it would take you to write a reply to this post, you could write your first prompt and experience it firsthand.&lt;/p&gt;
&lt;p&gt;If you are a developer looking to supercharge your productivity, give the Antigravity 2 and Gemini 3.5 Flash duo a spin. I think you won&#39;t look back. 😊&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>My dream of a container image format: a call to the web community</title>
		<link href="https://andreaverlicchi.eu/en/blog/end-of-responsive-images-dream-image-format/"/>
		<updated>2026-04-29T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/end-of-responsive-images-dream-image-format/</id>
		<content type="html">&lt;p&gt;A few days ago, &lt;a href=&quot;https://piccalil.li/author/mat-marquis/&quot;&gt;Mat Marquis&lt;/a&gt; wrote a great article on &lt;a href=&quot;https://piccalil.li/blog/the-end-of-responsive-images/#the-beginning-and-the-end&quot;&gt;the end of responsive images&lt;/a&gt;, explaining how the now widely-supported &lt;code&gt;sizes=&amp;quot;auto&amp;quot;&lt;/code&gt; attribute lets browsers figure out the rendered size of lazy-loaded images on their own, removing the need to hand-craft the &lt;code&gt;sizes&lt;/code&gt; attribute for most images.&lt;/p&gt;
&lt;p&gt;Reading it revived a dream I&#39;ve been carrying for years: an image format that would let us write a radically simpler &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag — simpler than even &lt;code&gt;sizes=&amp;quot;auto&amp;quot;&lt;/code&gt; allows. I&#39;ll get to it below. But first, a quick recap of Andy&#39;s piece for context.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Vf5NuI4bBl-648.webp 648w, https://andreaverlicchi.eu/img/Vf5NuI4bBl-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/Vf5NuI4bBl-648.png 648w, https://andreaverlicchi.eu/img/Vf5NuI4bBl-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;On the left, the text &#39;The dream of a container image format&#39;. On the right, a graphical representation of a container image labeled &#39;.img&#39; bundling multiple image sizes inside it.&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Vf5NuI4bBl-648.png&quot; width=&quot;1296&quot; height=&quot;723&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;A dream image format: one file, all the sizes you need.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;andys-tl-dr&quot; tabindex=&quot;-1&quot;&gt;Andy&#39;s TL;DR &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/end-of-responsive-images-dream-image-format/#andys-tl-dr&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For lazy-loaded images (most images on a page), we can drop the hand-crafted &lt;code&gt;sizes&lt;/code&gt; and let the browser do the work:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
    shirt_300w.jpg   300w,
    shirt_600w.jpg   600w,
    shirt_1200w.jpg 1200w,
    shirt_2400w.jpg 2400w
  &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A shirt&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For &amp;quot;hero&amp;quot; images — the ones above the fold, candidates to become the page&#39;s LCP — we still need to be meticulous with upfront sizing via &lt;code&gt;sizes&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;eager&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
    shirt_300w.jpg   300w,
    shirt_600w.jpg   600w,
    shirt_1200w.jpg 1200w,
    shirt_2400w.jpg 2400w
  &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 1200px) 100vw,
         (min-width: 600px) 600px,
         300px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A shirt&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;sizes&lt;/code&gt; can mostly go away. But we&#39;re still left with that long &lt;code&gt;srcset&lt;/code&gt; listing every variant. And that&#39;s where my old dream comes back in.&lt;/p&gt;
&lt;h2 id=&quot;i-have-a-dream&quot; tabindex=&quot;-1&quot;&gt;I have a dream &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/end-of-responsive-images-dream-image-format/#i-have-a-dream&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For years I&#39;ve been dreaming about a container image format — a single file containing every resolution of an image inside it. Think of it as a bundled folder of images, packaged as one.&lt;/p&gt;
&lt;p&gt;With a format like that, the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag, at least for lazy images, could be drastically simplified. Something like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shirt.imgc *w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A shirt&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No more complex &lt;code&gt;srcset&lt;/code&gt; with a comma-separated list of widths. The browser would open the file, see which resolutions are available inside, and download only the bytes it needs for the size it has to render.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag, finally simple again.&lt;/p&gt;
&lt;h2 id=&quot;a-call-to-the-community&quot; tabindex=&quot;-1&quot;&gt;A call to the community &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/end-of-responsive-images-dream-image-format/#a-call-to-the-community&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Andy&#39;s article shows that the platform can absorb a lot of the complexity we&#39;ve been carrying around in our markup. I&#39;d love to see us go even further.&lt;/p&gt;
&lt;p&gt;To the web standards folks, image format authors, and browser engineers reading this: is a container image format something we could actually build? HTTP range requests already allow browsers to fetch segments of files. Container formats already exist in other domains. The building blocks are all there.&lt;/p&gt;
&lt;p&gt;I&#39;ve been holding this dream for a long time. Could we finally make it real?&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk: Enhancing Web Responsiveness at Web Day 2026, Milan</title>
		<link href="https://andreaverlicchi.eu/en/blog/web-day-2026-enhancing-web-responsiveness/"/>
		<updated>2026-04-01T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/web-day-2026-enhancing-web-responsiveness/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/niFQg6TlTD-648.webp 648w, https://andreaverlicchi.eu/img/niFQg6TlTD-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/niFQg6TlTD-648.jpeg 648w, https://andreaverlicchi.eu/img/niFQg6TlTD-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi on stage at Web Day 2026, Milan&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/niFQg6TlTD-648.jpeg&quot; width=&quot;1296&quot; height=&quot;864&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Andrea Verlicchi on stage at Web Day 2026, Milan&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I had the chance to speak at &lt;a href=&quot;https://www.webdayconf.it/&quot;&gt;Web Day 2026&lt;/a&gt;, the 9th edition of the conference organized by Improove in Milan, held on &lt;time datetime=&quot;2026-03-30&quot;&gt;March 30th, 2026&lt;/time&gt; at Talent Garden Calabiana.&lt;/p&gt;
&lt;p&gt;My talk was &amp;quot;Enhancing Web Responsiveness — A practical guide to debugging and avoiding slow interactions&amp;quot;, and it was all about Interaction to Next Paint (INP), the Core Web Vital metric that measures how responsive a page is to user interactions.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/pBs26H3_Ty-648.webp 648w, https://andreaverlicchi.eu/img/pBs26H3_Ty-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/pBs26H3_Ty-648.jpeg 648w, https://andreaverlicchi.eu/img/pBs26H3_Ty-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi on stage at Web Day 2026, Milan&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/pBs26H3_Ty-648.jpeg&quot; width=&quot;1296&quot; height=&quot;864&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Andrea Verlicchi on stage at Web Day 2026, Milan&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I shared real-world case studies showing how to identify and fix poor INP, and practical techniques you can apply right away to make your websites feel snappier. If you&#39;ve ever wondered why a button click feels sluggish or a form takes forever to respond, this one was for you.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.webdayconf.it/e/sessione/5113/Enhancing-Web-Responsiveness-%E2%80%93-A-practical-guide-to-debugging-and-avoiding-slow-interactions&quot;&gt;🔗 Talk page on the Web Day website&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Refactoring Gender Bias, One Commit at a Time</title>
		<link href="https://andreaverlicchi.eu/en/blog/refactoring-gender-bias-one-commit-at-a-time/"/>
		<updated>2026-03-27T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/refactoring-gender-bias-one-commit-at-a-time/</id>
		<content type="html">&lt;p&gt;I recently had the pleasure of co-presenting with &lt;a href=&quot;https://www.linkedin.com/in/giulia-naponiello/&quot;&gt;Giulia Naponiello&lt;/a&gt;, Senior Software Engineer at Red Hat, about gender bias in technology at two local meetups. The talk, titled &amp;quot;Rifattorizziamo i bias di genere, un commit alla volta&amp;quot; (Refactoring Gender Bias, One Commit at a Time), explored how unconscious biases subtly manifest in tech workplaces.&lt;/p&gt;
&lt;p&gt;We shared personal stories and examined how bias shows up in everyday situations—from code review language to hiring assessments, and from the recognition of technical authority to team dynamics. The goal wasn&#39;t to point fingers, but to shine a light on the &amp;quot;cultural bugs&amp;quot; we all carry and suggest ways to fix them. Think of it as refactoring: same codebase, better outcomes. 🐛➡️✅&lt;/p&gt;
&lt;h2 id=&quot;bologna-front-end&quot; tabindex=&quot;-1&quot;&gt;Bologna Front-end 🇮🇹 &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/refactoring-gender-bias-one-commit-at-a-time/#bologna-front-end&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Bxmbrmmo2p-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Refactoring Biases, One Commit at a Time - DevRomagna, March 2026 - Giulia Naponiello and Andrea Verlicchi&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Bxmbrmmo2p-648.png&quot; width=&quot;648&quot; height=&quot;364&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The cover slide of our talk.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On &lt;time datetime=&quot;2026-03-10&quot;&gt;Tuesday, March 10th, 2026&lt;/time&gt;, we presented at the 61st episode of &lt;a href=&quot;https://www.meetup.com/it-IT/bologna-front-end/&quot;&gt;Bologna Front-end&lt;/a&gt; at the Granata venue in Bologna.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/8tXGJk0Q1fs&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/it-it/bologna-front-end/events/313066751/&quot;&gt;🔗 Event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;devromagna&quot; tabindex=&quot;-1&quot;&gt;DevRomagna 🇮🇹 &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/refactoring-gender-bias-one-commit-at-a-time/#devromagna&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On &lt;time datetime=&quot;2026-03-17&quot;&gt;Tuesday, March 17th, 2026&lt;/time&gt;, we brought the same talk to &lt;a href=&quot;https://www.meetup.com/it-IT/devromagna/&quot;&gt;DevRomagna&lt;/a&gt; at Gellify in Imola.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/it-it/devromagna/events/313450456/&quot;&gt;🔗 Event page&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>GitBar Podcast: Non toccate quel tag!</title>
		<link href="https://andreaverlicchi.eu/en/blog/gitbar-podcast-web-performance/"/>
		<updated>2026-03-19T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/gitbar-podcast-web-performance/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/pc_qdd2vex-648.webp 648w, https://andreaverlicchi.eu/img/pc_qdd2vex-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/pc_qdd2vex-648.png 648w, https://andreaverlicchi.eu/img/pc_qdd2vex-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;GitBar Podcast episode 228 - Non toccate quel tag! with Andrea Verlicchi&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/pc_qdd2vex-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;GitBar Podcast - Episode 228&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I recently had the pleasure of being a guest on &lt;a href=&quot;https://www.gitbar.it/&quot;&gt;GitBar&lt;/a&gt;, the Italian podcast by Mauro &amp;quot;Brainrepo&amp;quot; Murru. In episode 228, titled &amp;quot;Non toccate quel tag!&amp;quot; (Don&#39;t Touch That Tag!), we had a long and fun conversation about web performance — from Core Web Vitals to image optimization, from the infamous Interaction to Next Paint to the silent damage of Google Tag Manager.&lt;/p&gt;
&lt;p&gt;We also touched on some nostalgic topics like Flash, Dreamweaver, and MySpace, and talked about how AI tools like Claude are starting to help with performance analysis. It was a blast!&lt;/p&gt;
&lt;h2 id=&quot;watch-listen&quot; tabindex=&quot;-1&quot;&gt;Watch / Listen &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/gitbar-podcast-web-performance/#watch-listen&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/YXuWrBe6zyU&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; loading=&quot;lazy&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;You can also find the episode on the &lt;a href=&quot;https://www.gitbar.it/episode/ep228-non-toccate-quel-tag-con-andrea-verlicchi&quot;&gt;GitBar website&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk: Gemini + Chrome: Oltre la Chat, Bologna JS Meetup</title>
		<link href="https://andreaverlicchi.eu/en/blog/bologna-js-gemini-chrome-devtools-mcp/"/>
		<updated>2026-02-25T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/bologna-js-gemini-chrome-devtools-mcp/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/qS--BYanGM-648.webp 648w, https://andreaverlicchi.eu/img/qS--BYanGM-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;undefined&quot; srcset=&quot;https://andreaverlicchi.eu/img/qS--BYanGM-648.heif 648w, https://andreaverlicchi.eu/img/qS--BYanGM-1296.heif 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Bologna JS Meetup - Gemini + Chrome: Oltre la Chat. Usare l&#39;AI per controllare il browser&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/qS--BYanGM-648.webp&quot; width=&quot;1296&quot; height=&quot;728&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Bologna JS Meetup&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On &lt;time datetime=&quot;2026-02-25&quot;&gt;Wednesday, February 25th, 2026&lt;/time&gt;, I presented at the &lt;a href=&quot;https://www.meetup.com/bologna-js-meetup/&quot;&gt;Bologna JS Meetup&lt;/a&gt; at Spazio01 Coworking in Bologna.&lt;/p&gt;
&lt;p&gt;The talk, titled &amp;quot;Gemini + Chrome: Oltre la Chat. Usare l&#39;AI per controllare il browser&amp;quot; (Gemini + Chrome: Beyond the Chat. Using AI to control the browser), was a demo of the &lt;a href=&quot;https://github.com/ChromeDevTools/chrome-devtools-mcp&quot;&gt;Chrome DevTools MCP Server&lt;/a&gt; — showing how to connect AI with Chrome DevTools through the &lt;a href=&quot;https://modelcontextprotocol.io/&quot;&gt;Model Context Protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I showed practical examples of how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read the DOM in real-time and manipulate web pages&lt;/li&gt;
&lt;li&gt;Run visual smoke tests across different viewports&lt;/li&gt;
&lt;li&gt;Simulate complex user interactions for end-to-end testing&lt;/li&gt;
&lt;li&gt;Intercept network requests and analyze performance metrics&lt;/li&gt;
&lt;li&gt;Identify performance bottlenecks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/bologna-js-meetup/events/313427486/&quot;&gt;🔗 Event page&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk video: &quot;Ehi Gemini, sistema il CSS!&quot;, Bologna Front-end #58</title>
		<link href="https://andreaverlicchi.eu/en/blog/bologna-front-end-gemini-chrome-devtools-mcp/"/>
		<updated>2025-12-09T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/bologna-front-end-gemini-chrome-devtools-mcp/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/qBSIBBiQMA-648.webp 648w, https://andreaverlicchi.eu/img/qBSIBBiQMA-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;undefined&quot; srcset=&quot;https://andreaverlicchi.eu/img/qBSIBBiQMA-648.heif 648w, https://andreaverlicchi.eu/img/qBSIBBiQMA-1296.heif 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Bologna Front-end meetup episode 58 - Ehi Gemini, sistema il CSS! with Andrea Verlicchi&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/qBSIBBiQMA-648.webp&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Bologna Front-end #58&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On &lt;time datetime=&quot;2025-12-09&quot;&gt;Tuesday, December 9th, 2025&lt;/time&gt;, I presented at the 58th episode of &lt;a href=&quot;https://www.meetup.com/bologna-front-end/&quot;&gt;Bologna Front-end&lt;/a&gt; at Granata venue in Bologna.&lt;/p&gt;
&lt;p&gt;The talk, titled &amp;quot;Ehi Gemini, sistema il CSS!&amp;quot; (Hey Gemini, fix the CSS!), was a live demo of the &lt;a href=&quot;https://github.com/ChromeDevTools/chrome-devtools-mcp&quot;&gt;Chrome DevTools MCP Server&lt;/a&gt; — a tool that lets you control Chrome DevTools through the &lt;a href=&quot;https://modelcontextprotocol.io/&quot;&gt;Model Context Protocol&lt;/a&gt; (MCP), using natural language commands from your terminal.&lt;/p&gt;
&lt;p&gt;I showed how to leverage it to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run accessibility audits&lt;/li&gt;
&lt;li&gt;Debug complex CSS layouts&lt;/li&gt;
&lt;li&gt;Simulate different network conditions&lt;/li&gt;
&lt;li&gt;Test custom viewports for responsive design&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All through natural language, without leaving the terminal. Pretty neat stuff!&lt;/p&gt;
&lt;h2 id=&quot;watch&quot; tabindex=&quot;-1&quot;&gt;Watch &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/bologna-front-end-gemini-chrome-devtools-mcp/#watch&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/sCHuoalAJCs&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; loading=&quot;lazy&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/bologna-front-end/events/312180052/&quot;&gt;🔗 Event page&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Google Antigravity: The New IDE That Embraces Agentic AI</title>
		<link href="https://andreaverlicchi.eu/en/blog/google-antigravity-new-ide-agentic-ai/"/>
		<updated>2025-11-24T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/google-antigravity-new-ide-agentic-ai/</id>
		<content type="html">&lt;p&gt;There’s a new IDE from Google that embraces agentic AI and leverages Gemini 3: &lt;a href=&quot;https://antigravity.google/&quot;&gt;Google Antigravity&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/7qVgD3KN79-648.webp 648w, https://andreaverlicchi.eu/img/7qVgD3KN79-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/7qVgD3KN79-648.png 648w, https://andreaverlicchi.eu/img/7qVgD3KN79-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A bright and futuristic abstract representation of the Google Antigravity IDE interface.&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/7qVgD3KN79-648.png&quot; width=&quot;1296&quot; height=&quot;695&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;With Gemini 3&#39;s advanced reasoning, tooling, and autonomous programming capabilities, Google Antigravity transforms AI assistance from a tool in a developer&#39;s toolkit to an active partner. While the core of Google Antigravity is a familiar AI IDE experience, its agents have been elevated to a dedicated interface and gained direct access to the editor, terminal, and browser. Now agents can autonomously plan and execute complex, end-to-end software tasks on your behalf, while validating their own code.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/SVCBA-pBgt0?si=-KPiJ6v2sxRXdude&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;On Friday, my workmate Brian and I put it to work on some complex task in the development of the project we&#39;re working on, with the Gemini 3 model, and we were quite impressed by it.&lt;/p&gt;
&lt;p&gt;What I love about Antigravity is that it handles planning by producing two text artifacts, just like a Tech Lead would: a &lt;strong&gt;Walkthrough&lt;/strong&gt; and &lt;strong&gt;Tasks&lt;/strong&gt;. You can provide feedback on these — whether it made a mistake or if the prompt wasn&#39;t specific enough — by selecting text and commenting on it, similar to how you would in Google Docs or Notion. You can also give feedback on the entire approach, much like in a Pull Request. I almost always write &amp;quot;LGTM&amp;quot; (Looks Good To Me) there. Then it starts working. Actually, lately, it starts even before your feedback to get a head start, confident in its plan, and can correct course later if needed.&lt;/p&gt;
&lt;p&gt;I tried working without Antigravity, using only OpenSpec with Gemini 3 via the &lt;code&gt;gemini-cli&lt;/code&gt;, but it felt more cumbersome and frustrating. The CLI isn&#39;t asynchronous like Antigravity, so you lose a lot of time waiting for the AI to think. Antigravity breaks everything down into smaller tasks that are easier and faster for the AI to handle, so it effectively starts working sooner and finishes faster.&lt;/p&gt;
&lt;p&gt;Then there&#39;s the &lt;strong&gt;Agent Manager&lt;/strong&gt;. If you feel like being an AI-powered superhero coder, you can ask it to do several things in parallel, even on different repos (or different clones of the same repo if you need to work on two different branches).&lt;/p&gt;
&lt;p&gt;I wanted to know more on how to use it best, so this weekend I took some time to watch a couple of videos that I highly recommend.&lt;/p&gt;
&lt;h2 id=&quot;learn-the-basics-of-google-antigravity&quot; tabindex=&quot;-1&quot;&gt;Learn the basics of Google Antigravity &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-antigravity-new-ide-agentic-ai/#learn-the-basics-of-google-antigravity&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first one is &amp;quot;Learn the basics of Google Antigravity&amp;quot; from the Antigravity team.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/nTOVIGsqCuY?si=Q74TZpCHCD14C2EY&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;This video provides an official introduction and walkthrough of Anti-gravity&#39;s core components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Three Main Surfaces&lt;/strong&gt;: The tool combines an &lt;strong&gt;Agent Manager&lt;/strong&gt; (to create and manage agents), an &lt;strong&gt;Editor&lt;/strong&gt; (a full IDE experience), and a &lt;strong&gt;Browser&lt;/strong&gt; (incorporating an agent directly inside Chrome for autonomous testing).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent Assisted Development&lt;/strong&gt;: The LLM is set up to automatically make decisions and implement easy tasks. For complex issues, it can pause and prompt the user for clarification.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Artifacts for Transparency&lt;/strong&gt;: The agent generates markdown files like &lt;strong&gt;Implementation Plans&lt;/strong&gt; and &lt;strong&gt;Walkthroughs&lt;/strong&gt; to document its progress and changes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parallel Task Execution&lt;/strong&gt;: Developers can kick off a task for the agent and start another complex task themselves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autonomous Testing&lt;/strong&gt;: The agent can launch the integrated browser to verify its own code changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;google-antigravity-the-new-best-ai-editor&quot; tabindex=&quot;-1&quot;&gt;Google Antigravity: The New Best AI Editor? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-antigravity-new-ide-agentic-ai/#google-antigravity-the-new-best-ai-editor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want a more in-depth view, check out &amp;quot;Google Antigravity: The New Best AI Editor?&amp;quot; from &amp;quot;AI with Brandon&amp;quot;.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/j0UPItO6BX4?si=Nlfsk8KXBsgRcG2J&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;This review highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agent Manager Inbox&lt;/strong&gt;: The main interface is designed like an email inbox for managing multiple projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Free Gemini 3 Pro Access&lt;/strong&gt;: Includes free access to Gemini 3 Pro within the editor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complex Task Handling&lt;/strong&gt;: The reviewer demonstrates the agent successfully implementing a full-stack feature involving multiple external services (trigger.dev, OpenAI TTS, blob store, database, and UI updates).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It looks like it&#39;s gonna change the way we develop, by turning us into... orchestrators of agents?&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Improving Web Responsiveness - Interactivity improvements from real-world cases</title>
		<link href="https://andreaverlicchi.eu/en/blog/improving-web-responsiveness-interactivity-improvements-from-real-world-cases/"/>
		<updated>2025-11-01T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/improving-web-responsiveness-interactivity-improvements-from-real-world-cases/</id>
		<content type="html">&lt;p&gt;On &lt;time datetime=&quot;2025-10-29&quot;&gt;Wednesday, October 29th, 2025&lt;/time&gt;, I had the pleasure of speaking at the &lt;a href=&quot;https://luma.com/ziykhh4y&quot;&gt;performance.sync()&lt;/a&gt; event in Amsterdam. It was a pre-conference meetup for the &lt;a href=&quot;https://perfnow.nl/&quot;&gt;performance.now()&lt;/a&gt; conference, and a great opportunity to meet and learn from other web performance experts.&lt;/p&gt;
&lt;p&gt;My talk, &amp;quot;Improving Web Responsiveness - Interactivity improvements from real-world cases&amp;quot;, was a 15-minute session where I shared practical techniques for debugging and optimizing slow interactions on websites.&lt;/p&gt;
&lt;p&gt;Interaction speed is a key aspect of a site’s responsiveness to user interactions. This talk demonstrates practical techniques for improving slow interactions through real-world case studies of debugging and optimizing poor interaction speed.&lt;/p&gt;
&lt;p&gt;Watch the video of the talk if you want to understand how to identify, troubleshoot, and fix slow interactions, ensuring a consistently responsive user experience.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/HSLLBUXuu08&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;The slides are available at the following link.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.google.com/presentation/d/1yrjOQV4CVB7AsA1onIj-QLALe4pG71YI3EHasEd5KCQ/edit?usp=sharing&quot;&gt;📽️ Slides&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And here&#39;s just a picture of me on stage, just to provide eleventy with an image for the posts list. 😉&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Gjh5wPI1Ul-648.webp 648w, https://andreaverlicchi.eu/img/Gjh5wPI1Ul-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/Gjh5wPI1Ul-648.jpeg 648w, https://andreaverlicchi.eu/img/Gjh5wPI1Ul-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi wearing a yellow sweater speaking on stage at the performance.sync() meetup in Amsterdam. The current slide shows &amp;quot;Slow GTM Code. Audit. Remove. Update. Not enough?&amp;quot;&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Gjh5wPI1Ul-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;On stage at performance.sync() 2025.&lt;/figcaption&gt;
&lt;/figure&gt;</content>
	</entry>
	
	<entry>
		<title>The macOS clipboard manager you&#39;ve been waiting for, now native in MacOS 26 Tahoe</title>
		<link href="https://andreaverlicchi.eu/en/blog/how-to-use-multiple-clipboard-feature-on-macOS-26-tahoe/"/>
		<updated>2025-09-16T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/how-to-use-multiple-clipboard-feature-on-macOS-26-tahoe/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/xjOsbWNCeV-509.webp 509w, https://andreaverlicchi.eu/img/xjOsbWNCeV-1018.webp 1018w&quot; sizes=&quot;509px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/xjOsbWNCeV-509.png 509w, https://andreaverlicchi.eu/img/xjOsbWNCeV-1018.png 1018w&quot; sizes=&quot;509px&quot;&gt;&lt;img alt=&quot;Spotlight overlay showing the title &#39;Clipboard&#39; and – in the history – different text, code and image items&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/xjOsbWNCeV-509.png&quot; width=&quot;1018&quot; height=&quot;759&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;A screenshot of the Spotlight overlay showing the (searchable) clipboard history.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You know when you copy a piece of code, then you copy another one and you lose the previous one? Or you know you have something in your clipboard, you&#39;d like to copy something else, but you have to paste what&#39;s in your clipboard first, otherwise you&#39;ll lose it? No more clipboard stress. Finally, multiple clipboard landed on macOS 26 Tahoe.&lt;/p&gt;
&lt;p&gt;With the release of macOS Tahoe, you no longer have to rely on third-party apps to access items you&#39;ve copied in the past. It&#39;s a game-changer for anyone who regularly copies and pastes multiple pieces of text (including code blocks), links, or images.&lt;/p&gt;
&lt;p&gt;Here’s a quick guide on how to start using this long-awaited feature and supercharge your workflow.&lt;/p&gt;
&lt;h3 id=&quot;enabling-clipboard-history&quot; tabindex=&quot;-1&quot;&gt;Enabling Clipboard History &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-use-multiple-clipboard-feature-on-macOS-26-tahoe/#enabling-clipboard-history&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The clipboard history is built right into Spotlight, but it&#39;s not immediately visible. The first time you use it, you&#39;ll need to enable it. Here&#39;s how:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Press &lt;code&gt;Command (⌘)&lt;/code&gt; + &lt;code&gt;Space&lt;/code&gt; to open Spotlight.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, you have two options to access the new clipboard features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Press the &lt;code&gt;Tab&lt;/code&gt; key to reveal the new Spotlight menus.&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Command (⌘)&lt;/code&gt; + &lt;code&gt;4&lt;/code&gt; to go directly to the &lt;strong&gt;Clipboard&lt;/strong&gt; tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The first time you do this, a prompt will appear asking you to enable the feature. Just click &amp;quot;Enable&amp;quot; and you&#39;re good to go!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;using-the-clipboard-history&quot; tabindex=&quot;-1&quot;&gt;Using the Clipboard History &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-use-multiple-clipboard-feature-on-macOS-26-tahoe/#using-the-clipboard-history&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once enabled, using the clipboard history is super simple. Whenever you want to access a previously copied item:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Command (⌘)&lt;/code&gt; + &lt;code&gt;Space&lt;/code&gt; to open &lt;strong&gt;Spotlight&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Command (⌘)&lt;/code&gt; + &lt;code&gt;4&lt;/code&gt; to bring up the Clipboard tab in Spotlight.&lt;/li&gt;
&lt;li&gt;You&#39;ll see a list of the text, links, and images you&#39;ve copied.&lt;/li&gt;
&lt;li&gt;Use your arrow keys or the mouse to select the item you want.&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Enter&lt;/code&gt; or click on the item to re-copy it to your clipboard.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From there, you can paste it anywhere using the standard &lt;code&gt;Command (⌘)&lt;/code&gt; + &lt;code&gt;V&lt;/code&gt; shortcut.&lt;/p&gt;
&lt;h3 id=&quot;a-few-things-to-note&quot; tabindex=&quot;-1&quot;&gt;A Few Things to Note &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-use-multiple-clipboard-feature-on-macOS-26-tahoe/#a-few-things-to-note&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While this is a huge step forward for macOS, it&#39;s worth noting a few of its current limitations. For example, it only saves your copied items for about eight hours, and there&#39;s no way to pin or save items permanently. If you need a more advanced solution with features like custom shortcuts, unlimited history, or smart filters, a third-party app might still be the way to go.&lt;/p&gt;
&lt;p&gt;But for the average user, this new built-in feature is a major productivity boost and a very welcome addition to macOS. No more frantic re-copying!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk video: &quot;Debugging and Optimizing Interaction to Next Paint (INP) for a Smoother Web&quot;, Performance Observer Meetup</title>
		<link href="https://andreaverlicchi.eu/en/blog/performance-observer-meetup-talk/"/>
		<updated>2025-04-16T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/performance-observer-meetup-talk/</id>
		<content type="html">&lt;p&gt;On &lt;time datetime=&quot;2025-04-16&quot;&gt;16 April 2025&lt;/time&gt;, I had the pleasure of speaking at one of the excellent Performance Observer meetups. The Performance Observer community focuses on sharing knowledge and practical insights into web performance monitoring and optimization. You can check out their past and future events &lt;a href=&quot;https://performanceobserver.dev/events/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My talk was titled &amp;quot;Debugging and Optimizing Interaction to Next Paint (INP) for a Smoother Web&amp;quot;. Here is the video recording of the session:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/pCNvVC5aTqk?si=or7DgTYR2KUYQAZ0&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;In this talk, I delved into the practical aspects of identifying and fixing Interaction to Next Paint (INP) issues. I covered common causes of poor responsiveness that I&#39;ve encountered and demonstrated techniques using browser developer tools and performance monitoring data to pinpoint bottlenecks. The goal was to provide actionable strategies to improve user interaction speed and achieve better INP scores, keeping experiences snappy for users.&lt;/p&gt;
&lt;p&gt;The Performance Observer meetups are a fantastic series dedicated to all things web performance, regularly featuring talks from industry experts on monitoring, optimization, and the latest performance metrics. It was great to contribute to this knowledgeable community.&lt;/p&gt;
&lt;figure&gt;
  &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/PUBDOGIwN3-800.webp 800w&quot; sizes=&quot;800px&quot;&gt;&lt;img alt=&quot;Presenter speaking during the online Performance Observer meetup. A slide with performance data is visible.&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/PUBDOGIwN3-800.png&quot; width=&quot;800&quot; height=&quot;448&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;Presenting during the Performance Observer meetup session.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.google.com/presentation/d/1_okzKg2FagXQHG68f4yiwPwS5XGfK5aFY3CWi7QmOG8/edit&quot;&gt;📽️ Slides&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Introducing yieldy-for-loop: an npm package to keep your loops non-blocking (and your UI smooth)</title>
		<link href="https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/"/>
		<updated>2025-01-14T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/</id>
		<content type="html">&lt;p&gt;If you’ve ever had to process thousands (or millions) of items in JavaScript, you’ve likely experienced that dreaded lag or UI freeze. It can happen when you perform intensive loops on the main thread, blocking updates to the interface. To tackle this, I’ve created an NPM package called &lt;a href=&quot;https://www.npmjs.com/package/yieldy-for-loop&quot;&gt;yieldy-for-loop&lt;/a&gt;. This tiny utility helps you break large loops into chunks, periodically yielding control to the browser so your application remains responsive.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/OdlkifvJiX-648.webp 648w, https://andreaverlicchi.eu/img/OdlkifvJiX-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/OdlkifvJiX-648.png 648w, https://andreaverlicchi.eu/img/OdlkifvJiX-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;yieldy-for-loop on npm&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/OdlkifvJiX-648.png&quot; width=&quot;1296&quot; height=&quot;693&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;yieldy-for-loop in npm&#39;s website&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;background&quot; tabindex=&quot;-1&quot;&gt;Background &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#background&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Long tasks&lt;/strong&gt; are a common performance bottleneck in front-end applications. When the main thread is busy running large loops, browsers can’t update the UI, and users may notice unresponsiveness or janky scrolling. Inspired by the article &lt;a href=&quot;https://calendar.perfplanet.com/2024/breaking-up-with-long-tasks-or-how-i-learned-to-group-loops-and-wield-the-yield/&quot;&gt;“Breaking up with long tasks, or how I learned to group loops and wield the yield” (PerfPlanet 2024)&lt;/a&gt;, I wanted a simple, reusable function that would:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Break large loops&lt;/strong&gt; into smaller batches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Yield to the browser&lt;/strong&gt; after each batch, giving the rendering engine a chance to paint and the user a chance to interact.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Adapt&lt;/strong&gt; to whether the document is visible or hidden, since work behind a hidden tab can be deprioritized or even paused in many browsers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hence, &lt;code&gt;yieldy-for-loop&lt;/code&gt; was born.&lt;/p&gt;
&lt;h2 id=&quot;what-it-does&quot; tabindex=&quot;-1&quot;&gt;What it does &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#what-it-does&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Non-blocking iteration&lt;/strong&gt;: Processes your items in batches, aiming to stay within a target time slice (e.g., 33ms for ~30 FPS).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-yield logic&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;If the page is &lt;strong&gt;hidden&lt;/strong&gt;, yields less frequently (e.g., every 500ms) to save resources.&lt;/li&gt;
&lt;li&gt;If the page is &lt;strong&gt;visible&lt;/strong&gt;, yields more frequently to keep animations and user interactions smooth.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser compatibility&lt;/strong&gt;: Uses a race between a short &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;requestAnimationFrame&lt;/code&gt;, and optionally calls the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Scheduler&quot;&gt;Scheduler API&lt;/a&gt; if available.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;installation&quot; tabindex=&quot;-1&quot;&gt;Installation &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#installation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; yieldy-for-loop&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;usage-example&quot; tabindex=&quot;-1&quot;&gt;Usage example &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#usage-example&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; yieldyForLoop &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;yieldy-for-loop&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Your heavy processing logic&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Processing item:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Starting yieldy loop...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;yieldyForLoop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; processItem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;fps&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;              &lt;span class=&quot;token comment&quot;&gt;// Aim for ~30 frames per second&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;hiddenThreshold&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Yield threshold (in ms) when tab is hidden&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;All items processed without blocking the UI!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;how-it-works&quot; tabindex=&quot;-1&quot;&gt;How it works &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#how-it-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Time Slice Calculation&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;The default frames per second (FPS) is set to &lt;strong&gt;30&lt;/strong&gt;, so it calculates a batch duration of ~33ms.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;shouldYield()&lt;/code&gt; Check&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Before processing each item, the function checks how much time has passed since the last yield.&lt;/li&gt;
&lt;li&gt;If it exceeds the threshold (e.g., ~33ms or 500ms if the document is hidden), it yields control back to the browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Yielding Mechanisms&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page Hidden&lt;/strong&gt;: Uses &lt;code&gt;setTimeout(resolve, 1)&lt;/code&gt;—just enough to let other tasks slip in.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Page Visible&lt;/strong&gt;: Uses a combination of &lt;code&gt;requestAnimationFrame&lt;/code&gt; and a short timeout. If the experimental &lt;code&gt;scheduler.yield()&lt;/code&gt; is available, it calls that as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By splitting your loop into batches, the browser has breathing room to render, respond to user input, and run other scripts, thereby avoiding the dreaded “page unresponsive” problem.&lt;/p&gt;
&lt;h2 id=&quot;why-you-need-this&quot; tabindex=&quot;-1&quot;&gt;Why you need this &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#why-you-need-this&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Better user experience&lt;/strong&gt;: Smooth scrolling, responsive buttons, and no random freezing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy to use&lt;/strong&gt;: Just wrap your normal loop logic with &lt;code&gt;yieldyForLoop&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Micro-optimized&lt;/strong&gt;: The code is minimal and straightforward, so it’s easy to maintain or customize.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;next-steps&quot; tabindex=&quot;-1&quot;&gt;Next steps &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#next-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Try it out&lt;/strong&gt;: Install the package, import it, and integrate it into any heavy loop you have.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contributions&lt;/strong&gt;: Issues and pull requests are welcome! Check out the &lt;a href=&quot;https://github.com/YourUsername/yieldy-for-loop&quot;&gt;GitHub repo&lt;/a&gt; to file bugs, request features, or open PRs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spread the word&lt;/strong&gt;: If you find this helpful, let others know.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;shout-out&quot; tabindex=&quot;-1&quot;&gt;Shout-out &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#shout-out&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A special thanks to &lt;a href=&quot;https://rviscomi.dev/&quot;&gt;Rick Viscomi&lt;/a&gt; for writing the PerfPlanet article that inspired me to build this.
Breaking up large tasks into smaller chunks has become a key performance strategy, and &lt;code&gt;yieldy-for-loop&lt;/code&gt; aims to make it even easier to adopt.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/introducing-yieldy-for-loop/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Long loops don’t have to mean unresponsive UIs. By periodically yielding to the browser, you can maintain a slick experience for your users. &lt;code&gt;yieldy-for-loop&lt;/code&gt; takes care of the heavy lifting with minimal code, letting you focus on what you do best—building amazing web apps.&lt;/p&gt;
&lt;p&gt;If you have questions, reach out or open an issue on GitHub.
Now, go forth and keep those loops running smoothly.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Optimizing SVG Usage for Web Performance: A Comprehensive Discussion</title>
		<link href="https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/"/>
		<updated>2024-12-05T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/</id>
		<content type="html">&lt;p&gt;In a recent conversation among web performance enthusiasts, the topic of efficiently loading SVGs (Scalable Vector Graphics) on websites was explored in depth. The discussion centered around the best methods for incorporating SVGs, particularly icons, with performance in mind. Various techniques were compared, including inline SVGs, the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag, CSS backgrounds, and SVG sprites. Here&#39;s a summary of the key insights and recommendations from that conversation.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/7JYSvCHYQ1-648.webp 648w, https://andreaverlicchi.eu/img/7JYSvCHYQ1-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/7JYSvCHYQ1-648.jpeg 648w, https://andreaverlicchi.eu/img/7JYSvCHYQ1-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A set of SVG icons&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/7JYSvCHYQ1-648.jpeg&quot; width=&quot;1296&quot; height=&quot;863&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;SVG images are widely used to make icons on the web&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Let&#39;s consider the following methods for loading SVGs.&lt;/p&gt;
&lt;h2 id=&quot;1-inline-svgs&quot; tabindex=&quot;-1&quot;&gt;1. Inline SVGs &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#1-inline-svgs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Ideal for above-the-fold icons like logos or menu buttons, especially when you need to style or animate individual elements within the SVG using CSS or JavaScript.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Styling Flexibility:&lt;/strong&gt; Allows for direct manipulation of SVG elements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Immediate Rendering:&lt;/strong&gt; No additional HTTP requests since the SVG is part of the HTML.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Increased DOM Size:&lt;/strong&gt; Each inline SVG adds to the DOM, which can impact performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance Overhead:&lt;/strong&gt; Selectable and styleable elements may affect rendering performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;URL-Encoding over Base64:&lt;/strong&gt; When embedding SVGs inline using data URLs, URL-encode them instead of base64-encoding to achieve better compression.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limit Use:&lt;/strong&gt; Reserve inline SVGs for essential, above-the-fold graphics that require interactivity.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2-img-tag&quot; tabindex=&quot;-1&quot;&gt;2. &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#2-img-tag&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Suitable for general icons and images where styling or interaction isn&#39;t necessary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lazy Loading:&lt;/strong&gt; Supports the &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt; attribute to defer loading images until they are needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simpler DOM:&lt;/strong&gt; Keeps the DOM cleaner compared to inline SVGs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited Styling:&lt;/strong&gt; Cannot manipulate internal SVG elements directly through CSS or JavaScript.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static Content:&lt;/strong&gt; Not ideal for icons that need to change color or shape on hover.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dimension Attributes:&lt;/strong&gt; Always include &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; to prevent layout shifts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid Lazy Loading for Immediate Assets:&lt;/strong&gt; Do not lazy-load images that are crucial to the initial rendering or immediate interactions like hover states.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-css-background-images&quot; tabindex=&quot;-1&quot;&gt;3. CSS background images &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#3-css-background-images&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Best for decorative graphics or background patterns that don&#39;t require interactivity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Separation of Concerns:&lt;/strong&gt; Keeps background images within CSS, maintaining a clean HTML structure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conditional Loading:&lt;/strong&gt; Can be combined with media queries or JavaScript for responsive designs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited Control:&lt;/strong&gt; Harder to manipulate or animate compared to inline SVGs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accessibility Issues:&lt;/strong&gt; Background images are not read by screen readers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lazy Loading:&lt;/strong&gt; Use JavaScript libraries like &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; to defer loading of background images if they are not immediately visible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Appropriate Usage:&lt;/strong&gt; Reserve for non-critical, decorative elements.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;4-svg-sprites-and-use-tag&quot; tabindex=&quot;-1&quot;&gt;4. SVG sprites and &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; tag &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#4-svg-sprites-and-use-tag&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Effective when you need multiple instances of icons that can be styled or animated, and when serving SVGs from the same domain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reusable Symbols:&lt;/strong&gt; Define SVG symbols once and reference them multiple times.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Styling Capabilities:&lt;/strong&gt; Allows CSS styling of SVG elements as if they were inline.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced HTTP Requests:&lt;/strong&gt; Consolidates icons into a single file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Initial Setup Complexity:&lt;/strong&gt; Requires creating and managing an external sprite file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Same-Origin Policy:&lt;/strong&gt; The external SVG sprite must be on the same domain due to browser security restrictions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Best practices:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Efficient Organization:&lt;/strong&gt; Group commonly used icons into a single sprite file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fallbacks:&lt;/strong&gt; Implement fallbacks for browsers that might not support external SVG sprites.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;match-method-to-your-use-case&quot; tabindex=&quot;-1&quot;&gt;Match method to your use case &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#match-method-to-your-use-case&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Choose the SVG loading method based on the specific needs of your project. Inline SVGs for interactive elements, &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags for static icons, CSS backgrounds for decorative images, and SVG sprites for reusable, stylable icons.&lt;/p&gt;
&lt;h2 id=&quot;performance-considerations&quot; tabindex=&quot;-1&quot;&gt;Performance considerations &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#performance-considerations&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DOM Size Matters:&lt;/strong&gt; Excessive inline SVGs can bloat the DOM and degrade performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lazy Loading Wisely:&lt;/strong&gt; Use lazy loading for images not immediately needed, but avoid it for assets required for initial interactions or hover effects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compression Techniques:&lt;/strong&gt; Prefer URL-encoding over base64 when embedding SVGs in data URLs to maintain better compression ratios.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;styling-and-interactivity&quot; tabindex=&quot;-1&quot;&gt;Styling and interactivity &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#styling-and-interactivity&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Interactive Icons:&lt;/strong&gt; Use inline SVGs or SVG sprites with the &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; tag when icons need to respond to user interactions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static Icons:&lt;/strong&gt; Use &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags for icons that don&#39;t require interactivity to keep the DOM lean.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;accessibility-and-semantics&quot; tabindex=&quot;-1&quot;&gt;Accessibility and semantics &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#accessibility-and-semantics&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Proper Attributes:&lt;/strong&gt; Include &lt;code&gt;alt&lt;/code&gt; attributes for &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags and &lt;code&gt;aria-label&lt;/code&gt; or &lt;code&gt;role=&amp;quot;img&amp;quot;&lt;/code&gt; for inline SVGs to enhance accessibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid Background Images for Essential Content:&lt;/strong&gt; Since CSS background images are ignored by assistive technologies, don&#39;t use them for important content.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;avoid-outdated-techniques&quot; tabindex=&quot;-1&quot;&gt;Avoid outdated techniques: &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#avoid-outdated-techniques&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Image Sprites:&lt;/strong&gt; Traditional image sprites are largely considered outdated due to the complexity and diminishing returns in the era of HTTP/2 and HTTP/3.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Font Icons:&lt;/strong&gt; Consider migrating away from icon fonts to SVGs for better scalability and styling flexibility, as detailed in &lt;a href=&quot;https://calendar.perfplanet.com/2021/from-fonts-to-svg-an-icon-migration-strategy/&quot;&gt;Erwin Hofman&#39;s article&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Optimizing SVG usage on websites involves balancing performance, maintainability, and functionality. By selecting the appropriate method for loading SVGs based on their purpose—whether for static display, styling, or interactivity—you can enhance both the user experience and site performance. Remember to consider factors like DOM size, lazy loading, and accessibility when implementing SVGs in your projects.&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot; tabindex=&quot;-1&quot;&gt;Further reading &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/loading_svg_images_icons_performance_considerations/#further-reading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://svgsprit.es/&quot;&gt;SVG sprites generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tympanus.net/codrops/2015/07/16/styling-svg-use-content-css/&quot;&gt;Styling SVG &lt;use&gt; Content with CSS&lt;/use&gt;&lt;/a&gt; by Sara Soueidan&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://calendar.perfplanet.com/2021/from-fonts-to-svg-an-icon-migration-strategy/&quot;&gt;From Fonts to SVG: An Icon Migration Strategy&lt;/a&gt; by Erwin Hofman&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload GitHub Repository&lt;/a&gt; by Andrea Verlicchi (yours truly)&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk video: &quot;How I made the web more responsive — real-world case studies of INP optimizations&quot;, We Love Speed 2024 conference</title>
		<link href="https://andreaverlicchi.eu/en/blog/how-i-made-web-more-responsive-inp-video-we-love-speed-2024-nantes/"/>
		<updated>2024-11-26T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/how-i-made-web-more-responsive-inp-video-we-love-speed-2024-nantes/</id>
		<content type="html">&lt;p&gt;On &lt;time datetime=&quot;2024-07-17&quot;&gt;17 September 2024&lt;/time&gt;, I spoke at the We Love Speed 2024 conference about enhancing web responsiveness. Specifically, I discussed how to debug and avoid slow interactions based on my experience on auditing Interaction to Next Paint (INP) on clients&#39; websites.&lt;/p&gt;
&lt;p&gt;The title of the talk was &amp;quot;How I made the web more responsive - real-world case studies of INP optimizations&amp;quot;, in French &amp;quot;Comment j’ai rendu le web plus réactif — études de cas concrets d’optimisations d’INP&amp;quot;, and this is the video of my talk.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/FDb4aKLIVsI?si=WNNwr8DcyRAplbKB&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;After providing an initial explanation of INP, I demonstrate how to debug slow interactions using both Chrome DevTools and Real User Monitoring (RUM) data. I then illustrate three common mistakes I encountered while auditing INP on dozens of websites and explain how to avoid them to ensure snappy user interactions and keep your INP below 200 milliseconds.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/qB1-i3O1fD-648.webp 648w, https://andreaverlicchi.eu/img/qB1-i3O1fD-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/qB1-i3O1fD-648.jpeg 648w, https://andreaverlicchi.eu/img/qB1-i3O1fD-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi speaking on stage at We Love Speed, Nantes. The slide shows the flame chart of the performance trace run after an INP optimization&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/qB1-i3O1fD-648.jpeg&quot; width=&quot;1296&quot; height=&quot;863&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;On stage at We Love Speed 2024.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.google.com/presentation/d/1kSHr9mEN2Q4Nyis8uWvxoA3_pqOIywr3TXCLeO_-4qA/edit&quot;&gt;📽️ Slides&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>The web is dead, long live the web (repost in English)</title>
		<link href="https://andreaverlicchi.eu/en/blog/the-web-is-dead-long-live-the-web-antonio-moro-itomi/"/>
		<updated>2024-11-22T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/the-web-is-dead-long-live-the-web-antonio-moro-itomi/</id>
		<content type="html">&lt;p&gt;👀 The author of this article is Antonio Moro aka Itomi.
&lt;br&gt;&lt;a href=&quot;https://www.clickbaiting.it/p/il-web-e-morto-lunga-vita-al-web&quot;&gt;🇮🇹 Original article&lt;/a&gt; | &lt;a href=&quot;https://itomi.studio/&quot;&gt;Itomi Studio&lt;/a&gt; | &lt;a href=&quot;https://itomi.studio/about/&quot;&gt;About&lt;/a&gt; | &lt;a href=&quot;https://itomi.shop/&quot;&gt;Shop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The closure of Badtaste.it is just the latest closing on a coffin that has already been closed for years: online publishing as we have known it for the past twenty years is now dead and buried.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/WmlI0fe2k1-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Meme of the young boy giving his thumbs up on camera while using a computer&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/WmlI0fe2k1-648.jpeg&quot; width=&quot;648&quot; height=&quot;364&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Yesterday, news broke that Badtaste.it is shutting down after 20 years of activity. It’s not a surprise, at least not to me. It’s just the latest signal among many over the last five years. And anyone blaming the pandemic has understood very little about what’s really happened.&lt;/p&gt;
&lt;p&gt;I’m one of those who has been part of “online publishing,” as it’s been fashionably called for years, in Italy since its inception—back when it was simply called “posting on a blog.” The party lasted 20 years, then it ended. And even if some are lingering at the exit, there’s not much to be done. The music has stopped.&lt;/p&gt;
&lt;p&gt;Thankfully, I had the clarity to get out before it completely imploded. Three years ago, I stepped down from the leadership of the site I founded and directed for 12 years and started a publishing house based on a completely different project—one that returns to the physical object and abandons the &amp;quot;all digital&amp;quot; concept so cherished by this industry over the last two decades.&lt;/p&gt;
&lt;p&gt;The web is dead, and it largely killed itself. It killed itself when it let a single company and a single search engine dictate the rules upon which it relied.&lt;/p&gt;
&lt;p&gt;It killed itself when it handed over the communities it painstakingly built over the years to a few social networks.&lt;/p&gt;
&lt;p&gt;For years, Google dictated how online articles had to be written, published, and formatted. What keywords and how many needed to be included in every piece for it to even make sense to publish. We stopped writing for our audience and, without even realizing it, started writing for Google’s algorithm—to get more traffic, more people onto our content. We became addicted to a substance that never nourished us: blind, useless traffic made up of people who didn’t even know what they were reading or where they were reading it. We erased the identities of our sites and blogs, turning them into sterile containers of personality-free content.&lt;/p&gt;
&lt;p&gt;Facebook, the only other strong source of traffic, finished the job. It took away our communities, our loyal readers. It took away interactions, devouring what we had built. The moment we started seeing “Comments: Zero” as normal under our articles, our sites began dying irreversibly.&lt;/p&gt;
&lt;p&gt;We abandoned a small, loyal, and engaged audience for a large, disinterested, and unaware one.&lt;/p&gt;
&lt;p&gt;Blogs and editorial sites were born because a few enthusiasts wanted to share their ideas, opinions, and content. We did it for free, in our spare time. And those who read us did so for free. And we were happy with that.&lt;/p&gt;
&lt;p&gt;Then it became a job, and figuring out how to make money from it became crucial. Once we’d given away the fruits of our labor—our content—the only option left was to monetize through banners and ad campaigns.&lt;/p&gt;
&lt;p&gt;On Lega Nerd, I resisted for years, doing only “native” campaigns with advertisers aligned to my niche, keeping banner ads to a minimum because they killed readability and the overall user experience. Over time, the Internet economy and online advertising shifted more and more toward new players—today we call them “influencers,” but they’re just content creators like we were, only doing it differently and on other platforms, reaching massive audiences.&lt;/p&gt;
&lt;p&gt;It took advertisers a few years to grasp the power of influencers, but eventually, the money moved to creators. Running a campaign for your site was already difficult five years ago, let alone today.&lt;/p&gt;
&lt;p&gt;Now, the gods of websites are banners. They exploded at the end of the 2010s, thanks to the rise of “Real-Time Bidding” platforms that boosted their profitability, and we dove into this new opportunity, filling our sites with crap. Crap in every paragraph. Crap popping up over content. Crap autoplaying and staying fixed as you scroll to read. Crap everywhere.&lt;/p&gt;
&lt;p&gt;We needed more traffic, and we chased it by any means necessary. More traffic equaled more page views, more page views equaled more banners shown, and more banners equaled more money to keep the ship afloat.&lt;/p&gt;
&lt;p&gt;We needed more traffic from Google, so we wrote what it wanted, rebuilt our sites from scratch to its specifications, optimized everything as it dictated.&lt;/p&gt;
&lt;p&gt;We needed more traffic from social media, so we started publishing hundreds, thousands of news stories. Current events. Just a few lines, little substance, but enough for people scrolling through Facebook mindlessly. Thousands of news pieces per day. Then we went for clickbait—to make people click and land on our sites. And fake news—hundreds, thousands of sites created solely to generate traffic and monetize banners.&lt;/p&gt;
&lt;p&gt;Crap, covered in more crap.&lt;/p&gt;
&lt;p&gt;And those who genuinely believed in it, who wanted to publish interesting, independent, educational, informative content? They’re screwed.&lt;/p&gt;
&lt;p&gt;Screwed because they can’t compete with those who play by those rules without turning their site into crap too. Do you want to make a living, or do you want to write for a handful of people and earn nothing?&lt;/p&gt;
&lt;p&gt;The pandemic years further inflated the web artificially. Traffic grew, banners multiplied even more, and users’ patience ran out. It was only a couple of years of good news for publishers before plunging back into reality.&lt;/p&gt;
&lt;p&gt;Now banners pay almost nothing. Campaigns are gone. Monetizing an editorial site is harder than ever. We’ve made the web ugly, and now no one wants to look at it. People get their information elsewhere, without having to endure the crap that covers internet sites.&lt;/p&gt;
&lt;p&gt;We gave away our content for 20 years, and now no one wants to pay for it—especially after we published crap for years. No subscriptions. No “premium” areas. Nothing works anymore, and we don’t know where to turn.&lt;/p&gt;
&lt;p&gt;It’s time to close. To do something else.&lt;/p&gt;
&lt;p&gt;The young will figure out something new, something innovative and suited to the times. Fast times. Brutal times.&lt;/p&gt;
&lt;p&gt;I see a faint return to the past. Small communities of people tired of the bulimia of social media are emerging. Small editorial projects are being born that use the web but don’t rely solely on it. The web will never truly die.&lt;/p&gt;
&lt;p&gt;The web is dead. Long live the web.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>My experience at performance.now() 2024: Europe&#39;s premier web performance conference</title>
		<link href="https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/"/>
		<updated>2024-11-16T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/</id>
		<content type="html">&lt;p&gt;From &lt;strong&gt;November 14 to 15&lt;/strong&gt;, I attended &lt;a href=&quot;https://www.perfnow.nl/&quot;&gt;&lt;strong&gt;performance.now&lt;/strong&gt;&lt;/a&gt; in &lt;strong&gt;Amsterdam&lt;/strong&gt;, the most esteemed conference in the realm of web performance in Europe. As someone deeply embedded in this niche of web development, meeting other like-minded people at the event was both inspiring and invaluable.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/VIH8mSoDfg-648.webp 648w, https://andreaverlicchi.eu/img/VIH8mSoDfg-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/VIH8mSoDfg-648.png 648w, https://andreaverlicchi.eu/img/VIH8mSoDfg-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;performance.now() – Andrea Verlicchi – @verlok (he/him) – Speed Kit, IT, – Sponsors: Google, SpeedCurve, Mozilla, Akamai, Sentry. The image also contains stickers from Firefox, SpeedCurve #perfhero, No vanity metrics P50, Anti Javascript Javascript Club&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/VIH8mSoDfg-648.png&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;My performance.now 2024 badge, plus some swag and stickers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;exceptional-content-and-speakers&quot; tabindex=&quot;-1&quot;&gt;Exceptional Content and Speakers &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/#exceptional-content-and-speakers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/yvWX-HFVbQ-648.webp 648w, https://andreaverlicchi.eu/img/yvWX-HFVbQ-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/yvWX-HFVbQ-648.png 648w, https://andreaverlicchi.eu/img/yvWX-HFVbQ-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Schedule for first and second day, also available following the link in the figure caption&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/yvWX-HFVbQ-648.png&quot; width=&quot;1296&quot; height=&quot;1250&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The &lt;a href=&quot;https://perfnow.nl/schedule&quot;&gt;schedule&lt;/a&gt; for the two conference days.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;From the moment the conference commenced, it was evident that performance.now() stands out for its &lt;strong&gt;high-caliber content and &lt;a href=&quot;https://perfnow.nl/speakers&quot;&gt;speakers&lt;/a&gt;&lt;/strong&gt;. Each session was meticulously curated, featuring industry leaders who covered a wide array of topics surrounding modern web performance challenges and solutions.&lt;/p&gt;
&lt;p&gt;Keynotes explored the evolving landscape of web speed, emphasizing the critical need for responsiveness and user-centric metrics. Talks addressed diverse subjects, from accessibility&#39;s impact on performance to practical strategies for improving Core Web Vitals, particularly INP (Interaction to Next Paint). Other presentations focused on advanced tooling, font optimization, and minimizing third-party script impacts.&lt;/p&gt;
&lt;p&gt;With in-depth case studies and future-focused discussions, the event showcased cutting-edge techniques and encouraged a holistic view of web performance.&lt;/p&gt;
&lt;h2 id=&quot;connecting-with-like-minded-professionals&quot; tabindex=&quot;-1&quot;&gt;Connecting with like-minded professionals &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/#connecting-with-like-minded-professionals&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the highlights of the conference for me was the opportunity to &lt;strong&gt;connect with fellow professionals&lt;/strong&gt; who share the same passion for web performance. The numerous breaks and the lively after-party facilitated meaningful conversations and networking. It was refreshing to exchange ideas, discuss challenges, and explore potential collaborations with peers who truly understand the intricacies of our field.&lt;/p&gt;
&lt;p&gt;In addition to attending, I had the honor of contributing to the conference in two significant ways.&lt;/p&gt;
&lt;h3 id=&quot;contributing-in-the-help-desk-sponsored-by-google&quot; tabindex=&quot;-1&quot;&gt;Contributing in the help desk sponsored by Google &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/#contributing-in-the-help-desk-sponsored-by-google&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/vhmLxNlZ84-648.webp 648w, https://andreaverlicchi.eu/img/vhmLxNlZ84-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/vhmLxNlZ84-648.png 648w, https://andreaverlicchi.eu/img/vhmLxNlZ84-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Me at the help desk session with Morten Sorth and Ismail Gunsaya from Skyscanner&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/vhmLxNlZ84-648.png&quot; width=&quot;1296&quot; height=&quot;796&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Morten Sorth and Ismail Gunsaya from Skyscanner asking me about INP optimization&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;One of the key highlights for me was participating in the &lt;strong&gt;Google-sponsored Help Desk&lt;/strong&gt;, where I engaged with attendees for about half an hour, answering their questions and offering solutions to their web performance challenges. This experience not only allowed me to give back to the community but also to learn from the diverse array of problems and perspectives presented by other professionals.&lt;/p&gt;
&lt;h3 id=&quot;participating-in-henri-helveticas-live-interview-on-youtube&quot; tabindex=&quot;-1&quot;&gt;Participating in &lt;strong&gt;Henri Helvetica&#39;s live interview on YouTube&lt;/strong&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/#participating-in-henri-helveticas-live-interview-on-youtube&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
	&lt;img alt=&quot;Henri Helvetica and with a green and a red microphone during the live streaming&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/_gangJ34x9-648.webp&quot; width=&quot;1296&quot; height=&quot;863&quot; srcset=&quot;https://andreaverlicchi.eu/img/_gangJ34x9-648.webp 648w, https://andreaverlicchi.eu/img/_gangJ34x9-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;
	&lt;figcaption&gt;Henri Helvetica and me during the live streaming&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;One of the key highlights for me was participating in &lt;strong&gt;Henri Helvetica&#39;s live interview on YouTube&lt;/strong&gt;. Being interviewed by Henri provided an opportunity to share my experience and background with a broader audience. The interview delved into my personal background and personal challenges, and I loved that.&lt;/p&gt;
&lt;p&gt;Check out &lt;a href=&quot;https://www.youtube.com/channel/UC927gvqy8i0vw0q5-6-WWBA&quot;&gt;Henri Helvetica&#39;s Youtube channel&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;pre-event-performance-sync-by-mozilla&quot; tabindex=&quot;-1&quot;&gt;Pre-event: Performance.Sync by Mozilla &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/#pre-event-performance-sync-by-mozilla&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;On November 13&lt;/strong&gt;, the day before Performance.now, I also had the pleasure of taking part in &lt;strong&gt;Performance.Sync&lt;/strong&gt;, an event organized by Mozilla. During this session, my good colleague Brian Louis Ramirez presented on the topic of &amp;quot;&lt;strong&gt;Finding the needle in the haystack&lt;/strong&gt;&amp;quot;, which focused on identifying anomalies in &lt;strong&gt;Real User Monitoring (RUM) data&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Brian&#39;s insights into effectively sifting through vast amounts of performance data to pinpoint critical issues were both enlightening and highly practical. Participating in Performance.Sync provided a deeper understanding of advanced data analysis techniques and reinforced the importance of meticulous monitoring in optimizing web performance.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/7oWOBJjikH-648.webp 648w, https://andreaverlicchi.eu/img/7oWOBJjikH-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/7oWOBJjikH-648.jpeg 648w, https://andreaverlicchi.eu/img/7oWOBJjikH-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Brian Louis Ramirez on stage at Performance.sync 2024&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/7oWOBJjikH-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Madames et messieurs, &lt;a href=&quot;https://screenspan.net/&quot;&gt;Brian Louis Ramirez&lt;/a&gt; on stage&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;captured-insights-and-follow-ups&quot; tabindex=&quot;-1&quot;&gt;Captured insights and follow-ups &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/#captured-insights-and-follow-ups&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Throughout the conference, I took some notes that I will carefully review at a second time, as some of them inspired actions on my side.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SpeedCurve wrote a &lt;a href=&quot;https://www.speedcurve.com/web-performance-guide/&quot;&gt;comprehensive web performance guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Good idea to correlate conversion rate and INP&lt;/li&gt;
&lt;li&gt;Only alert on the KPI changes, not when enablers changed&lt;/li&gt;
&lt;li&gt;Bucket type of regressions in moderate, acceptable and critical, based on the % of regression&lt;/li&gt;
&lt;li&gt;When a regression happened, triage who, wht, when, where and why it happened&lt;/li&gt;
&lt;li&gt;~Lazy loaded images can be decoded asynchronously, but eagerly loaded images should not.~ Contested, see &lt;a href=&quot;https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/&quot;&gt;what &lt;code&gt;decode=async&lt;/code&gt; actually does&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The new annotations functionality on Chrome Dev Tools will be very useful to me and other professionals&lt;/li&gt;
&lt;li&gt;We can use &lt;a href=&quot;https://crbug.com/new&quot;&gt;crbug.com/new&lt;/a&gt; to report bugs to the Chromium project and eventually request new features&lt;/li&gt;
&lt;li&gt;Chrome developer is moving the insights from the Performance Insights panel to the Performance panel -- there is one for CSS performance too, if you trace with the &amp;quot;Selector stats (slow)&amp;quot; option active&lt;/li&gt;
&lt;li&gt;Variable fonts are lighter only if you use 2 or more variations of the font, otherwise just load the single variation (e.g. the bold version for titles)&lt;/li&gt;
&lt;li&gt;The CSS overview tab in developer tools gives you the idea of how many instances of the page are using which fonts&lt;/li&gt;
&lt;li&gt;There&#39;s a new working group for incremental font transfer, to download only the portion of the font users currently need&lt;/li&gt;
&lt;li&gt;&lt;code&gt;size-adjust&lt;/code&gt; (at box size) and &lt;code&gt;font-size-adjust&lt;/code&gt; (at font level) are useful to try and render the fallback font like the web font. I noted there is a css-size-adjust-tester tool, which I can&#39;t find at the moment, whereas I found &lt;a href=&quot;https://screenspan.net/fallback/&quot;&gt;Brian Louis Ramirez&#39;s fallback font generator&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Google Publisher Tag (GPT) has a &lt;a href=&quot;https://developers.google.com/publisher-tag/reference#googletag.config.PageSettingsConfig.threadYield&quot;&gt;feature to yield to the main thread&lt;/a&gt; to optimize INP&lt;/li&gt;
&lt;li&gt;When there are gaps in commit events in dev tools, look in other tracks or load the trace in Perfetto to find out why&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These notes have been instrumental in formulating follow-up actions and integrating new techniques into my workflow, and also for my pet projects. Sharing these insights will undoubtedly benefit others who are passionate about advancing their web performance skills.&lt;/p&gt;
&lt;h2 id=&quot;reflecting-on-the-experience&quot; tabindex=&quot;-1&quot;&gt;Reflecting on the Experience &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/performance-now-2024-experience-europe-web-performance-conference/#reflecting-on-the-experience&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;img alt=&quot;Front rows attendees of performance.now()&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/pWsca6bveI-648.webp&quot; width=&quot;1296&quot; height=&quot;863&quot; srcset=&quot;https://andreaverlicchi.eu/img/pWsca6bveI-648.webp 648w, https://andreaverlicchi.eu/img/pWsca6bveI-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;
	&lt;figcaption&gt;I like to be in the front rows to visually engage with the speakers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Attending Performance.now was a rewarding experience that reinforced my commitment to excellence in web performance. The blend of &lt;strong&gt;high-level content, expert speakers, and a vibrant community&lt;/strong&gt; makes it an unmissable event for anyone in this niche. I look forward to applying the knowledge gained and contributing further to the ongoing dialogue in our field.&lt;/p&gt;
&lt;p&gt;If you’re passionate about web performance and looking to elevate your skills, I highly recommend attending Performance.now. It’s not just a conference; it’s a gathering of the brightest minds dedicated to pushing the boundaries of what’s possible on the web.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Feel free to reach out if you have any questions about the conference or web performance in general!&lt;/em&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use Google Meet with two screens: separating shared content and attendees&#39; faces</title>
		<link href="https://andreaverlicchi.eu/en/blog/google-meet-two-screens-separate-content-faces/"/>
		<updated>2024-11-06T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/google-meet-two-screens-separate-content-faces/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/JCP9CiWzL1-509.webp 509w, https://andreaverlicchi.eu/img/JCP9CiWzL1-1018.webp 1018w&quot; sizes=&quot;509px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/JCP9CiWzL1-509.png 509w, https://andreaverlicchi.eu/img/JCP9CiWzL1-1018.png 1018w&quot; sizes=&quot;509px&quot;&gt;&lt;img alt=&quot;Ready to join? Andrea Verlicchi and Andrea Verlicchi are in this call. Switch here; Other ways to join ⬇&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/JCP9CiWzL1-509.png&quot; width=&quot;1018&quot; height=&quot;569&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The welcome screen of Google Meet.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In Google Meet, if you&#39;re working with two screens, you might want to keep the shared content on one screen while keeping the faces of attendees on another. This setup allows for better engagement in the meeting by making it easier to focus on the faces of attendees, chat, and other meeting interactions, while still keeping an eye on the presentation or shared content. Here’s how you can do it with Google Meet&#39;s &lt;em&gt;Companion mode&lt;/em&gt; and a few manual steps.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;👀 &lt;strong&gt;The wait is over&lt;/strong&gt;!!! This is not required from March 2026 anymore, because Google &lt;a href=&quot;https://releasebot.io/updates/google/google-meet#:~:text=Move%20shared%20content%20in%20Google%20Meet%20to%20a%20separate%20window%20with%20the%20%E2%80%9COpen%20in%20new%20window%E2%80%9D%20option&quot;&gt;released&lt;/a&gt; the feature to bring the shared content to a new window! 🥳
I&#39;m leaving the article here because it&#39;s a nice example of how to use &lt;em&gt;Companion mode&lt;/em&gt; and it might be useful for some people.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;step-by-step-guide-to-using-companion-mode&quot; tabindex=&quot;-1&quot;&gt;Step-by-step guide to using Companion mode &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-meet-two-screens-separate-content-faces/#step-by-step-guide-to-using-companion-mode&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using &lt;em&gt;Companion mode&lt;/em&gt; lets you join a Google Meet meeting again from a second tab or window without duplicating audio, allowing you to configure each window individually. Here’s how I set it up:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set layout for attendee faces&lt;/strong&gt;&lt;br&gt;
In your main meeting window, click on the &lt;code&gt;...&lt;/code&gt; (more options) menu, and go to &lt;strong&gt;Change layout&lt;/strong&gt;. Choose &lt;strong&gt;Tiled&lt;/strong&gt; to make sure attendees’ faces are visible in a grid.&lt;/p&gt;
 &lt;figure&gt;
     &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/zx39sVPAf7-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Change layout. Selection is saved for future meetings. Auto; Tiled; Spotlight; Sidebar. Tiles; Maximum tiles to display, depending on window size. Hide tiles without video.&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/zx39sVPAf7-648.png&quot; width=&quot;648&quot; height=&quot;888&quot;&gt;&lt;/picture&gt;
     &lt;figcaption&gt;Google Meet layer to change the layut&lt;/figcaption&gt;
 &lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minimize the presentation in the main window&lt;/strong&gt;&lt;br&gt;
If the presentation is pinned, unpin it by hovering over it and clicking the pin icon. This will make the presentation smaller and attendees’ faces larger, ensuring your main focus in this window remains on the people, not the content.&lt;/p&gt;
 &lt;figure&gt;
     &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/6jdKG95u7c-436.webp 436w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Icons to unpin, mute, remove from the call. The tooltip shows &#39;Unpin&#39;.&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/6jdKG95u7c-436.png&quot; width=&quot;436&quot; height=&quot;270&quot;&gt;&lt;/picture&gt;
     &lt;figcaption&gt;This is the icon to unpin the presented content.&lt;/figcaption&gt;
 &lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Duplicate the Google Meet tab&lt;/strong&gt;&lt;br&gt;
Right-click on your Google Meet tab and select &lt;strong&gt;Duplicate&lt;/strong&gt;. This new tab will be used exclusively for viewing the shared content.&lt;/p&gt;
 &lt;figure&gt;
     &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/bA21waIEKV-341.webp 341w, https://andreaverlicchi.eu/img/bA21waIEKV-682.webp 682w&quot; sizes=&quot;341px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/bA21waIEKV-341.png 341w, https://andreaverlicchi.eu/img/bA21waIEKV-682.png 682w&quot; sizes=&quot;341px&quot;&gt;&lt;img alt=&quot;...&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/bA21waIEKV-341.png&quot; width=&quot;682&quot; height=&quot;676&quot;&gt;&lt;/picture&gt;
     &lt;figcaption&gt;Here&#39;s the dropdown menu to duplicate a Chrome tab&lt;/figcaption&gt;
 &lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enable Companion mode in the duplicated tab&lt;/strong&gt;&lt;br&gt;
In the duplicated tab, choose &lt;strong&gt;Use Companion mode&lt;/strong&gt;. Companion mode will join the meeting again without sound, so you won’t have any distracting audio echo or feedback. This secondary window will serve as your content-only view.&lt;/p&gt;
 &lt;figure&gt;
     &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/wmjELm1U7i-512.webp 512w, https://andreaverlicchi.eu/img/wmjELm1U7i-1024.webp 1024w&quot; sizes=&quot;512px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/wmjELm1U7i-512.png 512w, https://andreaverlicchi.eu/img/wmjELm1U7i-1024.png 1024w&quot; sizes=&quot;512px&quot;&gt;&lt;img alt=&quot;Ready to join? Andrea Verlicchi and Andrea Verlicchi are in this call. Switch here; Present; Use Companion mode; Show fewer options ⬆️&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/wmjELm1U7i-512.png&quot; width=&quot;1024&quot; height=&quot;833&quot;&gt;&lt;/picture&gt;
     &lt;figcaption&gt;Companion mode is right there, highlighted in blue.&lt;/figcaption&gt;
 &lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Move the Companion mode tab to a new window and position it on your main screen&lt;/strong&gt;&lt;br&gt;
Drag the Companion mode tab into a separate window, and move it to your main screen where you want to view the shared content. Now, you’ll have the main meeting with attendees’ faces on one screen and the content in Companion mode on another.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enhance the Companion mode window with my Google Meet true full screen bookmarklet&lt;/strong&gt;
In the &lt;em&gt;Companion mode&lt;/em&gt; window, you can use my &lt;a href=&quot;https://github.com/verlok/google-meet-true-full-screen/&quot;&gt;Google Meet true full screen&lt;/a&gt; bookmarklet to enable a true full-screen mode. This way, the shared content fills the screen without any extra UI elements, making it easier to focus on the presentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bonus step&lt;/strong&gt; If you bring the main Google Meet&#39;s picture-in-picture (PIP) in the main Google Meet window, it&#39;s even possible to bring participants faces in front of someone else&#39;s presented content, like you can do with Zoom.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;why-this-setup-works&quot; tabindex=&quot;-1&quot;&gt;Why this setup works &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-meet-two-screens-separate-content-faces/#why-this-setup-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This setup keeps attendees’ faces, chat, and controls accessible in the main window, while reserving a second screen exclusively for content. It’s a more immersive experience and a workaround for Google Meet’s current UI limitations.&lt;/p&gt;
&lt;h2 id=&quot;final-thoughts&quot; tabindex=&quot;-1&quot;&gt;Final thoughts &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-meet-two-screens-separate-content-faces/#final-thoughts&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yes, it’s a bit of a manual process, but until Google improves its dual-screen functionality, these steps are the most effective way to manage meeting visuals across multiple screens. This setup is especially useful for virtual conferences or meetings with high levels of interaction, as it keeps both the presentation and the people engaging with it fully visible.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Give it a try, and let me know how it works for you! If you have any suggestions to streamline the process, feel free to share them.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>True full-screen mode for Google Meet shared content</title>
		<link href="https://andreaverlicchi.eu/en/blog/true-full-screen-google-meet-bookmarklet/"/>
		<updated>2024-11-05T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/true-full-screen-google-meet-bookmarklet/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Z2bUG-5AUo-648.webp 648w, https://andreaverlicchi.eu/img/Z2bUG-5AUo-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/Z2bUG-5AUo-648.png 648w, https://andreaverlicchi.eu/img/Z2bUG-5AUo-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Google Meet in true full screen, without the top bar and the controls&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/Z2bUG-5AUo-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Google Meet in true full screen, finally!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As someone who spends a lot of time on Google Meet, I’ve often been frustrated by the inability to view shared content in true full-screen mode. There’s a lot to be said for maximizing screen space, especially when diving into complex code or detailed design presentations. But for whatever reason, Meet limits full-screen options, leaving borders and UI elements visible, which can be distracting.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;👀 &lt;strong&gt;The wait is over&lt;/strong&gt;!!! This is not required from March 2026 anymore, because Google &lt;a href=&quot;https://releasebot.io/updates/google/google-meet#:~:text=Move%20shared%20content%20in%20Google%20Meet%20to%20a%20separate%20window%20with%20the%20%E2%80%9COpen%20in%20new%20window%E2%80%9D%20option&quot;&gt;released&lt;/a&gt; the feature to bring the shared content to a new window! 🥳
I&#39;m leaving the article here because it&#39;s a nice example of how to create a bookmarklet and it might be useful for some people.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I got tired of waiting for Google to provide a solution, so I decided to make one myself. I created a bookmarklet that lets you view shared content in true full-screen mode on Google Meet, removing the extraneous elements and maximizing usable screen space.&lt;/p&gt;
&lt;p&gt;Check it out and add it to your browser here:&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://github.com/verlok/google-meet-true-full-screen/tree/main&quot;&gt;Google Meet True Full-Screen Bookmarklet on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There you will find the procedure to add the bookmarklet to your browser, and once added, you can activate true full-screen mode with a single click.&lt;/p&gt;
&lt;p&gt;This simple script aims to improve your meeting experience by keeping the focus on the content that matters.
Let me know if you find it useful, or if there are any tweaks or features you&#39;d like to see added.&lt;/p&gt;
&lt;p&gt;Happy full-screening!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>The remote work debate: my view on finding balance</title>
		<link href="https://andreaverlicchi.eu/en/blog/remote-work-debate-perfect-balance/"/>
		<updated>2024-10-20T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/remote-work-debate-perfect-balance/</id>
		<content type="html">&lt;img alt=&quot;An illustration of a person working remotely in a comfortable home office, surrounded by plants and personal items, with a laptop open.&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/6DbJ6HsspB-648.webp&quot; width=&quot;1296&quot; height=&quot;740&quot; srcset=&quot;https://andreaverlicchi.eu/img/6DbJ6HsspB-648.webp 648w, https://andreaverlicchi.eu/img/6DbJ6HsspB-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;
&lt;p&gt;After nearly three years of working fully remotely, six years of &amp;quot;smart-working&amp;quot; (two remotely, three in the office), and more than 15 years working in offices, I’ve gained a lot of perspective on the remote work debate. While I support many of the benefits of working from home, I also recognize the drawbacks, and I think there’s a middle ground that works best.&lt;/p&gt;
&lt;h2 id=&quot;the-benefits-of-remote-work&quot; tabindex=&quot;-1&quot;&gt;The Benefits of Remote Work &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/remote-work-debate-perfect-balance/#the-benefits-of-remote-work&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Remote work offers clear advantages. First and foremost, it’s effective—allowing for increased productivity, fewer distractions, and better focus when you have the right setup, whether an isolated space at home or a desk in a coworking space. For employees, there’s also the benefit of flexibility. You have the freedom to arrange your schedule more easily around personal commitments and preferences. Financially, it’s a win, too—no commuting costs, no need to buy lunch out every day.&lt;/p&gt;
&lt;h2 id=&quot;the-human-element-what-we-miss&quot; tabindex=&quot;-1&quot;&gt;The Human Element: What We Miss &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/remote-work-debate-perfect-balance/#the-human-element-what-we-miss&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;But remote work isn’t all upside. One of the biggest downsides is the isolation it can bring. It’s easy to compensate for this by staying active, going to the gym, or catching up with friends. Yet, there’s no replacement for the spontaneous exchanges that happen with colleagues when you share a workspace. These informal interactions can spark new ideas and help foster team spirit.&lt;/p&gt;
&lt;p&gt;A personal example: just last Thursday, I was in Hamburg for an event at the company office. During a break, I had a casual conversation with one of my colleagues, a working student, and discovered she was preparing her thesis on a topic directly related to a project I’m working on. That valuable connection wouldn’t have happened without the in-person interaction.&lt;/p&gt;
&lt;p&gt;There is something unique about the bonds formed through working side-by-side for long hours. In many cases, you spend more time with your colleagues than with your family when working full-time in an office. This is especially true for small teams, where these connections can be strong enough to last years—bonds* that can remain strong even as you move on to new jobs.&lt;/p&gt;
&lt;p&gt;*Marco, Giorgio, Alberto, David, and Tommy, if you&#39;re reading this, I&#39;m thinking of you.&lt;/p&gt;
&lt;h2 id=&quot;finding-balance-a-mixed-approach&quot; tabindex=&quot;-1&quot;&gt;Finding Balance: A Mixed Approach &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/remote-work-debate-perfect-balance/#finding-balance-a-mixed-approach&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In my experience, the ideal setup is a hybrid approach. Work from home most of the time, but with the flexibility to go to the office when needed—for example, for brainstorming sessions, collaborative projects, or important meetings.&lt;/p&gt;
&lt;p&gt;I also believe companies should organize regular in-person events—whether workshops or team-building activities—at least four times a year to maintain a sense of connection and shared purpose.&lt;/p&gt;
&lt;p&gt;This model strikes the right balance between autonomy and collaboration, ensuring that while we enjoy the flexibility of remote work, we don’t lose the valuable interpersonal connections that fuel innovation and camaraderie in a team.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk: How I made the web more responsive — real-world case studies of INP optimizations</title>
		<link href="https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/"/>
		<updated>2024-09-17T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/</id>
		<content type="html">&lt;p&gt;In May 2024, I started speaking at conferences and meetups about improving web responsiveness. My talks focus on debugging and preventing slow interactions, drawing from my experience auditing Interaction to Next Paint (INP) on dozens of clients&#39; websites.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/FDb4aKLIVsI?si=WNNwr8DcyRAplbKB&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;After providing an initial explanation of INP, I demonstrate how to debug slow interactions using both Chrome DevTools and Real User Monitoring (RUM) data. I then illustrate three common mistakes I encountered while auditing INP on dozens of websites and explain how to avoid them to ensure snappy user interactions and keep your INP below 200 milliseconds.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.google.com/presentation/d/1kSHr9mEN2Q4Nyis8uWvxoA3_pqOIywr3TXCLeO_-4qA/edit&quot;&gt;📽️ Slides&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;we-love-speed-nantes-17-september-2024&quot; tabindex=&quot;-1&quot;&gt;We Love Speed, Nantes 🇫🇷 - &lt;time datetime=&quot;2024-07-17&quot;&gt;17 September 2024&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/#we-love-speed-nantes-17-september-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/rpboOrNxxf-648.webp 648w, https://andreaverlicchi.eu/img/rpboOrNxxf-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/rpboOrNxxf-648.jpeg 648w, https://andreaverlicchi.eu/img/rpboOrNxxf-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi speaking at We Love Speed, Nantes, 2024&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/rpboOrNxxf-648.jpeg&quot; width=&quot;1296&quot; height=&quot;863&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;On stage at We Love Speed 2024, Nantes&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The title of the talk was &amp;quot;How I made the web more responsive - real-world case studies of INP optimizations&amp;quot;, in French &amp;quot;Comment j’ai rendu le web plus réactif — études de cas concrets d’optimisations d’INP&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=FDb4aKLIVsI&quot;&gt;📺 Video&lt;/a&gt; - &lt;a href=&quot;https://www.welovespeed.com/en/2024/talks/how-i-made-the-web-more-responsive/&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;we-make-future-bologna-14-june-2024&quot; tabindex=&quot;-1&quot;&gt;We Make Future, Bologna 🇮🇹 - &lt;time datetime=&quot;2024-06-14&quot;&gt;14 June 2024&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/#we-make-future-bologna-14-june-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/YKQw5uBAIG-648.webp 648w, https://andreaverlicchi.eu/img/YKQw5uBAIG-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/YKQw5uBAIG-648.jpeg 648w, https://andreaverlicchi.eu/img/YKQw5uBAIG-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi speaking on the Coding Front-end stage of We Make Future Bologna. The slide&amp;nbsp;shows the browser visiting a website, the developer tools of the browser open on the Performance panel, and 7 steps described to the right. 1: Emulate device, 2: Performance options, 3: Slowdown the CPU, 4: Start recording, 5: Click around, 6: Type around, 7: Stop recording&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/YKQw5uBAIG-648.jpeg&quot; width=&quot;1296&quot; height=&quot;835&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;On the Coding Front-end stage of WMF 2024: how to debug INP, the hard way.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The title of the talk, in Italian, was &amp;quot;Migliorare la reattività del web — Guida pratica per debug e prevenzione delle interazioni lente&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=OQ8djUCFHTk&quot;&gt;📺 Video&lt;/a&gt; - &lt;a href=&quot;https://www.wemakefuture.it/s/65e6dde7acc90ad8ebbfff17/#sala=CodingFrontend%7Ccodingfrontend&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;google-developer-group-madrid-4-june-2024&quot; tabindex=&quot;-1&quot;&gt;Google Developer Group, Madrid 🇪🇸 - &lt;time datetime=&quot;2024-06-04&quot;&gt;4 June 2024&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/#google-developer-group-madrid-4-june-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/hthSTqoJ5y-648.webp 648w, https://andreaverlicchi.eu/img/hthSTqoJ5y-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/hthSTqoJ5y-648.jpeg 648w, https://andreaverlicchi.eu/img/hthSTqoJ5y-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi speaking at GDG Madrid (c/o Celonis), a few people in the front rows, the slide showing the input delay part of the INP measurement in the browser&#39;s main thread&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/hthSTqoJ5y-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;Presenting at GDG Madrid, showing the first of the INP subparts: Input Delay.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The title of the talk in Spanish was: &amp;quot;Hagamos que la web sea mas responsive en 2024&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-madrid-presents-hagamos-que-la-web-sea-mas-responsive-en-2024/&quot;&gt;GDG Madrid event&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;bologna-js-bologna-22-may-2024&quot; tabindex=&quot;-1&quot;&gt;Bologna JS, Bologna 🇮🇹 - &lt;time datetime=&quot;2024-05-22&quot;&gt;22 May 2024&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/#bologna-js-bologna-22-may-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/HKEEow_XEy-648.webp 648w, https://andreaverlicchi.eu/img/HKEEow_XEy-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/HKEEow_XEy-648.jpeg 648w, https://andreaverlicchi.eu/img/HKEEow_XEy-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi speaking at Bologna JS, a few people in the front rows, the slide shows the word &#39;Conclusion&#39;&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/HKEEow_XEy-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;At the Bologna JS Meetup. This is the only picture I&#39;ve got 🤷‍♂️. It&#39;s pretty final.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://youtube.com/live/ibZ1y3LxKKg?feature=share&quot;&gt;📺 Video&lt;/a&gt; · &lt;a href=&quot;https://www.meetup.com/bologna-js-meetup/events/300919249/&quot;&gt;Meetup event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;google-developer-group-bologna-01-october-2024&quot; tabindex=&quot;-1&quot;&gt;Google Developer Group, Bologna 🇮🇹 - &lt;time datetime=&quot;2024-10-01&quot;&gt;01 October 2024&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/#google-developer-group-bologna-01-october-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/-QghAZtl_M-648.webp 648w, https://andreaverlicchi.eu/img/-QghAZtl_M-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/-QghAZtl_M-648.jpeg 648w, https://andreaverlicchi.eu/img/-QghAZtl_M-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi on stage at Phygital Hub (Gellify)&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/-QghAZtl_M-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me speaking on &quot;stage&quot; at Phygital Hub (Gellify)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Title: &amp;quot;Come ho reso il web più reattivo - Guida pratica di come trovare ed evitare le interazioni lente.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-bologna-presents-come-ho-reso-il-web-piu-reattivo/&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;devromagna-faenza-26-september-2024&quot; tabindex=&quot;-1&quot;&gt;DevRomagna, Faenza 🇮🇹 - &lt;time datetime=&quot;2024-09-26&quot;&gt;26 September 2024&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-i-made-the-web-more-responsive--debug-avoid-slow-interaction-next-paint-inp/#devromagna-faenza-26-september-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/n-9_MSNZXX-648.webp 648w, https://andreaverlicchi.eu/img/n-9_MSNZXX-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/n-9_MSNZXX-648.jpeg 648w, https://andreaverlicchi.eu/img/n-9_MSNZXX-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi on stage at DevRomagna, Faenza&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/n-9_MSNZXX-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me speaking on &quot;stage&quot; on stage at DevRomagna, Faenza&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Title: &amp;quot;Come ho reso il web più reattivo - Guida pratica di come trovare ed evitare le interazioni lente.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://meetu.ps/e/NtXTj/zKMHn/i&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>My Favorite Features of iOS 18: A Game-Changer for Multilingual Users and More</title>
		<link href="https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/"/>
		<updated>2024-09-13T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/</id>
		<content type="html">&lt;p&gt;With each new iOS release, I always look forward to exploring the latest features Apple has to offer. iOS 18 has introduced several changes, some small and subtle, others more profound, that have significantly enhanced my user experience. Here are my favorite new features in iOS 18 and why I think they’re a game-changer.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/x4O6m0ssMy-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The iOS 18 keyboard switcher showing different keyboards sets: Italian and English, Portuguese and French, Spanish and German&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/x4O6m0ssMy-648.png&quot; width=&quot;648&quot; height=&quot;535&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The iOS 18 keyboard switcher showing different keyboards sets: Italian and English, Portuguese and French, Spanish and German&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;1-bilingual-keyboards-a-seamless-multilingual-experience&quot; tabindex=&quot;-1&quot;&gt;1. Bilingual Keyboards: A Seamless Multilingual Experience &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/#1-bilingual-keyboards-a-seamless-multilingual-experience&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of my absolute favorite updates is the new keyboard functionality that allows me to type in multiple languages without changing the input language manually. It&#39;s much better this way! Essentially, iOS 18 offers bilingual keyboards, so I can write messages like:&lt;/p&gt;
&lt;p&gt;“Guten Tag! Buenos días! Alles gut? Sí, muy bien! Bom dia! Bonjour! Tudo beleza? Oui, ça va très bien!”&lt;/p&gt;
&lt;p&gt;And the best part? I don’t need to switch the keyboard layout every time I change languages. This is a massive improvement, especially for people who frequently switch between languages like I do. It’s a small feature that adds so much fluidity to multilingual conversations.&lt;/p&gt;
&lt;h2 id=&quot;2-enhanced-dictation-faster-and-smarter&quot; tabindex=&quot;-1&quot;&gt;2. Enhanced Dictation: Faster and Smarter &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/#2-enhanced-dictation-faster-and-smarter&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;“Hi, I’m trying out the new dictation feature on iPhone 18. It seems to have automatic punctuation also in Italian now. What time did you say we’re leaving today?”&lt;/p&gt;
&lt;p&gt;Yes, automatic punctuation is here! It’s a simple yet highly useful upgrade, and it saves me a ton of editing time. But here&#39;s a tip: to dictate in English, make sure you have English dictation enabled, as the default Italian setting will only pick up basic English words. It&#39;s a small hurdle, but the overall improvement in dictation is undeniable.&lt;/p&gt;
&lt;h2 id=&quot;3-improved-home-screen-control-center-and-backgrounds&quot; tabindex=&quot;-1&quot;&gt;3. Improved Home Screen, Control Center, and Backgrounds &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/#3-improved-home-screen-control-center-and-backgrounds&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;iOS 18 also made some great strides in customization. Now, managing your home screen and control center is much more flexible. You can freely position app icons on the home screen without the rigid grid system of old. Plus, the background management has become more intuitive, making it easier to switch and organize wallpapers.&lt;/p&gt;
&lt;h2 id=&quot;4-upgrades-to-notes-reminders-and-calendar&quot; tabindex=&quot;-1&quot;&gt;4. Upgrades to Notes, Reminders, and Calendar &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/#4-upgrades-to-notes-reminders-and-calendar&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For those of us who use the built-in productivity apps daily, iOS 18 has delivered some helpful tweaks. In Notes, you now have collapsible sections, while in Reminders, the smart lists feature makes managing tasks a breeze. The Calendar app has introduced a new month view that makes scheduling even more efficient. These are small, incremental updates, but they’re invaluable for staying organized.&lt;/p&gt;
&lt;h2 id=&quot;5-internet-pages-read-aloud-the-real-game-changer&quot; tabindex=&quot;-1&quot;&gt;5. Internet Pages Read Aloud (The Real Game-Changer) &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/#5-internet-pages-read-aloud-the-real-game-changer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This might just be the killer feature of iOS 18. You can now have entire web pages or articles read aloud to you, even with the screen turned off. Siri now gives you controls for play, pause, and reading speed, making it incredibly convenient. Before, I relied on Microsoft Edge for this, but now Siri can handle it, at least for Italian content (as I use Siri in Italian). For English articles, I’ll probably stick with Edge for now, but this feature is a fantastic addition for hands-free browsing.&lt;/p&gt;
&lt;h2 id=&quot;6-a-new-password-app-for-secure-management&quot; tabindex=&quot;-1&quot;&gt;6. A New Password App for Secure Management &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/#6-a-new-password-app-for-secure-management&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;iOS 18 also introduces a new password app, which lets you manage passwords, passkeys, and two-factor authentication codes all in one place. It&#39;s a handy tool for anyone who doesn’t already use a third-party password manager. Personally, I will still use KeePass and KeePassX because I need to share some passwords with non-Apple devices, and I don&#39;t want to get locked out of everything if I lose access to my Apple ID by any chance.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/favourite-features-ios-18/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are my favourite features that have made iOS 18 such a joy to use. With smoother multilingual typing, smarter dictation, and enhanced customization, Apple has really upped the game. And let’s not forget the convenience of having Siri read web pages aloud or the new built-in password manager. iOS 18 feels like a solid evolution that improves daily tasks, making life just that little bit easier.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Mitigating CLS Caused by Promotional Banners: A Practical Solution</title>
		<link href="https://andreaverlicchi.eu/en/blog/mitigating-cls-caused-by-promotional-banners/"/>
		<updated>2024-08-26T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/mitigating-cls-caused-by-promotional-banners/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/a9Yij_7xm3-648.webp 648w, https://andreaverlicchi.eu/img/a9Yij_7xm3-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/a9Yij_7xm3-648.png 648w, https://andreaverlicchi.eu/img/a9Yij_7xm3-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The home page of a website with a top promotional banner pushing down the content below it&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/a9Yij_7xm3-648.png&quot; width=&quot;1296&quot; height=&quot;733&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;A website with a top promotional banner pushing down the content below it&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt; is a core web vital metric that measures visual stability. It occurs when content on a web page moves unexpectedly, often causing user frustration.&lt;/p&gt;
&lt;p&gt;One common cause of CLS is a &lt;strong&gt;promotional banner being injected at the top of the page&lt;/strong&gt; after the main content has already loaded. This would push down other elements on the page, leading to a poor user experience. Unluckily, this is a very common problem occurring in the websites I&#39;ve been working on or consulting for.&lt;/p&gt;
&lt;p&gt;In this blog post, we&#39;ll explore a method to mitigate CLS by reserving space for a promotional banner using session storage. This approach ensures that the banner doesn&#39;t cause layout shifts on subsequent page loads, leading to a more stable and user-friendly experience.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot; tabindex=&quot;-1&quot;&gt;The Problem &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/mitigating-cls-caused-by-promotional-banners/#the-problem&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the scenario described before, the logic to determine whether to show this banner is executed via JavaScript, often after the page&#39;s content is already visible. This results in a layout shift, where all content below the banner is suddenly pushed down, causing a jarring user experience.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot; tabindex=&quot;-1&quot;&gt;The Solution &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/mitigating-cls-caused-by-promotional-banners/#the-solution&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To solve this problem, we can use &lt;code&gt;sessionStorage&lt;/code&gt; to remember the banner&#39;s content and state during the user&#39;s session. By doing this, we can inject the banner&#39;s content immediately when the page loads, preventing any layout shift. If the user has closed the banner, we ensure it remains hidden for the rest of the session, so it isn&#39;t shown on the next page load.&lt;/p&gt;
&lt;p&gt;Here&#39;s how we can implement this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check if the banner was previously closed&lt;/strong&gt;:&lt;br&gt;We first check if the user has closed the banner in their current session. If they have, we don’t display it again.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inject the banner&#39;s content&lt;/strong&gt;:&lt;br&gt;If the banner was not closed and there is saved content in session storage, we inject it into the page as soon as possible. This prevents the layout from shifting when the banner is eventually loaded.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Save the banner&#39;s content&lt;/strong&gt;:&lt;br&gt;When the promotional content is fetched for the first time, we save it to session storage. This allows us to reuse it on subsequent page loads without causing a layout shift.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Handle banner closure&lt;/strong&gt;:&lt;br&gt;If the user closes the banner, we set a flag in session storage to ensure it doesn’t reappear during the same session.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;implementation&quot; tabindex=&quot;-1&quot;&gt;Implementation &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/mitigating-cls-caused-by-promotional-banners/#implementation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Find here the &lt;a href=&quot;https://github.com/verlok/cls-issue-promotional-banner-mitigation/&quot;&gt;GitHub repository&lt;/a&gt; with the code and the &lt;a href=&quot;https://verlok.github.io/cls-issue-promotional-banner-mitigation/&quot;&gt;live demo&lt;/a&gt; on GitHub Pages.&lt;/p&gt;
&lt;p&gt;For your convenience, here&#39;s the code copy-pasted from the demo page.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bannerContainerId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;promo-banner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ID of the banner container&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bannerSessionKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;promoBannerContent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bannerClosedKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;promoBannerClosed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Function to check if the banner was closed by the user&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;isBannerClosed&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    sessionStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerClosedKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Check if the banner was previously closed by the user. If yes, do nothing.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isBannerClosed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Function to inject the banner into the page&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;injectBanner&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;bannerContent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bannerContainer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerContainerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerContainer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      bannerContainer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; bannerContent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      bannerContainer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;block&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 👀 Check if banner content exists in sessionStorage, and eventually inject it&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; savedBannerContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sessionStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerSessionKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;savedBannerContent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;injectBanner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;savedBannerContent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Function to simulate the fetch of the promotion.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;loadPromotion&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bannerContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;div&gt;Your promotion content here&amp;lt;/div&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Inject the banner content&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;injectBanner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerContent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// 👀 Save the banner content to sessionStorage for the next time&lt;/span&gt;
      sessionStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerSessionKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bannerContent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Function to handle banner close action&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;closeBanner&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    sessionStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerClosedKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bannerContainer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerContainerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bannerContainer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      bannerContainer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Simulate fetching the promotion&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;loadPromotion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Example event listener for closing the banner&lt;/span&gt;
  document
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;close-banner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; closeBanner&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;how-it-works&quot; tabindex=&quot;-1&quot;&gt;How It Works &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/mitigating-cls-caused-by-promotional-banners/#how-it-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Session Storage&lt;/strong&gt;: This is used to store the promotional content and the closed state of the banner. The data persists across page loads within the same session, ensuring the user experience is consistent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Immediate Injection&lt;/strong&gt;: By immediately injecting saved content into the page, we prevent any layout shift that would occur if the banner were loaded after the page was fully rendered.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User Control&lt;/strong&gt;: If the user closes the banner, it won&#39;t reappear during the same session, ensuring the user’s preference is respected.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/mitigating-cls-caused-by-promotional-banners/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By leveraging session storage to manage the display of promotional banners, you can significantly reduce CLS on your website. This approach not only enhances the user experience but also improves your site’s performance metrics, contributing to better SEO and higher engagement rates.&lt;/p&gt;
&lt;p&gt;This method is particularly useful for websites with dynamic content, where the decision to show certain elements is made after the page has loaded. By planning for these elements ahead of time, you can create a smoother, more stable experience for your users.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This approach is a simple yet effective way to address one of the common causes of CLS, and can be implemented with minimal changes to your existing codebase.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Impressions on the Google I/O Connect 2024 + GDE Forum in Berlin</title>
		<link href="https://andreaverlicchi.eu/en/blog/google-io-connect-2024-berlin/"/>
		<updated>2024-08-01T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/google-io-connect-2024-berlin/</id>
		<content type="html">&lt;p&gt;Google I/O is the annual Google event for developers which takes place in their offices in California, &lt;abbr title=&quot;United States of America&quot;&gt;USA.
Google I/O Connect is a series of hands-on, in-person developer events held around the world, to help developers apply the technology and announcements from Google I/O through live sessions, demos, codelabs, office hours, and more.
As well as last year, I was invited to Google I/O Connect &lt;abbr title=&quot;Europe, Middle-East and Africa&quot;&gt;EMEA&lt;/abbr&gt; 2024.
And as a Google Developer Expert (GDE), on the next day I also took part to the GDE Forum in Berlin Google offices.
Keep reading to find out what these events were like and what I liked most of them.&lt;/abbr&gt;&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/6c6K15oE1u-648.webp 648w, https://andreaverlicchi.eu/img/6c6K15oE1u-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/6c6K15oE1u-648.jpeg 648w, https://andreaverlicchi.eu/img/6c6K15oE1u-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi leaning on the slash between the I and the O of the Google I/O Connect logo covered in flowers&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/6c6K15oE1u-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me, comfortably leaning on the slash between the I and the O of the Google I/O Connect logo&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-community-dinner&quot; tabindex=&quot;-1&quot;&gt;The community dinner &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-io-connect-2024-berlin/#the-community-dinner&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On the day before the conference, Google holds a dinner event to mix Google Developer Experts (GDE), Women Tech Makers (WTM), Google Developer Groups (GDG) organizers and people who work at Google (aka Googlers) in the GDE program or as developer relationship (devrel).&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/-N-1rdItpM-648.webp 648w, https://andreaverlicchi.eu/img/-N-1rdItpM-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/-N-1rdItpM-648.jpeg 648w, https://andreaverlicchi.eu/img/-N-1rdItpM-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Different groups of people chatting at the community dinner&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/-N-1rdItpM-648.jpeg&quot; width=&quot;1296&quot; height=&quot;984&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;People chatting at the community dinner&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The aim of the event is to socialize, getting to know more people, networking with the ones you already know, strengthen the personal and professional connection, all of that while eating, drinking and discussing of the latest news about the industry.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Wmyyo4K_PM-648.webp 648w, https://andreaverlicchi.eu/img/Wmyyo4K_PM-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/Wmyyo4K_PM-648.jpeg 648w, https://andreaverlicchi.eu/img/Wmyyo4K_PM-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Google Developer Experts on web performance with the web performance developer advocate Barry Pollard&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Wmyyo4K_PM-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;From the left: Ines Akrap, me, Barry Pollard, Fabian Krumbholz, Medhat Dawoud, Jad Joubran, Erwin Hofman, Joan León, Anna Migas.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I enjoyed the event, spent most of the time chatting with other web performance GDEs and googlers - particularly Barry Pollard (web performance developer advocate for Google Chrome) and Jocelyn -, hung out briefly with the Italian GDG community, ended up singing karaoke with my former workmate Ines, and when the event was over I took a long walk to the hotel with Paolo Galeone, a Machine Learning GDE who flew in with me from Bologna.&lt;/p&gt;
&lt;h2 id=&quot;main-google-i-o-event&quot; tabindex=&quot;-1&quot;&gt;Main Google I/O event &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-io-connect-2024-berlin/#main-google-i-o-event&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The main stage was taken from Googlers for the initial keynote, and there was I, sitting in the front row as I like (mostly because I&#39;m short-sighted).&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/VRn5JHSgrp-648.webp 648w, https://andreaverlicchi.eu/img/VRn5JHSgrp-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/VRn5JHSgrp-648.jpeg 648w, https://andreaverlicchi.eu/img/VRn5JHSgrp-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Me, Aleksander Denisov and Rowdy Rabouw sitting in the front row&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/VRn5JHSgrp-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me, Aleksander Denisov and Rowdy Rabouw sitting in the front row&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;However Google I/O is NOT a replica of Google I/O, so Google require you to watch the videos of what was presented at the main I/O event beforehand. Then, at Google I/O connect, you have the chance to ask questions to Googlers, who sit on stage, about the topics presented.&lt;/p&gt;
&lt;p&gt;The event is divided in many stages (Web, AI, Android, Flutter, etc.) so you can attend the ones you&#39;re most interested in. For example, I spent most of the time in the Web stage, at events about the new web UI features, about the latest Angular release, etc.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/uCGsIUMD22-648.webp 648w, https://andreaverlicchi.eu/img/uCGsIUMD22-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/uCGsIUMD22-648.jpeg 648w, https://andreaverlicchi.eu/img/uCGsIUMD22-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Una Kravetz, Bramus, and Barry Pollard from Google, on stage at The Latest in Web UI&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/uCGsIUMD22-648.jpeg&quot; width=&quot;1296&quot; height=&quot;875&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Una Kravetz, Bramus, and Barry Pollard from Google, on stage at The Latest in Web UI&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;There, I also had the luck to meet Nishu Goel, who did a very nice job in exploring Interaction to Next Paint (INP) last year and gave a talk about it at the Performance Now confernce, so she&#39;s a rockstar to me but I never had the chance to meet her in person. So, more networking.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/FpNsGKx_5s-648.webp 648w, https://andreaverlicchi.eu/img/FpNsGKx_5s-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/FpNsGKx_5s-648.jpeg 648w, https://andreaverlicchi.eu/img/FpNsGKx_5s-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A selfie with me, Jeremy Wagner, Fabian Krumbholz, and Nishu Goel in front of the main street of the Google I/O Connect venue&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/FpNsGKx_5s-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;More networking! From the left: me, Jeremy Wagner, Fabian Krumbholz, and Nishu Goel&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This event was open to all the people invited to the community dinner, plus other people who occasionally joined the event by purchasing a ticket.&lt;/p&gt;
&lt;h2 id=&quot;gde-forum&quot; tabindex=&quot;-1&quot;&gt;GDE Forum &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/google-io-connect-2024-berlin/#gde-forum&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The GDE forum was restricted to Google Developer Experts, and had a limited number of seats (150), so only the ones who registered first were able to access it. I was amongst the lucky ones, but I know many who just were in the waiting list and still didn&#39;t make it.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Phy-CA_SBG-648.webp 648w, https://andreaverlicchi.eu/img/Phy-CA_SBG-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/Phy-CA_SBG-648.jpeg 648w, https://andreaverlicchi.eu/img/Phy-CA_SBG-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Me at the entrance of the GDE forum Belin at Google Offices, with bears on top of the logo&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Phy-CA_SBG-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me at the entrance of the GDE forum Belin at Google Offices&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Here I had the chance to see a preview and give feedback on some of the feature the Google Chrome Developer Tools team are working on, which I can&#39;t reveal as they&#39;re covered by &lt;abbr title=&quot;Non-discosure Agreement&quot;&gt;NDA&lt;/abbr&gt;, and take part to a live INP debugging session with Barry Pollard (the most appreciated event as it resulted from the final poll).&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/cW0SWSlvHB-648.webp 648w, https://andreaverlicchi.eu/img/cW0SWSlvHB-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/cW0SWSlvHB-648.jpeg 648w, https://andreaverlicchi.eu/img/cW0SWSlvHB-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;People sitting in front of the screen at the initial keynote for the GDE forum&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/cW0SWSlvHB-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Initial keynote for the GDE forum&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And of course, more networking!&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/mSybDR-N6Q-648.webp 648w, https://andreaverlicchi.eu/img/mSybDR-N6Q-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/mSybDR-N6Q-648.jpeg 648w, https://andreaverlicchi.eu/img/mSybDR-N6Q-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Nishu Goel, Barry Pollard and me&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/mSybDR-N6Q-648.jpeg&quot; width=&quot;1296&quot; height=&quot;921&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;More networking with Nishu Goel and Barry Pollard&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To conclude, it was a very lovely and useful event to take part to, and I hope I will have the chance to take part to it next year.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Jake Archibald&#39;s talk &quot;In the loop&quot;, transposed</title>
		<link href="https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/"/>
		<updated>2024-02-17T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://jakearchibald.com/&quot;&gt;Jake Archibald&lt;/a&gt;&#39;s talk &amp;quot;In the loop&amp;quot; (JS Conf Asia) is still one of the best sources of information on how browsers process tasks and are able to respond to user input. As I didn&#39;t find anything as comprehensible as that in text format, I transposed his talk into this blog post. Find the video at the end.&lt;/p&gt;
&lt;h2 id=&quot;main-thread-and-deterministic-order&quot; tabindex=&quot;-1&quot;&gt;Main thread and deterministic order &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#main-thread-and-deterministic-order&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Take the following code snippets:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Would you say they behave in the same way for the user experience? Will users see a blink because of the element was added to the DOM, then hidden right away?&lt;/p&gt;
&lt;p&gt;The answer is the two code snippets behave exactly in the same way, and that&#39;s because of how the main thread works.&lt;/p&gt;
&lt;h2 id=&quot;the-main-thread&quot; tabindex=&quot;-1&quot;&gt;The main thread &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#the-main-thread&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We call it the main thread because loads of stuff happen here. It&#39;s where JavaScript happens. It&#39;s where rendering happens. It&#39;s where the DOM lives.&lt;/p&gt;
&lt;p&gt;This means stuff on the web has a deterministic order. We don&#39;t get multiple bits of code running at the same time, like trying to edit the same DOM resulting in a world of horrible race conditions.&lt;/p&gt;
&lt;p&gt;But it does mean that if something on the main thread takes a long time (e.g. 200 milliseconds, which is a long time in terms of user interaction) then it becomes really noticeable because it has blocked loads of other things, like rendering, interaction.&lt;/p&gt;
&lt;p&gt;Think about a block in the main thread like when we sneeze. Everything else becomes blocked until the sneeze is over. Needless to say, we don&#39;t want to write code that is like a sneeze.&lt;/p&gt;
&lt;p&gt;So, although we have this main thread thing, we tend to spawn a whole series of threads like for networking stuff, encoding and decoding, crypto, monitoring input devices, but once these threads have done something that the page needs to hear about, they need to sort of come back to the main thread to give it that information and it&#39;s the &lt;strong&gt;event loop&lt;/strong&gt; that orchestrates all of this.&lt;/p&gt;
&lt;h2 id=&quot;task-queues&quot; tabindex=&quot;-1&quot;&gt;Task queues &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#task-queues&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Take &lt;code&gt;setTimeout&lt;/code&gt;, for instance. Have you thought about how it actually works? When invoked, must run the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;wait &lt;code&gt;ms&lt;/code&gt; milliseconds&lt;/li&gt;
&lt;li&gt;invoke callback&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Done.&lt;/p&gt;
&lt;p&gt;We run the steps in parallel — which is a way to say get off the main thread and run this stuff at the same time as other stuff — but we create a new problem here, because now we&#39;re invoking a callback from something other than the main thread, and there&#39;s no way this can really work. You would end up with lots of JavaScript running in parallel, still editing the same DOM and you&#39;d end up with all of these race conditions.&lt;/p&gt;
&lt;p&gt;So, what we do is this: we queue a task. We queue a task to get back on to the main thread at some point, and now we&#39;re calling JavaScript on the thread where JavaScript lives, so it all works.&lt;/p&gt;
&lt;h2 id=&quot;meet-the-event-loop&quot; tabindex=&quot;-1&quot;&gt;Meet the event loop &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#meet-the-event-loop&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/xMF_u-B-3e-648.webp 648w, https://andreaverlicchi.eu/img/xMF_u-B-3e-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/xMF_u-B-3e-648.png 648w, https://andreaverlicchi.eu/img/xMF_u-B-3e-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The event loop and the task detour on the left&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/xMF_u-B-3e-648.png&quot; width=&quot;1296&quot; height=&quot;726&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;This is how Jake depicted the event loop. It&#39;s a circle, the execution goes round and round, until a task is queued in the &quot;task detour&quot; on the left.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Now what if we do this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Well, according to the spec, these two algorithms go parallel, each waits for a thousand milliseconds, and then they need to come back on to the main thread. And they do that by queuing a task.&lt;/p&gt;
&lt;p&gt;So, the browser says to the event loop &amp;quot;Hey, I&#39;ve got something here that wants to do main thread work. In fact, I have two things&amp;quot;, and it adds each one as a separate to-do item in the task queue.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/e2eiThDXOF-648.webp 648w, https://andreaverlicchi.eu/img/e2eiThDXOF-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/e2eiThDXOF-648.png 648w, https://andreaverlicchi.eu/img/e2eiThDXOF-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Two tasks are scheduled for execution in the task queue&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/e2eiThDXOF-648.png&quot; width=&quot;1296&quot; height=&quot;727&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Now two tasks are scheduled for execution in the task queue&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The event loop&#39;s like: &amp;quot;Sure, that&#39;s fine, I&#39;ll get around to it&amp;quot;. So, it runs the first callback, it &lt;strong&gt;goes around the event loop&lt;/strong&gt;, and runs the second callback.&lt;/p&gt;
&lt;p&gt;And that&#39;s tasks. It would be pretty simple if that&#39;s all it was, but it gets more complicated when we think about the render steps.&lt;/p&gt;
&lt;h2 id=&quot;the-render-steps&quot; tabindex=&quot;-1&quot;&gt;The render steps &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#the-render-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is what the browser uses to update what&#39;s actually on the screen.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/NO5dbNqNiG-648.webp 648w, https://andreaverlicchi.eu/img/NO5dbNqNiG-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/NO5dbNqNiG-648.png 648w, https://andreaverlicchi.eu/img/NO5dbNqNiG-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The render steps&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/NO5dbNqNiG-648.png&quot; width=&quot;1296&quot; height=&quot;728&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;On the right side of the event loop, the render steps: style, layout, painting&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The render steps are another detour and that involves style calculation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Style (S): this is looking at all of the CSS that&#39;s going on and working out what applies to each element.&lt;/li&gt;
&lt;li&gt;Layout (L): this is creating a render tree, figuring out where everything is on the page and where it&#39;s positioned.&lt;/li&gt;
&lt;li&gt;Paint (P): creating the actual pixel data, doing the actual painting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, at some point the browser will say to the event loop: &amp;quot;Hey, you know, we need to update what&#39;s on the screen&amp;quot; and the event loop&#39;s like &amp;quot;No problem, I&#39;ll get around to that next time I go around the event loop.&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;an-infinite-loop-with-while-true&quot; tabindex=&quot;-1&quot;&gt;An infinite loop with &lt;code&gt;while(true)&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#an-infinite-loop-with-while-true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&#39;s a page with a gif and some text and a big button that runs an infinite JavaScript loop.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Kve0XgyRaS-648.webp 648w, https://andreaverlicchi.eu/img/Kve0XgyRaS-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/Kve0XgyRaS-648.png 648w, https://andreaverlicchi.eu/img/Kve0XgyRaS-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A simple page with a gif of a cat, some text, and an infinite loop button&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Kve0XgyRaS-648.png&quot; width=&quot;1296&quot; height=&quot;726&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;A simple page with a gif of a cat, some text, and an infinite loop button&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, if I click that button, everything stops. The gif has stopped. I can no longer select text. The whole tab comes to a standstill.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/IWfBvsvjEf-648.webp 648w, https://andreaverlicchi.eu/img/IWfBvsvjEf-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/IWfBvsvjEf-648.png 648w, https://andreaverlicchi.eu/img/IWfBvsvjEf-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The execution point is stuck in the single task in the queue&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/IWfBvsvjEf-648.png&quot; width=&quot;1296&quot; height=&quot;728&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Visualization of the event loop executing an infinite loop&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The user clicks the button, so, the browser says: &amp;quot;Hey, event loop, I&#39;ve got a task for you&amp;quot;, and event loop&#39;s like &amp;quot;Yep, no problem, I&#39;m on it.&amp;quot; But this task never ends. It&#39;s running JavaScript forever.&lt;/p&gt;
&lt;p&gt;A couple of milliseconds later the browser says: &amp;quot;Hey, event loop, we need to update that gif that was on the page. So, if you could just render at your next earliest convenience that would be fantastic&amp;quot;. The event loop&#39;s like, &amp;quot;Yeah, okay, I&#39;ll get around to that right after I finish this infinite loop that I&#39;m busy doing right now.&amp;quot;&lt;/p&gt;
&lt;p&gt;Then the user tries to highlight text and that involves like hit testing, involves looking at the DOM to see what the text actually is. So, the browser says: &amp;quot;Hey, I&#39;ve got a couple of more items for your to-do list there&amp;quot;. And the event loop&#39;s like: &amp;quot;Are you having a laugh? Do you know how long it takes to perform an infinite loop? It&#39;s a long time, you know. There is a clue in the name.&amp;quot;&lt;/p&gt;
&lt;p&gt;So, that is why a &lt;code&gt;while&lt;/code&gt; loop blocks rendering and other page interaction. But this is a good thing in practice. Let&#39;s look again at the code that we started with.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I used to worry that this would result in a flash of content, but it can&#39;t, right? Because this script runs as part of a task, and that must run to completion before the browser can get back around to the render steps.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The event loop guarantees your task will complete before next rendering happens.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;an-infinite-loop-with-settimeout&quot; tabindex=&quot;-1&quot;&gt;An infinite loop with &lt;code&gt;setTimeout()&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#an-infinite-loop-with-settimeout&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So, a while loop blocks rendering, but what about this?&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loop&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a loop, but each time we go round the loop we&#39;re using &lt;code&gt;setTimeout&lt;/code&gt; to queue the next call.&lt;/p&gt;
&lt;p&gt;If we execute that &lt;code&gt;setTimeout&lt;/code&gt; loop in the demo page, it looks nothing has changed, but here&#39;s what&#39;s happening in the background.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/1gyYELhudJ-648.webp 648w, https://andreaverlicchi.eu/img/1gyYELhudJ-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/1gyYELhudJ-648.png 648w, https://andreaverlicchi.eu/img/1gyYELhudJ-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The execution point is going towards the next task queued&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/1gyYELhudJ-648.png&quot; width=&quot;1296&quot; height=&quot;725&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The execution of a &lt;code&gt;setTimeout&lt;/code&gt; loop executes a single task, than queue another one&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We queue a task, go around the event loop, pick up that task, and we queue another task as a result.&lt;/p&gt;
&lt;p&gt;That just keeps happening and happening until the end of time, but as we&#39;ve already seen like only one task can be processed at a time. So, when it&#39;s processing a task, it&#39;s having to go all the way around the event loop to pick up the next task.&lt;/p&gt;
&lt;p&gt;So, that means at some point the browser can say &amp;quot;huh, we should update the display for that gif&amp;quot;, because at that point it can go around and update the display.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/wZDtA2dI97-648.webp 648w, https://andreaverlicchi.eu/img/wZDtA2dI97-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/wZDtA2dI97-648.png 648w, https://andreaverlicchi.eu/img/wZDtA2dI97-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The execution point is going towards the rendering steps&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/wZDtA2dI97-648.png&quot; width=&quot;1296&quot; height=&quot;727&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;After the execution of that &lt;code&gt;setTimeout&lt;/code&gt; callback, the loop is able to render&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And that&#39;s why a &lt;code&gt;setTimeout&lt;/code&gt; loop is not render blocking.&lt;/p&gt;
&lt;h2 id=&quot;requestanimationframe&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#requestanimationframe&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now if you want to run code that has anything to do with rendering, a task is really the wrong place to do it, because a task is on the opposite side of the world to all of the rendering stuff, as far as the event loop is concerned. What we want to do is we want to run code in the render steps.&lt;/p&gt;
&lt;p&gt;We want to run code here:&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/W_NRlUdy82-648.webp 648w, https://andreaverlicchi.eu/img/W_NRlUdy82-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/W_NRlUdy82-648.png 648w, https://andreaverlicchi.eu/img/W_NRlUdy82-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A yellow box labeled rAF has appeared before the style block in the render detour&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/W_NRlUdy82-648.png&quot; width=&quot;1296&quot; height=&quot;727&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt; is the yellow box labeled &quot;rAF&quot; which appeared before the style (S) block in the render detour&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And the browser lets us do that and it lets us do that using &lt;code&gt;requestAnimationFrame&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&amp;quot;rAF&amp;quot; callbacks, they happen as part of the render steps, and to show why this is useful, I&#39;m going to animate a box, just a box, using this code.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/fyHs2P66sI-648.webp 648w, https://andreaverlicchi.eu/img/fyHs2P66sI-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/fyHs2P66sI-648.png 648w, https://andreaverlicchi.eu/img/fyHs2P66sI-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A square box on a blue background&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/fyHs2P66sI-648.png&quot; width=&quot;1296&quot; height=&quot;726&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The box which is about to be animated&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;moveBoxForwardOnePixel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;requestAnimationFrame&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, I&#39;m going to move that box forward one pixel, and then use &lt;code&gt;requestAnimationFrame&lt;/code&gt; to create a loop around this. And that&#39;s it. That&#39;s all it does.&lt;/p&gt;
&lt;p&gt;But what if we switched &lt;code&gt;requestAnimationFrame&lt;/code&gt; for &lt;code&gt;setTimeout&lt;/code&gt;?&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;moveBoxForwardOnePixel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It looks like this.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/HQUe1Cnk27-648.webp 648w, https://andreaverlicchi.eu/img/HQUe1Cnk27-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/HQUe1Cnk27-648.png 648w, https://andreaverlicchi.eu/img/HQUe1Cnk27-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Two square boxes on a blue background, the first labeled requestAnimationFrame, the second labeled setTimeout&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/HQUe1Cnk27-648.png&quot; width=&quot;1296&quot; height=&quot;726&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The two boxes being animated. The one labeled &lt;code&gt;setTimeout&lt;/code&gt; is moving faster than the one labeled &lt;code&gt;requestAnimationFrame&lt;/code&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The new box animated with &lt;code&gt;setTimeout&lt;/code&gt; is moving about 3.5 times faster, and that means this callback is being called more often, and that is not a good thing. That&#39;s not a good thing at all.&lt;/p&gt;
&lt;p&gt;We saw earlier that rendering can happen in between tasks. But just because it can happen doesn&#39;t mean it must.&lt;/p&gt;
&lt;p&gt;We can take a task, &amp;quot;Should we render?&amp;quot;, &amp;quot;No, it can&#39;t be bothered yet.&amp;quot;&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Q08beXeA_D-648.webp 648w, https://andreaverlicchi.eu/img/Q08beXeA_D-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/Q08beXeA_D-648.png 648w, https://andreaverlicchi.eu/img/Q08beXeA_D-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;In the event loop, the switch leading to the render detour is closed&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Q08beXeA_D-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Should we render? Not yet.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Go around the event loop, pick up another task. &amp;quot;Shall we render now?&amp;quot;, &amp;quot;No, it doesn&#39;t feel like the right time&amp;quot;. Many tasks can happen and before the browser goes, &amp;quot;Yeah, actually next time we will update the display&amp;quot;.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/xFlMrtzs9O-648.webp 648w, https://andreaverlicchi.eu/img/xFlMrtzs9O-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/xFlMrtzs9O-648.png 648w, https://andreaverlicchi.eu/img/xFlMrtzs9O-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;In the event loop, the switch leading to the render detour is open&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/xFlMrtzs9O-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Should we render? Now it&#39;s time.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And the browser gets to decide when to do this, and it tries to be as efficient as possible. The render steps only happen if there&#39;s something actually worth updating. If nothing&#39;s changed, it won&#39;t bother.&lt;/p&gt;
&lt;p&gt;Like if the browser tab is in the background, if it isn&#39;t visible, it will never run the render steps because there&#39;s no point, but also the majority of screens update at a set frequency. In most cases that&#39;s 60 times a second. Some screens go faster, some screens go slower, but 60 Hertz is the most common.&lt;/p&gt;
&lt;p&gt;So, if we changed page styles like a thousand times a second, it&#39;s not going to run the render steps a thousand times a second, it will synchronize itself with the display, and only render up to a frequency the display is capable of. Usually, 60 times a second.&lt;/p&gt;
&lt;p&gt;Otherwise, it would be a waste of time, like there&#39;s no point rendering stuff the user will never see. But that&#39;s what &lt;code&gt;setTimeout&lt;/code&gt; is doing here. It&#39;s moving faster because it&#39;s updating the position of that box more times than the user can see, more times than this display is capable of showing us.&lt;/p&gt;
&lt;h4 id=&quot;other-ways-of-queuing-a-task&quot; tabindex=&quot;-1&quot;&gt;Other ways of queuing a task &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#other-ways-of-queuing-a-task&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;So far, we&#39;ve been using &lt;code&gt;setTimeout&lt;/code&gt; as a shorthand for &amp;quot;queuing a task&amp;quot;, and it isn&#39;t really, because even though we&#39;ve put 0 milliseconds for the callback, it&#39;s more like 4.7 milliseconds that the browser will use as a default (the specs the browser can pick any number to use, but Jake has tested and measured it).&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/eqUCIZRie3-648.webp 648w, https://andreaverlicchi.eu/img/eqUCIZRie3-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/eqUCIZRie3-648.png 648w, https://andreaverlicchi.eu/img/eqUCIZRie3-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Three square boxes on a blue background, the first labeled requestAnimationFrame, the second labeled setTimeout, the third labeled queueTask&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/eqUCIZRie3-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The three boxes being animated. The one labeled &lt;code&gt;queueTask&lt;/code&gt; is moving so fast that it appears randomly positioned on its lane&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;There isn&#39;t a single method that just queues a task, but we can kind of fake it using message channels. Jake ran a test with that.&lt;/p&gt;
&lt;p&gt;The result is there are so many tasks happening that it kind of just looks like the box is getting a random position. We&#39;re getting a task every two-hundredths (2/100) of a millisecond. So rendering can happen between tasks, but you can have many, even tens of thousands of tasks between renderings.&lt;/p&gt;
&lt;h2 id=&quot;tasks-and-frames-in-time&quot; tabindex=&quot;-1&quot;&gt;Tasks and frames in time &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#tasks-and-frames-in-time&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s imagine each of these is a frame that is displayed to the user.&lt;/p&gt;
&lt;p&gt;So, our rendering steps they happen at the start of each frame and that includes like style calculation, layout and paint, not necessarily all three every time.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/sUqQCbVCDl-648.webp 648w, https://andreaverlicchi.eu/img/sUqQCbVCDl-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/sUqQCbVCDl-648.png 648w, https://andreaverlicchi.eu/img/sUqQCbVCDl-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Three rectangles representing frames, each one containing a purple rectangle and a green rectangle representing style and render tasks&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/sUqQCbVCDl-648.png&quot; width=&quot;1296&quot; height=&quot;727&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Three frames, each one containing a style task (purple) and a render tasks (green)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Depends what actually needs updating, but I like this. I like this. This is very neat and tidy. This is a beautiful picture.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/evBQx4KYmZ-648.webp 648w, https://andreaverlicchi.eu/img/evBQx4KYmZ-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/evBQx4KYmZ-648.png 648w, https://andreaverlicchi.eu/img/evBQx4KYmZ-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Same as previous figure, now with yellow rectangle shown in random positions inside each rectangle representing a frame&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/evBQx4KYmZ-648.png&quot; width=&quot;1296&quot; height=&quot;728&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Tasks are executed everythere during a single frame&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Tasks on the other hand, they couldn&#39;t give a stuff. They just kind of appear anywhere they fancy. The event loop ensures that they happen in the right order, they happen in the order they were queued, but in terms of timing within a frame there is no kind of ordering here at all.&lt;/p&gt;
&lt;p&gt;And we saw this with our &lt;code&gt;setTimeout&lt;/code&gt;. We were getting four per frame, three or four per frame, and that means that three-quarters of those callbacks were wasted effort in terms of rendering.&lt;/p&gt;
&lt;figure&gt;
	 &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/F-dI3j6qJM-648.webp 648w, https://andreaverlicchi.eu/img/F-dI3j6qJM-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/F-dI3j6qJM-648.png 648w, https://andreaverlicchi.eu/img/F-dI3j6qJM-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Same as previous figure, now 3 out of 4 yellow rectangles are offset, representing the wasted effort&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/F-dI3j6qJM-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;3 out of 4 tasks highlghted as wasted effort in terms of rendering&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Old animation libraries used to do something like this, where they were trying to use a millisecond value that&#39;s going to give them roughly 60 callbacks per second...&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;animFrame&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...and they&#39;re assuming a lot about the screen there. They&#39;re assuming a screen is 60 Hertz, but that was the common case.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/s6MJKzYi7J-648.webp 648w, https://andreaverlicchi.eu/img/s6MJKzYi7J-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/s6MJKzYi7J-648.png 648w, https://andreaverlicchi.eu/img/s6MJKzYi7J-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Tasks distributed one per frame&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/s6MJKzYi7J-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Tasks are scheduled in every frame using &lt;code&gt;setTimeout&lt;/code&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So, it kind of worked, it eliminated some of the duplicate effort. Unfortunately, it was a massive hack because setTimeout was not designed for animation and it really shows like due to inaccuracies you can end up with drift.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/5GXsZPZ9_I-648.webp 648w, https://andreaverlicchi.eu/img/5GXsZPZ9_I-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/5GXsZPZ9_I-648.png 648w, https://andreaverlicchi.eu/img/5GXsZPZ9_I-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;One yellow square which was supposed to be in the second frame appears in the third frame&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/5GXsZPZ9_I-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;One task was supposed to be in the second frame, but was executed during the third frame&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So, what&#39;s happened here is we&#39;re doing nothing in one frame, and then in the next frame we&#39;re doing twice the amount of work, and that is a visual jank to user, it doesn&#39;t look great.&lt;/p&gt;
&lt;p&gt;Also, if one of your tasks runs long, you can end up moving the render steps around because it&#39;s all running on the same thread and you&#39;re sort of disturbing that lovely routine that they have.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/eEXu-sJktg-648.webp 648w, https://andreaverlicchi.eu/img/eEXu-sJktg-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/eEXu-sJktg-648.png 648w, https://andreaverlicchi.eu/img/eEXu-sJktg-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Yellow squares starting inside each frame, the first one of them extending over to the next frame&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/eEXu-sJktg-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Frames are starting inside each frame, the first one of them being executed over to the next frame&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If we use &lt;code&gt;requestAnimationFrame&lt;/code&gt; rather than &lt;code&gt;setTimeout&lt;/code&gt;, it would look a lot more like this. All neat and tidy. All nice and ordered. Everything is within the timing of the frame, even this longer task here.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/rH1aw-ePOj-648.webp 648w, https://andreaverlicchi.eu/img/rH1aw-ePOj-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/rH1aw-ePOj-648.png 648w, https://andreaverlicchi.eu/img/rH1aw-ePOj-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The yellow rectangles representing tasks are grouped together at the beginning of each frame&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/rH1aw-ePOj-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Tasks are grouped together at the beginning of every frame, using &lt;code&gt;requestAnimationFrame&lt;/code&gt; instead of &lt;code&gt;setTimeout&lt;/code&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Jake says when he sees performance traces like this, it makes him happy, as this is showing a good user experience.&lt;/p&gt;
&lt;p&gt;You can&#39;t avoid tasks completely of course because things like click events they&#39;re going to be delivered to you in a task, and generally you want to respond to those as soon as possible. But if you have things like timers or you have stuff coming from the network, Jake recommends using &lt;code&gt;requestAnimationFrame&lt;/code&gt; to batch that work together, especially if you already have animations running because you can save yourself a lot of duplicate work.&lt;/p&gt;
&lt;h2 id=&quot;tasks-and-render-timing&quot; tabindex=&quot;-1&quot;&gt;Tasks and render timing &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#tasks-and-render-timing&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&#39;s one more detail I want to get to and this is something that catches a lot of developers out, it caught me out. &lt;code&gt;requestAnimationFrame&lt;/code&gt; it comes before processing CSS and before painting.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;block&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;block&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;block&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;block&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, code like this might seem expensive, like we&#39;re showing and hiding a box many many times, but this is actually really cheap, like JavaScript will always run to completion before rendering happens.&lt;/p&gt;
&lt;p&gt;So, while you&#39;re doing this the browser just sits back, and it lets you have your fun changing a value and it doesn&#39;t really think about it in terms of CSS at all. And then at the end when it actually comes around to the render steps it goes, right, what did you actually change in the end? And the only bit that matters is the final line. And the only bit that matters is the final line.&lt;/p&gt;
&lt;p&gt;So the code above, in terms of rendering, is equivalent to the following code.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	box&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;animate-a-box&quot; tabindex=&quot;-1&quot;&gt;Animate a box? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#animate-a-box&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;m omitting the part where Jake explained how to queue some Javascript to animate a box from 1000 to 500 pixels using a double &lt;code&gt;requestAnimationFrame&lt;/code&gt; callback, as it&#39;s irrelevant at the time of writing: the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API&quot;&gt;Web Animation API&lt;/a&gt;, which was only available in Chrome at the time of Jake&#39;s talk, is now cross-browser.&lt;/p&gt;
&lt;h2 id=&quot;microtasks&quot; tabindex=&quot;-1&quot;&gt;Microtasks &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#microtasks&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Back in the 1990s, browsers wanted to give developers a way to monitor DOM changes and the W3C gave us mutation events.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;DOMNodeInserted&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Stuff added to the &amp;lt;body&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, this is where I could say, okay, I want to know when a node is inserted into the &lt;code&gt;body&lt;/code&gt; element. And you get a series of other events as well.&lt;/p&gt;
&lt;p&gt;But, in practice this was pretty problematic.
We take this bit of code here, what I&#39;m doing is I&#39;m adding a hundred spans into the body element.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; span &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;span&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;span&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	span&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Hello&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How many events would you expect to receive as a result of this?
One event? One event for the whole operation? Nope.
100 events? One for each span. Yes.&lt;/p&gt;
&lt;p&gt;But also, another hundred for &lt;code&gt;span.textContent = &#39;Hello&#39;;&lt;/code&gt; when the text node is going into the span. And because these events bubble, this simple piece of code is going to land you with 200 events.&lt;/p&gt;
&lt;p&gt;And because of this like relatively simple DOM modifications ended up triggering thousands of events and if you were doing like a tiny bit of work in these listeners that quickly became a big bit of work, and it was a performance disaster.&lt;/p&gt;
&lt;p&gt;What we really wanted was a way to sort of hear about a batch of this work.
And similar to what we saw with styles before.
We want the browser to kind of sit back, let us do some stuff and then at a convenient point, say, some stuff changed.
Here is a kind of an event or something to represent all of those changes.&lt;/p&gt;
&lt;p&gt;We want to hear about it once, not 200 times. And the answer became mutation observers. And they created a new queue called microtasks.&lt;/p&gt;
&lt;p&gt;A lot of documentation I read about microtasks suggests that it happens like, I don&#39;t know, every turn of the event loop or it happens after a task or something like that and it is kind of true. There is a single place on the event loop where microtasks happen, but that is not where you&#39;ll generally encounter it. They also happen whenever JavaScript finishes executing.&lt;/p&gt;
&lt;p&gt;That means that the JavaScript stack has gone from having stuff in it to having no stuff in it and that&#39;s where we run microtasks.&lt;/p&gt;
&lt;p&gt;So, you can end up with microtasks happening halfway through a task, you can have microtasks in the render steps as part of &lt;code&gt;requestAnimationFrame&lt;/code&gt;s, kind of anywhere, anywhere JavaScript can run.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; span &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;span&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;span&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	span&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Hello&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, that means this JavaScript will run to completion adding a hundred spans and their contents.
JavaScript finishes executing and we get our mutation observer callback.&lt;/p&gt;
&lt;p&gt;Promises made use of them as well.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Hey!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Yo!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, here we queue a microtask and then log ‘Yo!’.
JavaScript has finished executing.
Then, we go for the microtasks, and we log ‘Hey!’.&lt;/p&gt;
&lt;p&gt;And that means when the Promise callback is executing you were guaranteed that no other JavaScript is midway through at the time, the Promise callback is right at the bottom of the stack, and that&#39;s why Promises use microtasks.&lt;/p&gt;
&lt;h2 id=&quot;an-infinite-loop-with-promise-resolve&quot; tabindex=&quot;-1&quot;&gt;An infinite loop with &lt;code&gt;Promise.resolve()&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#an-infinite-loop-with-promise-resolve&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;But what happens if we create a loop using microtasks? In terms of code, a bit like we did with &lt;code&gt;setTimeout&lt;/code&gt; &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#an-infinite-loop-with-settimeout&quot;&gt;before&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/mUeG6U3eES-648.webp 648w, https://andreaverlicchi.eu/img/mUeG6U3eES-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/mUeG6U3eES-648.png 648w, https://andreaverlicchi.eu/img/mUeG6U3eES-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A web page with a cat gif, a bunch of text, and a button labeled &amp;quot;Microtask Loop&amp;quot;&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/mUeG6U3eES-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Same demo again: a cat gif, a bunch of text, and a button labeled &quot;Microtask Loop&quot;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Click the button and... it blocks rendering, it blocks the tab in the same way a plain &lt;code&gt;while&lt;/code&gt; loop did, but very different from &lt;code&gt;setTimeout&lt;/code&gt; before.&lt;/p&gt;
&lt;p&gt;So, &lt;code&gt;Promise&lt;/code&gt; callbacks are async, fine, but what does async actually mean?
All it means is that they happen after synchronously executing code, so that&#39;s why we get ‘Yo!’ before ‘Hey!’.
But just being async doesn&#39;t mean it must yield to rendering, doesn&#39;t mean it must yield to any particular part of the event loop.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/mmhyo-LkSN-648.webp 648w, https://andreaverlicchi.eu/img/mmhyo-LkSN-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/mmhyo-LkSN-648.png 648w, https://andreaverlicchi.eu/img/mmhyo-LkSN-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Three piles of rectangles each containing the word &amp;quot;Item&amp;quot;. The first pile is labeled Tasks, the second &amp;quot;Animation callbacks&amp;quot;, the third &amp;quot;Microtasks&amp;quot;&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/mmhyo-LkSN-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Three types of queues: Tasks, Animation Callbacks, Microtasks&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We&#39;ve looked at three different queues so far. We’ve looked at task queues, animation callback queues which is where &lt;code&gt;requestAnimationFrame&lt;/code&gt; callbacks happen and now we&#39;re looking at microtasks. And just to make your lives a little bit easier they all are processed very subtly differently.&lt;/p&gt;
&lt;p&gt;Like we&#39;ve seen with task queues, we take one item and we take one item only. And if another item is queued it just goes to the end of the queue. Fine.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/S5ndBRP0OV-648.webp 648w, https://andreaverlicchi.eu/img/S5ndBRP0OV-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/S5ndBRP0OV-648.png 648w, https://andreaverlicchi.eu/img/S5ndBRP0OV-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The same image depicted in the latest figure, but now the first item at the top of the task queue is green and it&#39;s labeled &amp;quot;Additional item&amp;quot;&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/S5ndBRP0OV-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Additional item added to the task queue is not immediately processed&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Animation callbacks they happen until completion, except ones that were queued while we were processing animation callbacks. They are deferred to the next frame.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/pZ9jzhbQJH-648.webp 648w, https://andreaverlicchi.eu/img/pZ9jzhbQJH-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/pZ9jzhbQJH-648.png 648w, https://andreaverlicchi.eu/img/pZ9jzhbQJH-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The same image depicted in the latest figure, but now all items in the requestAnimationFrame queue are green and are labeled &amp;quot;Additional item&amp;quot;&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/pZ9jzhbQJH-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;All tasks of the &lt;code&gt;requestAnimationFrame&lt;/code&gt; queue are processed, but not the newly added ones&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Microtasks on the other hand they are processed to completion including any additionally queued items.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/QBKz5LWGEF-648.webp 648w, https://andreaverlicchi.eu/img/QBKz5LWGEF-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/QBKz5LWGEF-648.png 648w, https://andreaverlicchi.eu/img/QBKz5LWGEF-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The same image depicted in the latest figure, but now all items in the microtasks queue are green, labeled &amp;quot;Additional item&amp;quot;, and more are appearing on top&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/QBKz5LWGEF-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;New microtasks keep being processed until the queue is empty&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So, if you were adding items to the queue as quickly as you&#39;re processing them you are processing microtasks forever.
The event loop cannot continue until that queue has completely emptied. And that is why it blocks rendering.&lt;/p&gt;
&lt;h2 id=&quot;more-in-the-video&quot; tabindex=&quot;-1&quot;&gt;More in the video &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#more-in-the-video&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The talk ends with some Javascript quizzes about microtasks and the order of execution, but this blog post is already veeeeeeeery long, so if you really want to solve the puzzles, watch the video.&lt;/p&gt;
&lt;p&gt;You should really watch the video from the talk if you didn&#39;t already, because the &amp;quot;slides&amp;quot; Jake created use amazing animation explaining all very well.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/cCOL7MC4Pl0?si=EEhZlFn4UuzsfCpj&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; loading=&quot;lazy&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I hope you found useful this transposition of Jake&#39;s talk into text!
It really helped me to understand how browsers work under the hood.&lt;/p&gt;
&lt;p&gt;It took me a while to write this, please consider &lt;a href=&quot;https://ko-fi.com/verlok&quot;&gt;buying me a coffee&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Web performance snippets to debug INP in Chrome dev tools</title>
		<link href="https://andreaverlicchi.eu/en/blog/web-performance-snippets-debug-inp-lcp-cls-core-web-vitals-in-chrome-dev-tools/"/>
		<updated>2024-02-14T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/web-performance-snippets-debug-inp-lcp-cls-core-web-vitals-in-chrome-dev-tools/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Ae26uAWD0H-648.webp 648w, https://andreaverlicchi.eu/img/Ae26uAWD0H-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/Ae26uAWD0H-648.png 648w, https://andreaverlicchi.eu/img/Ae26uAWD0H-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A screenshot of an interaction in the performance trace tab&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/Ae26uAWD0H-648.png&quot; width=&quot;1296&quot; height=&quot;526&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;A screenshot of an interaction debug in the performance trace. Credits: web.dev&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After keeping them on my computer for some days, I decided to publish on GitHub this set of web performance snippets to debug INP in Chrome developer tools, or to report data to your analytics&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;&lt;a href=&quot;https://github.com/verlok/webperf-snippets&quot;&gt;Find them here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Enjoy web performance debugging!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use scheduler.yield to improve web pages responsiveness</title>
		<link href="https://andreaverlicchi.eu/en/blog/how-to-use-scheduler-yield-to-improve-web-page-responsiveness/"/>
		<updated>2023-08-31T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/how-to-use-scheduler-yield-to-improve-web-page-responsiveness/</id>
		<content type="html">&lt;figure&gt;
	&lt;img alt=&quot;A street signal, a white triangle with red border with a red YIELD word inside it&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/0ZQEV3SwTA-648.webp&quot; width=&quot;1296&quot; height=&quot;864&quot; srcset=&quot;https://andreaverlicchi.eu/img/0ZQEV3SwTA-648.webp 648w, https://andreaverlicchi.eu/img/0ZQEV3SwTA-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;
	&lt;figcaption&gt;Just a random yield image&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In August 2023, Google introduced the &lt;code&gt;scheduler.yield&lt;/code&gt;, which is available as an origin trial in Chrome 115 and later.&lt;/p&gt;
&lt;h2 id=&quot;what-is-it&quot; tabindex=&quot;-1&quot;&gt;What is it &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-use-scheduler-yield-to-improve-web-page-responsiveness/#what-is-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;scheduler.yield&lt;/code&gt; is a new feature in Chrome that allows web developers to explicitly tell the browser to yield control back to the main thread. This can be useful for tasks that are known to take a long time, as this allows &lt;em&gt;other&lt;/em&gt; tasks to get time on the main thread sooner (than if they had to wait for long tasks to finish).&lt;/p&gt;
&lt;p&gt;When you explicitly yield, you&#39;re telling the browser &amp;quot;Hey, I understand that the work I&#39;m about to do could take a while, and I don&#39;t want you to have to do all of that work before responding to user input or other tasks that might be important, too&amp;quot;.&lt;/p&gt;
&lt;p&gt;This can help to improve the overall responsiveness of the web page, as the browser will be able to focus on other tasks while the long-running task is in progress.&lt;/p&gt;
&lt;p&gt;And of course, this will come in handy when working on improving the &lt;a href=&quot;https://web.dev/inp/&quot;&gt;Interaction to Next Paint (INP)&lt;/a&gt; web vital, which will become a Core Web Vital starting March 2024.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot; tabindex=&quot;-1&quot;&gt;How to use it &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-use-scheduler-yield-to-improve-web-page-responsiveness/#how-to-use-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is how you use it:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;yieldy&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Do some work...&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Yield!&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; scheduler&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Do some more work...&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But wait, can you use it only in Chrome?
Yes, but you could fall back to using the good old &lt;code&gt;setTimeout&lt;/code&gt; and do something similar.&lt;/p&gt;
&lt;p&gt;The only difference is browsers that don&#39;t support &lt;code&gt;scheduler.yield&lt;/code&gt; will yield without &amp;quot;front of queue&amp;quot; behavior, as &lt;code&gt;setTimeout&lt;/code&gt; sends the remaining work to the back of the task queue.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// A function for shimming scheduler.yield and setTimeout:&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;yieldToMain&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Use scheduler.yield if it exists:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;scheduler&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; window &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;yield&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; scheduler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; scheduler&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Fall back to setTimeout:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Example usage:&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doWork&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Do some work:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;yieldToMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Do some other work:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;want-to-try-it&quot; tabindex=&quot;-1&quot;&gt;Want to try it? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-use-scheduler-yield-to-improve-web-page-responsiveness/#want-to-try-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can try &lt;code&gt;scheduler.yield&lt;/code&gt; on your browser by enabling the &amp;quot;experimental web platform features&amp;quot; flag, as shown in the following image:&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/lyCjCZ-U60-648.webp 648w, https://andreaverlicchi.eu/img/lyCjCZ-U60-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/lyCjCZ-U60-648.png 648w, https://andreaverlicchi.eu/img/lyCjCZ-U60-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Experimental web platform features enabled in Chrome browser&#39;s settings&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/lyCjCZ-U60-648.png&quot; width=&quot;1296&quot; height=&quot;579&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;How to enable experimental web platform features in Chrome browser&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And then, you will be able to use it:&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/5A8b6ckAyT-648.webp 648w, https://andreaverlicchi.eu/img/5A8b6ckAyT-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/5A8b6ckAyT-648.png 648w, https://andreaverlicchi.eu/img/5A8b6ckAyT-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;scheduler.yield is present, scheduler.yield() returns a Promise (pending)&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/5A8b6ckAyT-648.png&quot; width=&quot;1296&quot; height=&quot;364&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;How `scheduler.yield` looks when invoked in the developer tools console&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;want-to-try-it-in-production&quot; tabindex=&quot;-1&quot;&gt;Want to try it in production? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-use-scheduler-yield-to-improve-web-page-responsiveness/#want-to-try-it-in-production&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can! The &lt;code&gt;scheduler.yield&lt;/code&gt; is - at the time of writing (September 2023) - in origin trial in Chrome 115 and later. You can learn more about origin trials and how to participate in the trial on the Chrome Developers website: &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/origin-trials/&quot;&gt;Get started with origin trials&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the full article with a detailed explanation on the Chrome Developers blog: &lt;a href=&quot;https://developer.chrome.com/blog/introducing-scheduler-yield-origin-trial/&quot;&gt;Introducing the scheduler.yield origin trial&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Preparing for Interaction to Next Paint (INP), a new Core Web Vital starting March 2024</title>
		<link href="https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/"/>
		<updated>2023-07-12T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/</id>
		<content type="html">&lt;figure&gt;
	&lt;img alt=&quot;Michelangelo&#39;s &#39;Creation of Adam&#39; painting&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/VNBwh4cWBA-648.webp&quot; width=&quot;648&quot; height=&quot;372&quot;&gt;
	&lt;figcaption&gt;Michelangelo&#39;s &quot;Creation of Adam&quot; painting&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As a web performance consultant, I&#39;m always on the lookout for new developments that impact the user experience of websites. One such upcoming change is the introduction of a new metric called &lt;a href=&quot;https://web.dev/inp/&quot;&gt;Interaction to Next Paint (INP)&lt;/a&gt; by Google. Set to become a &lt;a href=&quot;https://web.dev/cwv/&quot;&gt;Core Web Vital&lt;/a&gt; in March 2024, INP is designed to measure the time it takes for a website to respond to user interactions. In this blog post, we will delve into what INP is, why it matters, and how companies can prepare themselves to ensure their websites meet this crucial web performance metric.&lt;/p&gt;
&lt;h2 id=&quot;understanding-interaction-to-next-paint-inp&quot; tabindex=&quot;-1&quot;&gt;Understanding Interaction to Next Paint (INP) &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#understanding-interaction-to-next-paint-inp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;INP is an important addition to the Core Web Vitals, a set of metrics that Google uses to assess and rank websites based on their user experience.&lt;/p&gt;
&lt;p&gt;Unlike other metrics such as Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS), which measure loading and visual stability, INP focuses on interactivity, meaning how quickly a website responds to user input after it has loaded. It quantifies the time it takes for the website to be ready to paint something after users interacted with them, and it aims to bring users an experience without any noticeable delays.&lt;/p&gt;
&lt;h2 id=&quot;why-inp-matters&quot; tabindex=&quot;-1&quot;&gt;Why INP Matters &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#why-inp-matters&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In today&#39;s digital landscape, user expectations are higher than ever. People demand fast and seamless interactions when browsing the web, and any delays or unresponsive elements can result in frustration and abandonment. INP addresses this issue directly by measuring the time it takes for a website to respond to user inputs, which is a critical factor in delivering an exceptional user experience.&lt;/p&gt;
&lt;p&gt;Moreover, Google has emphasized the importance of Core Web Vitals as a ranking factor for search engine optimization (SEO). Websites that provide better user experiences, as measured by these metrics, are more likely to rank higher in search results. With INP set to become a Core Web Vital, companies that prioritize website interactivity will not only enhance their user experience but also gain an advantage in search engine visibility.&lt;/p&gt;
&lt;h2 id=&quot;preparing-for-inp&quot; tabindex=&quot;-1&quot;&gt;Preparing for INP &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#preparing-for-inp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As the March 2024 deadline approaches, companies need to prepare for the inclusion of INP as a Core Web Vital. Here are some steps to ensure your website is ready:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Evaluate Current INP Performance&lt;/strong&gt;: Start by assessing your website&#39;s current INP performance. The easiest way to check your website&#39;s INP values is via &lt;a href=&quot;https://search.google.com/search-console/about&quot;&gt;Google Search Console&lt;/a&gt;. Alternatively, you can try &lt;a href=&quot;https://developer.chrome.com/docs/crux/&quot;&gt;Chrome User Experience Report&lt;/a&gt; (CrUX) or &lt;a href=&quot;https://pagespeed.web.dev/&quot;&gt;PageSpeed Insights&lt;/a&gt;. Benchmark your current INP scores and set goals for improvement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Improve INP&lt;/strong&gt;: See next chapter to find out what to do to improve INP on your website.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Continuously monitoring and iterate&lt;/strong&gt;: Web performance is an ongoing process, and it&#39;s crucial to monitor and measure INP regularly. Continuously analyze your website&#39;s performance, implement optimizations, and retest to ensure your INP scores meet the desired targets. Regularly review Google&#39;s developer documentation and community forums for updated best practices.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;how-to-improve-inp&quot; tabindex=&quot;-1&quot;&gt;How to improve INP &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#how-to-improve-inp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s get a little bit technical now. There are 3 types of actions you can take to improve INP on your website. Avoid or break up long tasks, avoid unnecessary JavaScript, and avoid large rendering updates.&lt;/p&gt;
&lt;h3 id=&quot;avoid-or-break-up-long-tasks&quot; tabindex=&quot;-1&quot;&gt;Avoid or break up long tasks &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#avoid-or-break-up-long-tasks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Tasks are any piece of discrete work that the browser does. Tasks include rendering, layout, parsing, and compiling and executing scripts. When tasks become long tasks—that is, 50 milliseconds or longer—they block the main thread from being able to respond quickly to user inputs.&lt;/p&gt;
&lt;p&gt;Another option is to consider using APIs such as &lt;code&gt;isInputPending&lt;/code&gt; and the Scheduler API. &lt;code&gt;isInputPending&lt;/code&gt; is a function that returns a boolean value that indicates whether user input is pending. If it returns true, you can yield to the main thread so it can handle the pending user input. &lt;a href=&quot;https://web.dev/optimize-long-tasks/#yield-only-when-necessary&quot;&gt;Check out &lt;code&gt;isInputPending&lt;/code&gt;&lt;/a&gt; to yield only when necessary.&lt;/p&gt;
&lt;p&gt;The Scheduler API is a more advanced approach, which allows you to schedule work based on a system of priorities that take into account whether the work being done is user-visible or backgrounded. &lt;a href=&quot;https://web.dev/optimize-long-tasks/#a-dedicated-scheduler-api&quot;&gt;Check out the Scheduler API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By breaking up long tasks, you&#39;re giving the browser more opportunities to fit in critical user-visible work, such as dealing with interactions and any resulting rendering updates.&lt;/p&gt;
&lt;h3 id=&quot;avoid-unnecessary-javascript&quot; tabindex=&quot;-1&quot;&gt;Avoid unnecessary JavaScript &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#avoid-unnecessary-javascript&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&#39;s no doubt about it: websites are &lt;a href=&quot;https://almanac.httparchive.org/en/2022/javascript#how-much-javascript-do-we-load&quot;&gt;shipping more JavaScript&lt;/a&gt; than ever before, and the trend doesn&#39;t look like it&#39;s changing any time soon. When you ship too much JavaScript, you&#39;re creating an environment where tasks are competing for the main thread&#39;s attention. This can definitely affect your website&#39;s responsiveness, especially during that crucial startup period.&lt;/p&gt;
&lt;p&gt;This is not an unsolvable problem, however. You do have some options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the coverage tool in Chrome DevTools to find unused code in your website&#39;s resources. By reducing the size of the resources you need during startup, you can ensure your website spends less time parsing and compiling code, which leads to a smoother initial user experience. &lt;a href=&quot;https://developer.chrome.com/docs/devtools/coverage/&quot;&gt;Check out the Coverage Tool&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Sometimes the unused code you find using the coverage tool is marked &amp;quot;unused&amp;quot; because it wasn&#39;t executed during startup, but is still necessary for some functionality in the future. This is code that you can move to a separate bundle via code splitting. &lt;a href=&quot;https://web.dev/reduce-javascript-payloads-with-code-splitting/&quot;&gt;Find out more about code splitting&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you&#39;re using a tag manager, be sure to periodically check your tags to make sure they are optimized, or even if they&#39;re still being used. Older tags with unused code can be cleared out to make your tag manager&#39;s JavaScript smaller and more efficient. &lt;a href=&quot;https://web.dev/tag-best-practices/&quot;&gt;More best practices for tag managers&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;avoid-large-rendering-updates&quot; tabindex=&quot;-1&quot;&gt;Avoid large rendering updates &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#avoid-large-rendering-updates&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JavaScript isn&#39;t the only thing that can affect your website&#39;s responsiveness. Rendering can be a type of expensive work in its own right—and when large rendering updates happen, they can interfere with your website&#39;s ability to respond to user inputs.&lt;/p&gt;
&lt;p&gt;Optimizing rendering work isn&#39;t a straightforward process, and it often depends on what you&#39;re trying to achieve. Even so, there are some things you can do to ensure that your rendering updates are reasonable and don&#39;t sprawl into long tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid using &lt;code&gt;requestAnimationFrame()&lt;/code&gt; for doing any non-visual work. &lt;code&gt;requestAnimationFrame()&lt;/code&gt; calls are handled during the rendering phase of the event loop, and when too much work is done during this step, rendering updates can be delayed. It&#39;s essential that any work you&#39;re doing with &lt;code&gt;requestAnimationFrame()&lt;/code&gt; is reserved strictly for tasks that involve rendering updates.&lt;/li&gt;
&lt;li&gt;Keep your DOM size small. DOM size and the intensity of layout work are correlated. When the renderer has to update the layout for a very large DOM, the work required to recalculate its layout can increase significantly. &lt;a href=&quot;https://developer.chrome.com/docs/lighthouse/performance/dom-size/&quot;&gt;Avoiding excessive DOM size&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use CSS containment. CSS containment relies on the CSS contain property, which gives instructions to the browser about how to do layout work for the container the contain property is set on, including even isolating the scope of layout and rendering to a specific root in the DOM. It&#39;s not always an easy process, but by isolating areas containing complex layouts, you can avoid doing layout and rendering work for them that isn&#39;t necessary. &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/CSS_Containment&quot;&gt;More about CSS Containment&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With Interaction to Next Paint (INP) set to become a Core Web Vital in March 2024, companies should start to prioritize website interactivity to deliver an exceptional user experience and improve search engine rankings.&lt;/p&gt;
&lt;p&gt;By evaluating current INP performance, optimizing for interactivity, and continuously monitoring and iterating, businesses can prepare themselves for the upcoming change.&lt;/p&gt;
&lt;p&gt;Embracing INP as a vital performance metric will not only benefit users but also contribute to the long-term success of their online presence.&lt;/p&gt;
&lt;h2 id=&quot;need-a-hand&quot; tabindex=&quot;-1&quot;&gt;Need a hand? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/preparing-for-interaction-to-next-paint-inp-core-web-vital-google/#need-a-hand&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to know more about INP, how to optimize it, or you need web performance consultancy, feel free to &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out to me&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk: How and Why ($) to optimize web performance in 2023</title>
		<link href="https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/"/>
		<updated>2023-06-16T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/</id>
		<content type="html">&lt;p&gt;In 2023 I&#39;ve been speaking about web performance at conferences, Google Developer Groups (GDG) and local meetups all over Europe. The title of this talk is &amp;quot;How and Why ($) to improve web performance, practical tips for 2023&amp;quot;.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/ofRvkAJXGGw?si=2WGVWiQhq2ckqNY_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;The first part of the talk is about the reasons why you should optimize web performance, and the second part is about how to do it, with practical tips coming &lt;a href=&quot;https://web.dev/top-cwv-2023/&quot;&gt;from Google&lt;/a&gt; and based on data collected during the &lt;a href=&quot;https://almanac.httparchive.org/en/2022/performance&quot;&gt;web performance chapter&lt;/a&gt; of the &lt;a href=&quot;https://almanac.httparchive.org/en/2022/&quot;&gt;web almanac 2022&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Find below the slides of my talk, both in English and Italian language.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://andreaverlicchi.eu/pdf/how-why-improve-web-performance-practical-tips-2023.pdf&quot;&gt;Slides in English&lt;/a&gt; 🇬🇧 · &lt;a href=&quot;https://andreaverlicchi.eu/pdf/come-perche-migliorare-prestazioni-web-consigli-pratici-2023.pdf&quot;&gt;Slide in Italiano&lt;/a&gt; 🇮🇹&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;waysconf-krakow-4-september-2023&quot; tabindex=&quot;-1&quot;&gt;WaysConf, Kraków 🇵🇱 – &lt;time datetime=&quot;2023-09-04&quot;&gt;4 September 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#waysconf-krakow-4-september-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/RnlMzWFgWG-648.webp 648w, https://andreaverlicchi.eu/img/RnlMzWFgWG-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/RnlMzWFgWG-648.png 648w, https://andreaverlicchi.eu/img/RnlMzWFgWG-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi on stage at the WaysConf Kraków&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/RnlMzWFgWG-648.png&quot; width=&quot;1296&quot; height=&quot;864&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me explaining the difference between lab and RUM tools at WaysConf 2023&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ofRvkAJXGGw&quot;&gt;📺 Video&lt;/a&gt; · &lt;a href=&quot;https://www.waysconf.com/lecture/how-and-why-to-improve-web-performance-in-2023&quot;&gt;Conference talk page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;dev-bcn-conference-barcelona-4-july-2023&quot; tabindex=&quot;-1&quot;&gt;Dev BCN Conference, Barcelona 🇪🇸 – &lt;time datetime=&quot;2023-07-04&quot;&gt;4 July 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#dev-bcn-conference-barcelona-4-july-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/sR1XTNBOBC-648.webp 648w, https://andreaverlicchi.eu/img/sR1XTNBOBC-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/sR1XTNBOBC-648.png 648w, https://andreaverlicchi.eu/img/sR1XTNBOBC-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi showing a slide about Core Web Vitals and the new Interaction to Next Paint on stage at the Dev BCN conference&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/sR1XTNBOBC-648.png&quot; width=&quot;1296&quot; height=&quot;863&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me presenting a slide about Core Web Vitals on stage at the Dev BCN conference&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://www.devbcn.com/talk/457013&quot;&gt;Conference talk page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;devfest-vienna-14-october-2023&quot; tabindex=&quot;-1&quot;&gt;DevFest, Vienna 🇦🇹 – &lt;time datetime=&quot;2023-10-14&quot;&gt;14 October 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#devfest-vienna-14-october-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;img alt=&quot;Andrea Verlicchi on stage at DevFest Vienna, 2023&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/WnICdy0177-648.webp&quot; width=&quot;1296&quot; height=&quot;863&quot; srcset=&quot;https://andreaverlicchi.eu/img/WnICdy0177-648.webp 648w, https://andreaverlicchi.eu/img/WnICdy0177-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;
  &lt;figcaption&gt;Me on stage explaining what is Interaction to Next Paint&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://devfest.at/schedule/&quot;&gt;DevFest schedule&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;google-developer-group-munich-7-june-2023&quot; tabindex=&quot;-1&quot;&gt;Google Developer Group, Munich 🇩🇪 – &lt;time datetime=&quot;2023-06-07&quot;&gt;7 June 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#google-developer-group-munich-7-june-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/rZOIAdVBpk-648.webp 648w, https://andreaverlicchi.eu/img/rZOIAdVBpk-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/rZOIAdVBpk-648.jpeg 648w, https://andreaverlicchi.eu/img/rZOIAdVBpk-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea speaking in front of the audience, shot from the audience&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/rZOIAdVBpk-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me speaking in front of the audience in Google Munich&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-munich-presents-web-performance-meetup/&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;google-developer-group-firenze-25-may-2023&quot; tabindex=&quot;-1&quot;&gt;Google Developer Group, Firenze 🇮🇹 – &lt;time datetime=&quot;2023-05-25&quot;&gt;25 May 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#google-developer-group-firenze-25-may-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/ZmvXQ0KrMH-648.webp 648w, https://andreaverlicchi.eu/img/ZmvXQ0KrMH-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/ZmvXQ0KrMH-648.jpeg 648w, https://andreaverlicchi.eu/img/ZmvXQ0KrMH-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea speaking in front of the audience, shot from the side&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/ZmvXQ0KrMH-648.jpeg&quot; width=&quot;1296&quot; height=&quot;958&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me speaking in front of the audience at Nana Bianca, Firenze&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Italian title: Come e perché ($) migliorare le Prestazioni Web: consigli pratici per il 2023&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-firenze-presents-come-e-perche-migliorare-le-prestazioni-web/&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;bologna-js-google-developer-group-bologna-5-april-2023&quot; tabindex=&quot;-1&quot;&gt;Bologna JS + Google Developer Group, Bologna 🇮🇹 – &lt;time datetime=&quot;2023-04-05&quot;&gt;5 April 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#bologna-js-google-developer-group-bologna-5-april-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/Sa4w-8TfNq-648.webp 648w, https://andreaverlicchi.eu/img/Sa4w-8TfNq-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/Sa4w-8TfNq-648.jpeg 648w, https://andreaverlicchi.eu/img/Sa4w-8TfNq-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea speaking in front of the audience, the slide shows the text &#39;Assicurati che le pagine siano idonee per la cache back/forward (bfcache)&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/Sa4w-8TfNq-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me on stage at the Bologna event&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Italian title: &amp;quot;Come e perché ($) migliorare le Prestazioni Web: consigli pratici per il 2023&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=_UuExM3NhaA&quot;&gt;📺 Video&lt;/a&gt; · &lt;a href=&quot;https://www.meetup.com/it-IT/bologna-js-meetup/events/292424299/&quot;&gt;Bologna JS event page&lt;/a&gt; · &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-bologna-presents-come-e-perche-migliorare-le-prestazioni-web-consigli-pratici-per-il-2023/&quot;&gt;GDG event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;dev-romagna-imola-22-march-2023&quot; tabindex=&quot;-1&quot;&gt;Dev Romagna, Imola 🇮🇹 – &lt;time datetime=&quot;2023-03-22&quot;&gt;22 March 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#dev-romagna-imola-22-march-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/S9gCW7-iw_-648.webp 648w, https://andreaverlicchi.eu/img/S9gCW7-iw_-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/S9gCW7-iw_-648.jpeg 648w, https://andreaverlicchi.eu/img/S9gCW7-iw_-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;The location and the audience during the presentation of the Dev Romagna group&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/S9gCW7-iw_-648.jpeg&quot; width=&quot;1296&quot; height=&quot;972&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The location and the audience during the presentation of the Dev Romagna group&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Italian title: &amp;quot;Come e perché ($) migliorare le Prestazioni Web: consigli pratici per il 2023&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/it-IT/devromagna/events/291862771&quot;&gt;Dev Romagna event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;google-developer-group-turin-23-february-2023&quot; tabindex=&quot;-1&quot;&gt;Google Developer Group, Turin 🇮🇹 – &lt;time datetime=&quot;2023-02-23&quot;&gt;23 February 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#google-developer-group-turin-23-february-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/jEqhzoxgzj-648.webp 648w, https://andreaverlicchi.eu/img/jEqhzoxgzj-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/jEqhzoxgzj-648.jpeg 648w, https://andreaverlicchi.eu/img/jEqhzoxgzj-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi showing a slide: 1 second loading improvement can bring to -14% bounce rate, +13% conversion rate&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/jEqhzoxgzj-648.jpeg&quot; width=&quot;1296&quot; height=&quot;842&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;1 second loading time improvement can improve the website conversion rate and reduce the bounce rate&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/_Yiranwk6n-648.webp 648w, https://andreaverlicchi.eu/img/_Yiranwk6n-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://andreaverlicchi.eu/img/_Yiranwk6n-648.jpeg 648w, https://andreaverlicchi.eu/img/_Yiranwk6n-1296.jpeg 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi speaking in front of the GDG Torino audience in February 2023&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/_Yiranwk6n-648.jpeg&quot; width=&quot;1296&quot; height=&quot;446&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The beautiful audience in Turin&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Italian title: &amp;quot;Web Talks: from Design to Performance&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-torino-presents-web-talks-from-design-to-performance/&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;bologna-front-end-bologna-15-february-2023&quot; tabindex=&quot;-1&quot;&gt;Bologna front-end, Bologna 🇮🇹 – &lt;time datetime=&quot;2023-02-15&quot;&gt;15 February 2023&lt;/time&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-and-why-to-optimize-web-performance-practical-tips-2023/#bologna-front-end-bologna-15-february-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/9qzNBCbIdP-648.webp 648w, https://andreaverlicchi.eu/img/9qzNBCbIdP-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/9qzNBCbIdP-648.png 648w, https://andreaverlicchi.eu/img/9qzNBCbIdP-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi showing a self-introductory slide at the Bologna Front-end event in February 2023&quot; loading=&quot;lazy&quot; src=&quot;https://andreaverlicchi.eu/img/9qzNBCbIdP-648.png&quot; width=&quot;1296&quot; height=&quot;729&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;Me on stage at the Bologna Front-end event&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Italian title: &amp;quot;Web performance per tutti&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=eBBGYyKd7lg&quot;&gt;📺 Video&lt;/a&gt; · &lt;a href=&quot;https://www.meetup.com/it-IT/bologna-front-end/events/291336433/&quot;&gt;Event page&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>I&#39;m a Google Developer Expert for Web Performance</title>
		<link href="https://andreaverlicchi.eu/en/blog/google-developer-expert-gde-web-performance/"/>
		<updated>2022-12-06T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/google-developer-expert-gde-web-performance/</id>
		<content type="html">&lt;p&gt;In December 2023 I became a Google Developer Expert (GDE) for Web Performance. &lt;a href=&quot;https://developers.google.com/community/experts&quot;&gt;Google Developer Experts&lt;/a&gt; is a Google program to create a global network of professionals, influencers, and thought leaders, and enable them to share their knowledge with the developer community, like speaking at events, sharing best practices, and mentoring others.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/V0OR3WaxYk-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Experts&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/V0OR3WaxYk-648.png&quot; width=&quot;648&quot; height=&quot;367&quot;&gt;&lt;/picture&gt;
	&lt;figcaption&gt;The Google Develoeper Experts logo&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;By joining the GDE program, I joined a community of passionate technologists from around the world, allowing me to network with them and Google teams.&lt;/p&gt;
&lt;p&gt;In addition to getting &lt;a href=&quot;https://developers.google.com/community/experts/directory/profile/profile-andrea-verlicchi&quot;&gt;featured&lt;/a&gt; in the Google Developer Experts directory, I will get early access to products and web-performance-related news.&lt;/p&gt;
&lt;p&gt;Feel free to &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out&lt;/a&gt; if you want to talk about the program or web performance.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>aspect-ratio: A modern way to reserve space for images and async content in responsive design</title>
		<link href="https://andreaverlicchi.eu/en/blog/aspect-ratio-modern-reserve-space-lazy-images-async-content-responsive-design/"/>
		<updated>2022-11-19T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/aspect-ratio-modern-reserve-space-lazy-images-async-content-responsive-design/</id>
		<content type="html">&lt;p&gt;To avoid &lt;strong&gt;layout shifting&lt;/strong&gt; and optimize for the &lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift&lt;/a&gt; &lt;a href=&quot;https://web.dev/vitals/&quot;&gt;web vital&lt;/a&gt; in you web pages, you need to reserve space for any &lt;strong&gt;content that might be rendered later in time&lt;/strong&gt;. This is the case for images, videos and any asynchonously loaded content (e.g with AJAX calls). Here&#39;s a new way to do it.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/ks3J_BLdt9-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Different aspect ratios represented in squares and rectangles. 1/1, 4/3, 16/9, 2/3&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/ks3J_BLdt9-648.png&quot; width=&quot;648&quot; height=&quot;432&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-good-old-way&quot; tabindex=&quot;-1&quot;&gt;The good old way &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/aspect-ratio-modern-reserve-space-lazy-images-async-content-responsive-design/#the-good-old-way&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The traditional way to reserve space for images is to use the vertical padding trick.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image-wrapper&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;An image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.image-wrapper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;padding-bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 150%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/* 👆 image height / width * 100% */&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.image&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;the-modern-way-1-mapped-aspect-ratio&quot; tabindex=&quot;-1&quot;&gt;The modern way 1 - mapped &lt;code&gt;aspect-ratio&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/aspect-ratio-modern-reserve-space-lazy-images-async-content-responsive-design/#the-modern-way-1-mapped-aspect-ratio&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The modern and simpler way is to define a width / height aspect ratio implicitly by &lt;a href=&quot;https://twitter.com/addyosmani/status/1276779799198007301&quot;&gt;defining the width and height attributes on images and videos&lt;/a&gt;. This is called &amp;quot;mapped aspect-ratio&amp;quot;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;An image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;200&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;300&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;video&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A video&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;video.mp4&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1600&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;900&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;video&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Modern browser stylesheets will add a default
  aspect ratio based on the element&#39;s existing
  width and height attributes */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;img,
video&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;aspect-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; / &lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;height&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The good news is that either Chromium browsers (Chrome, Microsoft Egde, and Opera), Firefox and Safari (starting version 14) now support mapped &lt;code&gt;aspect-ratio&lt;/code&gt;! So the vast majority of browsers is covered, and Internet Explorer is slowly dying, while Microsoft Edge is ramping up.&lt;/p&gt;
&lt;p&gt;But there are some caveats when using JavaScript-powered lazy loading.&lt;/p&gt;
&lt;h3 id=&quot;demos&quot; tabindex=&quot;-1&quot;&gt;Demos &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/aspect-ratio-modern-reserve-space-lazy-images-async-content-responsive-design/#demos&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&#39;ve created a set of demos on Codepen to test mapped &lt;code&gt;aspect-ratio&lt;/code&gt; in different cases.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;th&gt;Works?&lt;/th&gt;
&lt;th&gt;Demo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Native lazy loading (no placeholders required)&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://codepen.io/verlok/pen/ExPwzGO&quot;&gt;Demo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Javascript lazy loading (no placeholders, no &lt;code&gt;display&lt;/code&gt; fix)&lt;/td&gt;
&lt;td&gt;🔴 No&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://codepen.io/verlok/pen/bGEYyZe&quot;&gt;Demo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Javascript lazy loading (no placeholders, with &lt;code&gt;display&lt;/code&gt; fix)&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://codepen.io/verlok/pen/RwKeoBX&quot;&gt;Demo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Javascript lazy loading (SVG placeholders, no &lt;code&gt;display&lt;/code&gt; fix)&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://codepen.io/verlok/pen/zYNmoxz&quot;&gt;Demo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;With &lt;code&gt;display&lt;/code&gt; fix I mean I needed to set the images &lt;code&gt;display&lt;/code&gt; property to &lt;code&gt;block&lt;/code&gt;, because leaving its value to the default one (&lt;code&gt;inline-block&lt;/code&gt;) didn&#39;t work out for Javascript lazy-loaded images.&lt;/p&gt;
&lt;p&gt;With &amp;quot;Works?&amp;quot; I mean if the browser reserved space for the images before they were loaded.
To check if it works yourself, use your browser&#39;s developer tools to disable the cache and emulate a &amp;quot;slow 3G&amp;quot; network speed.
You should see some space is reserved &lt;em&gt;before&lt;/em&gt; the images start loading, so the paragraph is rendered way below the images.&lt;/p&gt;
&lt;h2 id=&quot;the-modern-way-2-explicit-aspect-ratio&quot; tabindex=&quot;-1&quot;&gt;The modern way 2 - explicit &lt;code&gt;aspect-ratio&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/aspect-ratio-modern-reserve-space-lazy-images-async-content-responsive-design/#the-modern-way-2-explicit-aspect-ratio&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the future, you will also be able to explicitly set the aspect ratio in your CSS code using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio&quot;&gt;the aspect-ratio CSS rule&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;async&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Content is loading...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;aspect-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 16/9&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;s&gt;Unfortunately, this has currently (April 2021) supported only by Chromium browsers. We still don&#39;t know if and when this will be supported in future versions of Safari.&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;November 2021 update:&lt;/strong&gt; this is now &lt;a href=&quot;https://caniuse.com/mdn-css_properties_aspect-ratio&quot;&gt;supported&lt;/a&gt; by all latest versions of all browsers (except for Internet Explorer, but... well).&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/aspect-ratio-modern-reserve-space-lazy-images-async-content-responsive-design/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yay! It is possible to use mapped &lt;code&gt;aspect-ratio&lt;/code&gt; to reserve space for your lazily loaded content like images and videos today!&lt;/p&gt;
&lt;p&gt;Just set the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes to images and pick one of the following three ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use native lazy loading with &lt;code&gt;loading=lazy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use JavaScript lazy loading with no placeholders, but applying &lt;code&gt;display: block&lt;/code&gt; to the images&lt;/li&gt;
&lt;li&gt;Use JavaScript lazy loading with placeholders&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I can&#39;t wait to know how you reduced your pages&#39; &lt;a href=&quot;https://web.dev/cls&quot;&gt;CLS&lt;/a&gt; using these techniques.
Please &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out&lt;/a&gt; and let me know!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Against online streaming of local meetups.</title>
		<link href="https://andreaverlicchi.eu/en/blog/against-online-streaming-of-local-meetups/"/>
		<updated>2022-11-19T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/against-online-streaming-of-local-meetups/</id>
		<content type="html">&lt;p&gt;I like to take part to local meetup events. They are informative, fun, and socially engaging at the same time. Sometimes, the meetup organizers get asked to stream events online. It would be a cool feature, I guess, but if you ask me, it would do more harm than good the community. Let me explain why.&lt;/p&gt;
&lt;img alt=&quot;A sketch of a computer with persons having an online meeting&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/qZQpvuYqHk-648.webp&quot; width=&quot;648&quot; height=&quot;289&quot;&gt;
&lt;p&gt;Listening to the meetup topic in person, together with other people who share your interests, focused on the speaker and her/his slides, it&#39;s a type of experience. Watching to such an event at home, in front of a screen, alone, with distractions calling for your attention, far from where the event is happening, is a much weaker type of experience.&lt;/p&gt;
&lt;p&gt;You could easily find some blog posts or online tutorial about the same topic of the meetup event, most likely of a better quality. The real value of in-person meetup lies in socialising, networking, in the exchange of ideas that happens before and after the talk, and if you want, at the pizza place afterwards.&lt;/p&gt;
&lt;p&gt;Furthermore, the fact that an event would also be streamed online, weakens the event in person. One might think “Hey, who is making me go to the city, I can see it in live streaming. Then when it&#39;s time &amp;quot;Hey, who is making me watch it live, I&#39;ll see the recording later&amp;quot;. Then &amp;quot;Ah, why would I watch the recording, I&#39;ll watch an online tutorial&amp;quot;. Maybe.&lt;/p&gt;
&lt;p&gt;If we talk about conferences, however, there are some differences. Conferences can be online, but I think they have to be online or offline, not both. Online conferences may have a larger audience, even worldwide, and may reduce costs for attendees, they are more accessible to those with mobility impairments, but in my opinion in-person conferences are the best, for the same reasons: being together with people sharing your interests, exchanging ideas, etc.&lt;/p&gt;
&lt;p&gt;And you, what do you think? Feel free to &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out&lt;/a&gt; and let me know!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Do we still need lazy loading libraries and `data-src`?</title>
		<link href="https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/"/>
		<updated>2022-11-13T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/</id>
		<content type="html">&lt;p&gt;Back in the day, when browser support for &lt;a href=&quot;https://web.dev/browser-level-image-lazy-loading/&quot;&gt;native lazy loading&lt;/a&gt; wasn’t widespread, the best practice was to use &lt;code&gt;data-src&lt;/code&gt; attributes and a JavaScript library like my &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; to load images as they entered the viewport. Is this still best practice today?&lt;/p&gt;
&lt;img alt=&quot;Do we still need lazy load libraries and data-src in 2022&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/fEKUhQxFxu-648.webp&quot; width=&quot;648&quot; height=&quot;324&quot;&gt;
&lt;h2 id=&quot;what-is-lazy-loading&quot; tabindex=&quot;-1&quot;&gt;What is lazy loading? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#what-is-lazy-loading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Lazy loading images&lt;/strong&gt; is a technique to &lt;strong&gt;defer the loading of &lt;em&gt;below-the-fold&lt;/em&gt; images&lt;/strong&gt; until they are about to enter the viewport (the visible portion of the page). This technique saves bandwidth, reduces CDN costs, lowers the website&#39;s carbon footprint, and improves page rendering time, particularly the &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;javascript-driven-image-lazy-loading&quot; tabindex=&quot;-1&quot;&gt;JavaScript-driven image lazy loading &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#javascript-driven-image-lazy-loading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Traditionally, lazy loading images involved replacing the &lt;code&gt;src&lt;/code&gt; attribute with a &lt;code&gt;data-src&lt;/code&gt; attribute and using JavaScript to detect when the images are nearing the viewport, then copy the &lt;code&gt;data&lt;/code&gt; attributes into the proper ones, triggering their deferred loading.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;turtle.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Lazy turtle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;native-lazy-loading&quot; tabindex=&quot;-1&quot;&gt;Native lazy loading &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#native-lazy-loading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With native lazy loading, &lt;abbr title=&quot;also known as&quot;&gt;AKA&lt;/abbr&gt; &lt;a href=&quot;https://web.dev/browser-level-image-lazy-loading/&quot;&gt;browser-level lazy loading&lt;/a&gt;, simply add the &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt; attribute to the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;turtle.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Lazy turtle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works on &lt;a href=&quot;https://caniuse.com/loading-lazy-attr&quot;&gt;all modern browsers&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;do-we-still-need-javascript-driven-lazy-loading&quot; tabindex=&quot;-1&quot;&gt;Do we still need JavaScript-driven lazy loading? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#do-we-still-need-javascript-driven-lazy-loading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;No, unless you want greater control over the lazy loading process.&lt;/p&gt;
&lt;p&gt;Let&#39;s see what are the cases for using JavaScript-driven lazy loading, instead of just using &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;1-supporting-users-on-slow-or-faulty-connections&quot; tabindex=&quot;-1&quot;&gt;1. Supporting users on slow or faulty connections &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#1-supporting-users-on-slow-or-faulty-connections&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JavaScript libraries like &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; can cancel the download of images that leave the viewport and retry downloads if interrupted, enhancing the user experience on slow connections.&lt;/p&gt;
&lt;p&gt;A use case for that is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pages with many images +&lt;/li&gt;
&lt;li&gt;users on slow connections +&lt;/li&gt;
&lt;li&gt;fast scroll down&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Native lazy loading makes browsers download lazy images from top to bottom, resulting in a delay to show the bottom images.&lt;/p&gt;
&lt;p&gt;Javascript libraries like &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; will cancel the download of images that exit the viewport, keeping users&#39; bandwidth focused on the images currently in the viewport.&lt;/p&gt;
&lt;p&gt;Another use case is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;images downloading&lt;/li&gt;
&lt;li&gt;network connection interrupted&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; will retry downloading those images when the network connection is restored.&lt;/p&gt;
&lt;p&gt;You can try these features on any of the &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/#-demos&quot;&gt;vanilla-lazyload demos&lt;/a&gt;, like the &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/demos/image_basic.html&quot;&gt;basic case demo&lt;/a&gt;, and throttling or disabling your connection speed in the developer tools of your browser.&lt;/p&gt;
&lt;h3 id=&quot;2-advanced-callbacks-or-css-classes&quot; tabindex=&quot;-1&quot;&gt;2. Advanced callbacks or CSS classes &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#2-advanced-callbacks-or-css-classes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JavaScript-driven lazy loading provides callbacks and CSS classes for various events (start loading, finish loading, error, enter viewport, exit viewport, etc.), allowing for enhanced visual effects and monitoring.&lt;/p&gt;
&lt;p&gt;Those callbacks and CSS classes can be very helpful to create visual effects on your page.&lt;/p&gt;
&lt;p&gt;Find more about callbacks and classes in &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/#-api&quot;&gt;vanilla-lazyload API&lt;/a&gt; / &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/#options&quot;&gt;options&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;3-optimizing-web-performance-specifically-largest-contentful-paint&quot; tabindex=&quot;-1&quot;&gt;3. Optimizing web performance, specifically Largest Contentful Paint &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#3-optimizing-web-performance-specifically-largest-contentful-paint&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JavaScript-driven lazy loading offers more control over which images are downloaded, helping to optimize the Largest Contentful Paint (LCP).&lt;/p&gt;
&lt;p&gt;With native lazy loading, you don&#39;t have control over what images get downloaded from the browser.&lt;/p&gt;
&lt;p&gt;The use case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;some images are below-the-fold but not far off&lt;/li&gt;
&lt;li&gt;some images barely appear in the visible portion of the page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Native lazy loading would start downloading those images, which will share the bandwidth with the download of your LCP image, while you want to download the latter with the highest priority.&lt;/p&gt;
&lt;p&gt;JavaScript-driven lazy load like vanilla-lazyload provide &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/#-api&quot;&gt;APIs&lt;/a&gt; and &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/#options&quot;&gt;options&lt;/a&gt; to fine-grain control how far off-the-viewport images should be to start downloading.&lt;/p&gt;
&lt;h3 id=&quot;4-lazy-loading-other-assets&quot; tabindex=&quot;-1&quot;&gt;4. Lazy loading other assets &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#4-lazy-loading-other-assets&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For lazy loading background images, videos, animated SVGs, and more, a JavaScript library like &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; is still required.&lt;/p&gt;
&lt;h2 id=&quot;find-out-more&quot; tabindex=&quot;-1&quot;&gt;Find out more &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/do-we-still-need-lazy-loading-libraries-data-src/#find-out-more&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Check the &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/&quot;&gt;vanilla-lazyload documentation&lt;/a&gt; or my blog post &lt;a href=&quot;https://andreaverlicchi.eu/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/&quot;&gt;lazy load responsive images in 2020&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk: Get speedy with responsive images - LazyLoad Conference 2022</title>
		<link href="https://andreaverlicchi.eu/en/blog/lazyload-conference-talk-automating-responsive-images-automator/"/>
		<updated>2022-06-24T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/lazyload-conference-talk-automating-responsive-images-automator/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/-3gSKqUCg4-648.webp 648w, https://andreaverlicchi.eu/img/-3gSKqUCg4-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/-3gSKqUCg4-648.png 648w, https://andreaverlicchi.eu/img/-3gSKqUCg4-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi sitting in his living room, during the talk&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/-3gSKqUCg4-648.png&quot; width=&quot;1296&quot; height=&quot;728&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;This is a frame of the video, before I dove into the technical parts&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On June 24th 2022, I spoke about &lt;strong&gt;responsive images optimisation 4.0&lt;/strong&gt; at the &lt;a href=&quot;https://webdirections.org/lazyload/&quot;&gt;LazyLoad conference 2022&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The talk was about how to improve performance on your website by automating responsive images, with a data-driven approach. Here&#39;s the video of my talk.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/vuWH34f6uds?si=Za5a4gWUefluQ7-B&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;The tool mentioned in the the talk is &lt;a href=&quot;https://github.com/verlok/responsive-images-automator&quot;&gt;responsive-images-automator&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Talk: Images optimisation 4.0, automate your work with a user-centric approach - CSS Day 2022</title>
		<link href="https://andreaverlicchi.eu/en/blog/css-day-2022-talk-automating-responsive-images-automator-ottimizzazione-immagini-4-0/"/>
		<updated>2022-04-01T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/css-day-2022-talk-automating-responsive-images-automator-ottimizzazione-immagini-4-0/</id>
		<content type="html">&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/1r7VhO8cDn-648.webp 648w, https://andreaverlicchi.eu/img/1r7VhO8cDn-1296.webp 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;source type=&quot;image/png&quot; srcset=&quot;https://andreaverlicchi.eu/img/1r7VhO8cDn-648.png 648w, https://andreaverlicchi.eu/img/1r7VhO8cDn-1296.png 1296w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Andrea Verlicchi on stage at CSS Day 2022, Faenza, April 1st 2022&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/1r7VhO8cDn-648.png&quot; width=&quot;1296&quot; height=&quot;726&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;Me on stage at CSS Day 2022, Faenza&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On April 1st 2022 I spoke about &lt;strong&gt;responsive images optimisation 4.0&lt;/strong&gt; at the &lt;a href=&quot;https://2022.cssday.it&quot;&gt;CSS Day 2022 Conference&lt;/a&gt; in Faenza, Italy. This talk – in Italian language – is on how to become more productive by automating responsive images. Here&#39;s the video of my talk. It&#39;s in Italian language only.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/8D4skk17BGI?si=lSA2B2PT_dEfXY-l&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 9&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;The tool the talk was about is &lt;a href=&quot;https://github.com/verlok/responsive-images-automator&quot;&gt;responsive-images-automator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The talk was rated very positively! &lt;a href=&quot;https://joind.in/event/cssday-2022/-ottimizzazione-immagini-40-a-data-driven--test-driven-approach&quot;&gt;Read feedback on joind.in&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Find below the slides of this talk.&lt;/p&gt;
&lt;iframe loading=&quot;lazy&quot; src=&quot;https://www.slideshare.net/slideshow/embed_code/key/f0UQZznjoJ5Yvs?hostedIn=slideshare&amp;page=upload&quot; width=&quot;100%&quot; height=&quot;autp&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 16 / 11&quot;&gt;&lt;/iframe&gt;
</content>
	</entry>
	
	<entry>
		<title>How to integrate git in Mac OS Terminal (shell)</title>
		<link href="https://andreaverlicchi.eu/en/blog/how-integrate-git-autocomplete-mac-shell-terminal-bash-zsh/"/>
		<updated>2022-03-11T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/how-integrate-git-autocomplete-mac-shell-terminal-bash-zsh/</id>
		<content type="html">&lt;p&gt;Now that &lt;code&gt;zsh&lt;/code&gt; is the default shell on Mac OS terminal, you might want to setup you new Mac or VS Code terminal to have a smart integration with &lt;code&gt;git&lt;/code&gt;, something similar to &lt;a href=&quot;https://gitforwindows.org/&quot;&gt;git bash&lt;/a&gt; for Windows.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/fTQn3en4qR-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Mac OS X Terminal app | blog-11ty git:(main) * git status | On branch main | Your branch is ahead of &#39;origin/main&#39; by 1 commit. (use &amp;quot;git push&amp;quot; to publish your local commits) | Changes not staged for commit: | (use &amp;quot;git add ‹file&gt;...&amp;quot; to update what will be committed) | (use &amp;quot;git restore ‹file&gt;...&amp;quot; to discard changes in working directory) | modified: content/blog/how-integrate-git-autocomplete-mac-shell-terminal-bash-zsh/index.md | no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/fTQn3en4qR-648.png&quot; width=&quot;648&quot; height=&quot;403&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;Mac OS Terminal with git integration&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After searching around for a while and finding tools to integrate with &lt;code&gt;bash&lt;/code&gt;, I finally found &lt;a href=&quot;https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh&quot;&gt;this article&lt;/a&gt; that offers an explanation on how to integrate &lt;code&gt;git&lt;/code&gt; with &lt;code&gt;zsh&lt;/code&gt; in Mac OS Terminal (or shell).&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;zsh&lt;/code&gt; ships with a framework for getting information from version control systems, called &lt;a href=&quot;http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#Version-Control-Information&quot;&gt;&lt;code&gt;vcs_info&lt;/code&gt;&lt;/a&gt;, you can include the branch name in the prompt on the right side, add these lines to your ~/.zshrc file:&lt;/p&gt;
&lt;pre class=&quot;language-dot&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-dot&quot;&gt;&lt;span class=&quot;token node&quot;&gt;autoload&lt;/span&gt; -Uz &lt;span class=&quot;token node&quot;&gt;vcs_info&lt;/span&gt;
&lt;span class=&quot;token node&quot;&gt;precmd_vcs_info&lt;/span&gt;() &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token node&quot;&gt;vcs_info&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token node&quot;&gt;precmd_functions&lt;/span&gt;+&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;( &lt;span class=&quot;token node&quot;&gt;precmd_vcs_info&lt;/span&gt; )
&lt;span class=&quot;token node&quot;&gt;setopt&lt;/span&gt; &lt;span class=&quot;token node&quot;&gt;prompt_subst&lt;/span&gt;
&lt;span class=&quot;token attr-name&quot;&gt;RPROMPT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&#39;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token node&quot;&gt;vcs_info_msg_0_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&#39;
&lt;span class=&quot;token comment&quot;&gt;# PROMPT=&#39;${vcs_info_msg_0_}%# &#39;&lt;/span&gt;
&lt;span class=&quot;token node&quot;&gt;zstyle&lt;/span&gt; &#39;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token node&quot;&gt;vcs_info&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token node&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;*&#39; &lt;span class=&quot;token node&quot;&gt;formats&lt;/span&gt; &#39;%&lt;span class=&quot;token node&quot;&gt;b&lt;/span&gt;&#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zsh is powerful enough that there are entire frameworks dedicated to making it better. One of them is called &lt;a href=&quot;https://github.com/robbyrussell/oh-my-zsh&quot;&gt;&lt;code&gt;oh-my-zsh&lt;/code&gt;&lt;/a&gt;. &lt;code&gt;oh-my-zsh&lt;/code&gt;’s plugin system comes with powerful git tab-completion, and it has a variety of prompt &amp;quot;themes&amp;quot;, many of which display version-control data.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;oh-my-zsh&lt;/code&gt; running fhe following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enjoy your new &lt;code&gt;zsh&lt;/code&gt; terminal integrated with &lt;code&gt;git&lt;/code&gt; commands!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>An elegant technique to lazyload images in Swiper, and lazily create Swiper instances</title>
		<link href="https://andreaverlicchi.eu/en/blog/lazyload-swiper-images-instances/"/>
		<updated>2021-10-27T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/lazyload-swiper-images-instances/</id>
		<content type="html">&lt;p&gt;Say you have multiple carousels in a page, each one containing multiple images, and you want to download only the images that are inside the visible portion of the page, and maybe save some CPU time by lazily create the carousel instances. I think I’ve found a valuable and elegant technique to do so.&lt;/p&gt;
&lt;p&gt;The following technique is about lazy loading images inside an instance of &lt;a href=&quot;https://swiperjs.com/&quot;&gt;Swiper JS&lt;/a&gt;, and also lazily creating the Swiper instances below-the-fold, using Swiper with &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The HTML code of the first carousel sets a couple of images as eagerly loaded so browsers will prioritize their downloading, and it leaves all the rest to lazy loading.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper swiper--eager&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-wrapper&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Eagerly loaded images --&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S01E01&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S01E01 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S01E02&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S01E02 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Lazy loaded images --&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S01E03&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S01E03 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S01E04&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S01E04 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S01E05&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S01E05 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-button-prev&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-button-next&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the second carousel on, all the images are to be lazily loaded.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper swiper--lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiperLazy1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-wrapper&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- All lazy loaded images --&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S02E01&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S02E01 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S02E02&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S02E02 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S02E03&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S02E03 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S02E04&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S02E04 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-slide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=S02E05&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/440x560?text=S02E05 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
				&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-button-prev&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;swiper-button-next&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here goes the JavaScript code that makes the magic.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; swiperOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;slidesPerView&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;navigation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;nextEl&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.swiper-button-next&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;prevEl&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.swiper-button-prev&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// LazyLoad swiper images after swiper initialization&lt;/span&gt;
		&lt;span class=&quot;token function-variable function&quot;&gt;afterInit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;swiper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token literal-property property&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; swiper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token literal-property property&quot;&gt;cancel_on_exit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Initialize the first swiper right away&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; eagerSwiper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Swiper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.swiper--eager&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; swiperOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Initialize all other swipers as they enter the viewport&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;elements_selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.swiper--lazy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;unobserve_entered&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;callback_enter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;swiperElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Swiper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; swiperElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; swiperOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I tested it by emulating a &amp;quot;slow 3G&amp;quot; connection, and I like the waterfall of network calls and the optimal value of the Largest Contentful Paint.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/demos/swiper.html&quot;&gt;Try it live here&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>vanilla-lazyload vs lazysizes</title>
		<link href="https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/"/>
		<updated>2021-09-26T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/</id>
		<content type="html">&lt;p&gt;As the author of vanilla-lazyload, it&#39;s not the first time I get asked the question: &lt;q&gt;What are the differences between vanilla-lazyload and lazysizes?&lt;/q&gt; This blog post is the answer to that question.&lt;/p&gt;
&lt;img alt=&quot;vanilla-lazyload vs lazysizes&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/tRjMg3L7n7-648.webp&quot; width=&quot;648&quot; height=&quot;432&quot;&gt;
&lt;h2 id=&quot;what-are-vanilla-lazyload-and-lazy-sizes&quot; tabindex=&quot;-1&quot;&gt;What are vanilla-lazyload and lazy sizes? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#what-are-vanilla-lazyload-and-lazy-sizes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/&quot;&gt;vanilla-lazyload&lt;/a&gt; and &lt;a href=&quot;https://github.com/afarkas/lazysizes/&quot;&gt;lazysizes&lt;/a&gt; are two popular Javascript libraries to &lt;a href=&quot;https://web.dev/lazy-loading/&quot;&gt;lazyload&lt;/a&gt; images and other DOM elements, meaning &lt;strong&gt;load them only when they enter the visible portion of the web page&lt;/strong&gt; (the browser viewport), or a little bit earlier than they do.&lt;/p&gt;
&lt;p&gt;Using one of them is very important to improve the &lt;strong&gt;rendering time&lt;/strong&gt; of your website by delaying the loading of all non-critical content to later, in order to get better &lt;a href=&quot;https://web.dev/cwv&quot;&gt;Core Web Vitals&lt;/a&gt; and particularly to reduce the &lt;a href=&quot;https://web.dev/lcp&quot;&gt;Largest Contentful Paint&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So what are the &lt;strong&gt;differences between vanilla-lazyload and lazysizes&lt;/strong&gt;? What follows is a detailed comparison of the two.&lt;/p&gt;
&lt;h2 id=&quot;vanilla-lazyload-and-lazysizes-compared&quot; tabindex=&quot;-1&quot;&gt;vanilla-lazyload and lazysizes compared &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#vanilla-lazyload-and-lazysizes-compared&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Find the main features of vanilla-lazyload compared to lazysizes&#39; in the table below.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;It&lt;/th&gt;
&lt;th&gt;vanilla-lazyload&lt;/th&gt;
&lt;th&gt;lazysizes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Is lightweight (source: &lt;a href=&quot;https://bundlephobia.com/&quot;&gt;bundlephobia&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;✔ (2.8 kB)&lt;/td&gt;
&lt;td&gt;✔ (3.4 kB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is extendable&lt;/td&gt;
&lt;td&gt;✔ (via API)&lt;/td&gt;
&lt;td&gt;✔ (via plugins)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is SEO friendly&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optimizes performance by cancelling downloads of images that already exited the viewport&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retries loading after network connection went off and on again&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supports conditional usage of native lazyloading&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works with your DOM, your own classes, and data-attributes&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can lazyload responsive images&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...and automatically calculate the value of the &lt;code&gt;sizes&lt;/code&gt; attribute&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can lazyload iframes&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can lazyload videos&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can lazyload background images&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can lazily execute code when given elements enter the viewport&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can restore DOM to its original state&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;table-rows-explained&quot; tabindex=&quot;-1&quot;&gt;Table rows explained &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#table-rows-explained&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;is-extendable&quot; tabindex=&quot;-1&quot;&gt;Is extendable &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#is-extendable&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both vanilla-lazyload and lazysizes are extendable, see &lt;a href=&quot;https://www.github.com/verlok/vanilla-lazyload#-api&quot;&gt;vanilla-lazyload API&lt;/a&gt; and &lt;a href=&quot;https://github.com/aFarkas/lazysizes/tree/gh-pages/plugins&quot;&gt;lazysizes plugins&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;is-seo-friendly&quot; tabindex=&quot;-1&quot;&gt;Is SEO friendly &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#is-seo-friendly&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both scripts &lt;strong&gt;don&#39;t hide images/assets from search engines&lt;/strong&gt;. No matter what markup pattern you use. Search engines don&#39;t scroll/interact with your website. These scripts detect whether or not the user agent is capable to scroll and if not, they reveal all images instantly.&lt;/p&gt;
&lt;h3 id=&quot;optimizes-performance-by-cancelling-downloads-of-images-that-already-exited-the-viewport&quot; tabindex=&quot;-1&quot;&gt;Optimizes performance by cancelling downloads of images that already exited the viewport &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#optimizes-performance-by-cancelling-downloads-of-images-that-already-exited-the-viewport&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If your mobile users are on slow connections and they scroll down fast, vanilla-lazyload cancels the download of images that are still loading but already exited the viewport. Although if for some reason you don&#39;t want this to happen, this feature can be turned off.&lt;/p&gt;
&lt;h3 id=&quot;retries-loading-after-network-connection-went-off-and-on&quot; tabindex=&quot;-1&quot;&gt;Retries loading after network connection went off and on &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#retries-loading-after-network-connection-went-off-and-on&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If your mobile users are on flaky connections and go offline and back online, vanilla-lazyload retries downloading the images that errored.&lt;/p&gt;
&lt;h3 id=&quot;supports-conditional-usage-of-native-lazyloading&quot; tabindex=&quot;-1&quot;&gt;Supports conditional usage of native lazyloading &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#supports-conditional-usage-of-native-lazyloading&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If your users are on a browser supporting native lazyloading and you want to use it, with vanilla-lazyload you can conditionally activate it by setting the &lt;code&gt;use_native&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt;. Find here &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload#mixed-native-and-js-based-lazy-loading&quot;&gt;more information&lt;/a&gt; and the &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/demos/native_lazyload_conditional.html&quot;&gt;conditional native lazyload demo&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;works-with-your-dom-your-own-classes-and-data-attributes&quot; tabindex=&quot;-1&quot;&gt;Works with your DOM, your own classes and data-attributes &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#works-with-your-dom-your-own-classes-and-data-attributes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both scripts work by default with the &lt;code&gt;data-src&lt;/code&gt; attribute and the &lt;code&gt;lazy&lt;/code&gt; class in your DOM, but on vanilla-lazyload you can change it, e.g. to &lt;code&gt;data-origin&lt;/code&gt;, if you want to migrate from other lazy loading scripts to vanilla-lazyload without changing your HTML markup.&lt;/p&gt;
&lt;h3 id=&quot;can-lazyload-responsive-images&quot; tabindex=&quot;-1&quot;&gt;Can lazyload responsive images &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#can-lazyload-responsive-images&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both vanilla-lazyload and lazysizes can lazyload responsive images by all kinds, the simple &lt;code&gt;img&lt;/code&gt; tag and the &lt;code&gt;picture&lt;/code&gt; tag with multiple &lt;code&gt;source&lt;/code&gt; tags.&lt;/p&gt;
&lt;p&gt;For more information, check out &lt;a href=&quot;https://andreaverlicchi.eu/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/&quot;&gt;lazy load responsive images in 2020&lt;/a&gt; by yours truly.&lt;/p&gt;
&lt;h3 id=&quot;and-automatically-calculate-the-value-of-the-sizes-attribute&quot; tabindex=&quot;-1&quot;&gt;...and automatically calculate the value of the &lt;code&gt;sizes&lt;/code&gt; attribute &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#and-automatically-calculate-the-value-of-the-sizes-attribute&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The lazysizes script has a function that can spare you the &amp;quot;fatigue&amp;quot; of writing the value of the &lt;code&gt;sizes&lt;/code&gt; attribute in your HTML markup. By placing a &lt;code&gt;data-sizes=&amp;quot;auto&amp;quot;&lt;/code&gt; in your images markup, it can derive its value via Javascript from your CSS.&lt;/p&gt;
&lt;p&gt;This is a missing feature vanilla-lazyload for a reason. To make browsers display your website&#39;s content as fast as possible, you will have to &lt;strong&gt;mix lazy loading and eager loading&lt;/strong&gt; (eager being the opposite of lazy). The best practice here is to eagerly load images above-the-fold and lazy loading the ones below-the-fold. In the eagerly loaded images you will have to put a sensible value of the &lt;code&gt;sizes&lt;/code&gt; attribute. This means that you will have to calculate that value anyway and, once you did that, what is the use of calculating its value using JavaScript? You can use the value you calculated both for your eager images and your lazy ones.&lt;/p&gt;
&lt;h3 id=&quot;can-lazyload-iframes&quot; tabindex=&quot;-1&quot;&gt;Can lazyload iframes &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#can-lazyload-iframes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both vanilla-lazyload and lazysizes can lazyload the &lt;code&gt;iframe&lt;/code&gt; tag.&lt;/p&gt;
&lt;h3 id=&quot;can-lazyload-videos&quot; tabindex=&quot;-1&quot;&gt;Can lazyload videos &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#can-lazyload-videos&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Only vanilla-lazyload can lazyload the &lt;code&gt;video&lt;/code&gt; tag, even with multiple &lt;code&gt;source&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload#lazy-video&quot;&gt;lazy video&lt;/a&gt; in vanilla-lazyload documentation for more.&lt;/p&gt;
&lt;h3 id=&quot;can-lazyload-background-images&quot; tabindex=&quot;-1&quot;&gt;Can lazyload background images &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#can-lazyload-background-images&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Only vanilla-lazyload can lazyload background images, even multiple background images. It also has a way of supporting HiDPI displays such as Retina and Super Retina displays.&lt;/p&gt;
&lt;p&gt;Check &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload#lazy-background-image&quot;&gt;lazy background images&lt;/a&gt; in vanilla-lazyload documentation for more.&lt;/p&gt;
&lt;h3 id=&quot;can-lazily-execute-code-when-given-elements-enter-the-viewport&quot; tabindex=&quot;-1&quot;&gt;Can lazily execute code when given elements enter the viewport &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#can-lazily-execute-code-when-given-elements-enter-the-viewport&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Only on vanilla-lazyload you can execute code when given elements enter the visible portion of the page.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://www.github.com/verlok/vanilla-lazyload#lazy-functions&quot;&gt;lazy functions&lt;/a&gt; section in vanilla-lazyload documentation for more.&lt;/p&gt;
&lt;h3 id=&quot;can-restore-the-dom-to-its-original-state&quot; tabindex=&quot;-1&quot;&gt;Can restore the DOM to its original state &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#can-restore-the-dom-to-its-original-state&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes you need to clean up your DOM before unloading it and soft-navigating to another page, e.g. when using TurboLinks.&lt;/p&gt;
&lt;p&gt;vanilla-lazyload allows you to restore all DOM it manipulated to its original state by calling the &lt;code&gt;restoreAll()&lt;/code&gt; method.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/vanilla-lazyload-vs-lazysizes/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;vanilla-lazyload has more features you can use to lazyload images, background images, videos and iframes, it&#39;s optimised for slow connections, it automatically retries loading images after a network down, supports conditional native lazy loading, can execute code lazily, and restore your DOM to its original state.&lt;/p&gt;
&lt;p&gt;On the other hand, lazysizes is extendable and it has the ability to automatically calculate your images &lt;code&gt;sizes&lt;/code&gt; attribute if you don&#39;t want to.&lt;/p&gt;
&lt;p&gt;Links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload github page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/afarkas/lazysizes/&quot;&gt;lazysizes github page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>Quicklink case study: faster pages, increased page views</title>
		<link href="https://andreaverlicchi.eu/en/blog/quicklink-case-study-faster-pages-increased-page-views/"/>
		<updated>2021-06-18T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/quicklink-case-study-faster-pages-increased-page-views/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/GoogleChromeLabs/quicklink&quot;&gt;QuickLink&lt;/a&gt; is a lightweight library created by Addy Osmani (Google) that prefetches pages linked to the current page, as the links to those pages enter the visible portion of the page (viewport).&lt;/p&gt;
&lt;img alt=&quot;The logo of Quicklink&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/vt2DvehcqM-648.webp&quot; width=&quot;648&quot; height=&quot;243&quot;&gt;
&lt;p&gt;We used Quicklink on some of our ecommerce websites to improve the rendering time of our product detail pages (PDPs), with good results both on performance and business KPIs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/ynap-tech/quicklink-case-study-faster-pages-increased-page-views-1e829dbaa10c&quot;&gt;Continue reading on Medium&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>A clever way to serve WebP images to modern browsers and JPG to IE</title>
		<link href="https://andreaverlicchi.eu/en/blog/clever-way-serve-webp-modern-browsers-jpg-internet-explorer/"/>
		<updated>2020-11-29T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/clever-way-serve-webp-modern-browsers-jpg-internet-explorer/</id>
		<content type="html">&lt;p&gt;Before the day Safari started to support WebP images, we were forced to use the &lt;code&gt;picture&lt;/code&gt; tag to serve WebP images to browsers supporting it. Today all modern browsers support WebP, so there&#39;s probably a clever way to do that using a single tag: &lt;code&gt;img&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-we-did-it-before&quot; tabindex=&quot;-1&quot;&gt;How we did it before &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/clever-way-serve-webp-modern-browsers-jpg-internet-explorer/#how-we-did-it-before&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The old way to do that was using a &lt;code&gt;picture&lt;/code&gt; tag containing the regular &lt;code&gt;img&lt;/code&gt; tag with both &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;srcset&lt;/code&gt; attributes for browsers not supporting WebP, and a sibling &lt;code&gt;source&lt;/code&gt; tag - marked with the &lt;code&gt;type=&amp;quot;image/webp&amp;quot;&lt;/code&gt; - containing the &lt;code&gt;srcset&lt;/code&gt; for browsers accepting the WebP image format.&lt;/p&gt;
&lt;p&gt;Long story short, this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/webp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
            {url-standard}.webp 1x,
            {url-retina}.webp   2x
        &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Old way&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{url-standard}.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
            {url-standard}.jpg 1x,
            {url-retina}.jpg   2x
        &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;but-safari-is-more-modern-now&quot; tabindex=&quot;-1&quot;&gt;But Safari is more modern now &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/clever-way-serve-webp-modern-browsers-jpg-internet-explorer/#but-safari-is-more-modern-now&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that all modern browsers support WebP, we can assume that all browsers that support the &lt;code&gt;srcset&lt;/code&gt; attribute also support WebP. So we can get rid of the &lt;code&gt;picture&lt;/code&gt; tag and use a single &lt;code&gt;img&lt;/code&gt; tag.&lt;/p&gt;
&lt;p&gt;Like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;New, clever way&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{url-standard}.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
        {url-standard}.webp 1x,
        {url-retina}.webp   2x
    &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Legacy browsers fallback to the &lt;code&gt;src&lt;/code&gt; attribute, and they get the Jpg image. Simple as that.&lt;/p&gt;
&lt;h2 id=&quot;advantages&quot; tabindex=&quot;-1&quot;&gt;Advantages &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/clever-way-serve-webp-modern-browsers-jpg-internet-explorer/#advantages&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first, more obvious advantage is you need to write and maintain less HTML markup.&lt;/p&gt;
&lt;p&gt;A second advantage you could have is if you were using an image CDN to automatically serve the correct image format depending on the browser requesting it. If you were, you can probably get rid of that and save some time and money.&lt;/p&gt;
&lt;h2 id=&quot;compatibility&quot; tabindex=&quot;-1&quot;&gt;Compatibility &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/clever-way-serve-webp-modern-browsers-jpg-internet-explorer/#compatibility&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you&#39;re supporting versions of iOS older than 14, you probably want to continue using the &lt;code&gt;picture&lt;/code&gt; tag to to so. This depends on the audience you&#39;re targeting. Find more about your audience using Google Analytics data.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to cap image fidelity to 2x and save 45% image weight on high-end mobile phones</title>
		<link href="https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/"/>
		<updated>2020-11-11T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/</id>
		<content type="html">&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/KPZpoNl1-w-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Capping image fidelity to 2x&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/KPZpoNl1-w-648.jpeg&quot; width=&quot;648&quot; height=&quot;432&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2 id=&quot;images-x-screen-densities&quot; tabindex=&quot;-1&quot;&gt;Images x screen densities &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#images-x-screen-densities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;HiDPI displays are perfect when having to render vectors like fonts and SVG images, but when it comes to images, if we don’t provide a specific image for HiDPI displays, our regular image gets stretched to cover all the additional pixels. And stretched images don’t look good.&lt;/p&gt;
&lt;p&gt;So the first thing we started doing was to provide both a standard image and an image optimized for Retina displays, using the &lt;code&gt;srcset&lt;/code&gt; attribute and the &lt;code&gt;x&lt;/code&gt; descriptor. Like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_1x.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_1x.jpg 1x, batman_2x.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Batman, Super-man and Wonder Woman&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;720&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That &lt;code&gt;x&lt;/code&gt; descriptor in the &lt;code&gt;srcset&lt;/code&gt; attribute is to match sources to screen densities. &lt;code&gt;1x&lt;/code&gt; means “this is the image for regular screens”, &lt;code&gt;2x&lt;/code&gt; means “this is the image for HiDPI / Retina displays”. Depending on the device’s screen, browsers will pick the corresponding source.&lt;/p&gt;
&lt;h2 id=&quot;responsive-images&quot; tabindex=&quot;-1&quot;&gt;Responsive images &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#responsive-images&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images&quot;&gt;Responsive images&lt;/a&gt; is an HTML specification that allows us to serve the correct image size to users, depending on the space the image occupies on the user’s screen, and taking the device pixel ratio into account.&lt;/p&gt;
&lt;p&gt;The simplest way to code responsive images is to list all the image sizes we have in a &lt;code&gt;srcset&lt;/code&gt; attribute, using the &lt;code&gt;w&lt;/code&gt; descriptor, and tell the browser how big is our image, using the &lt;code&gt;sizes&lt;/code&gt; attribute. Browsers will do the math and will download the most appropriate image.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_1280w.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_1280w.jpg 1280w, batman_1024w.jpg 1024w, batman_768w.jpg 768w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Batman, Super-man and Wonder Woman&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;100vw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Additionally, when the size of your images changes depending on media queries, we can add the same media queries in the &lt;code&gt;sizes&lt;/code&gt; attribute.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_1280w.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
		batman_1440w.jpg 1440w,
		batman_1280w.jpg 1280w,
		batman_1024w.jpg 1024w,
		batman_768w.jpg   768w
	&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Batman, Super-man and Wonder Woman&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 640px) 50vw, 100vw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you feel confused, I recommend you to read &lt;a href=&quot;https://ericportis.com/posts/2014/srcset-sizes/&quot;&gt;Srcset and Sizes from Eric Portis&lt;/a&gt;. That article lighted my way when I was starting to play around with responsive images.&lt;/p&gt;
&lt;h2 id=&quot;devices-with-3x-displays&quot; tabindex=&quot;-1&quot;&gt;Devices with 3x displays &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#devices-with-3x-displays&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At the time I am writing this article, there&#39;s a bunch of high-end devices, both from Apple and Google, mounting a HiDPI display with 3x pixel density or more. Apple calls them Super Retina displays, Google calls them FHD+ displays.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/1EK9ztJTx7-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Apple iPhone 12 Mini, Apple iPhone X, Apple iPhone XS, Apple iPhone 11 Pro, Google Pixel 3, Google Pixel 4, Google Pixel 5, Apple iPhone 12, Apple iPhone 12 Pro&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/1EK9ztJTx7-648.jpeg&quot; width=&quot;648&quot; height=&quot;529&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;Devices with super HiDPI displays&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Apple launched their first Super Retina display with the iPhone X, the same kind of display is mounted in the iPhone XS / Max, iPhone 11 Pro / 11 Pro Max, and on all the phones in the iPhone 12 line-up, including the 12 Mini.&lt;/p&gt;
&lt;p&gt;Google Pixel phones have their FHD+ displays with a 3x pixel density, and QHD+ displays with a pixel density of 3.5x on the Pixel 4 XL.&lt;/p&gt;
&lt;h2 id=&quot;capping-image-fidelity&quot; tabindex=&quot;-1&quot;&gt;Capping image fidelity &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#capping-image-fidelity&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;According to the analysis on a &lt;a href=&quot;https://blog.twitter.com/engineering/en_us/topics/infrastructure/2019/capping-image-fidelity-on-ultra-high-resolution-devices.html&quot;&gt;Twitter mobile app change&lt;/a&gt;, capping image fidelity to 2x leads to a significant improvement in terms of rendering speed and no perceivable quality loss for your users.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Images in timelines on ultra-high resolution devices now load roughly 33% faster while using 1/3rd less data, and with no visible quality change.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The problem with doing responsive images using the &lt;code&gt;img&lt;/code&gt; tag, as we saw above, is there is no way to stop browsers from downloading the 3x image. The reason is that to determine which image to download from the &lt;code&gt;srcset&lt;/code&gt;, they do the following calculation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;width of the image on screen × device pixel density = width of the image to download
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So for example, if an image has to be displayed at a width of &lt;code&gt;300px&lt;/code&gt; on an iPhone 12, browsers would do the following calculation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;300 × 3 = 900
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And they would download the 900-pixels-wide image. What we want is to cap the fidelity to 2x so that it downloads the 600-pixels-wide image instead.&lt;/p&gt;
&lt;p&gt;The only way to do that on the web is to use the &lt;code&gt;picture&lt;/code&gt; tag like the following:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Landscape tablet / computers --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ####px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 1x, batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Portrait tablet / landscape smartphone --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Larger smartphone(s) --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Smallest smartphone --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Batman Super-man and Wonder&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: I replaced the real numbers with a &lt;code&gt;###&lt;/code&gt; placeholder because those numbers are not relevant to this explanation.&lt;/p&gt;
&lt;p&gt;Notice that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on the smartphones media queries, we describe only the &lt;code&gt;2x&lt;/code&gt; image because all smartphones mount a retina display nowadays&lt;/li&gt;
&lt;li&gt;on the landscape, tablet and computers media query, we should describe both the &lt;code&gt;1x&lt;/code&gt; and &lt;code&gt;2x&lt;/code&gt; images.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;src&lt;/code&gt; attribute on the &lt;code&gt;img&lt;/code&gt; tag is required, but it will be used only by legacy browsers, IE 11 included&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;optionally-reduce-complexity-on-tablets-and-computers-media-queries&quot; tabindex=&quot;-1&quot;&gt;Optionally reduce complexity on tablets and computers media queries &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#optionally-reduce-complexity-on-tablets-and-computers-media-queries&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your layout requires you to do more than 1 media query for tablets and computers, you should then consider using the &lt;code&gt;srcset&lt;/code&gt; attribute with the &lt;code&gt;w&lt;/code&gt; descriptor and the &lt;code&gt;sizes&lt;/code&gt; attribute, which leads to this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Landscape tablet / computers --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px) &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px) 33vw, 50vw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
            batman_####w.jpg ####w,
            batman_####w.jpg ####w,
            batman_###w.jpg   ###w
        &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Portrait tablet / landscape smartphone --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Larger smartphone(s) --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Smallest smartphone --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Batman Super-man and Wonder&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this way, from the landscape tablets and computers media query and above, you won’t need to add other &lt;code&gt;source&lt;/code&gt; tags, because there’s no need to cap image quality on computers. The upmost &lt;code&gt;source&lt;/code&gt; tag does the trick.&lt;/p&gt;
&lt;h2 id=&quot;that-s-a-lot-of-markup-for-one-image-you-say&quot; tabindex=&quot;-1&quot;&gt;“That’s a lot of markup for one image”, you say? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#that-s-a-lot-of-markup-for-one-image-you-say&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are using responsive images you probably already have considerably large &lt;code&gt;img&lt;/code&gt; tags, each one listing a set of image URLs in the &lt;code&gt;srcset&lt;/code&gt; attribute, and a set of media queries and sizes in the &lt;code&gt;sizes&lt;/code&gt; attribute. The code listed above can be slightly larger, but not significantly.&lt;/p&gt;
&lt;p&gt;That said, tools like GZip and Brotli — which are working out of the box in most applications servers and CDNs — do a great job at compressing repeated characters in markup, and there are lots of repeated characters in those image tags.&lt;/p&gt;
&lt;p&gt;I did a test and I found out that an HTML file containing 54 images weighs 37 kb uncompressed, but it only weighs 530 bytes GZipped. If you compare this to the &lt;strong&gt;45% data savings&lt;/strong&gt; on the downloaded images, that’s probably a good trade-off.&lt;/p&gt;
&lt;h2 id=&quot;result-45-lighter-images&quot; tabindex=&quot;-1&quot;&gt;Result: 45% lighter images &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#result-45-lighter-images&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using this technique on the product listing page of one of the websites we manage led to an &lt;strong&gt;image weight reduction of 45%&lt;/strong&gt;. Images weight on an iPhone 11 Pro was 1.7 Mb before and it’s only 949 kb after the capping.&lt;/p&gt;
&lt;figure&gt;
	&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/RhbzfQii2W-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Name w476.jpg, Size 185kb vs Name w360jpg, Size 102kb, etc.&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/RhbzfQii2W-648.jpeg&quot; width=&quot;648&quot; height=&quot;353&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;Images weight before (left) and after the capping (right)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class=&quot;videoWrapper&quot;&gt;
    &lt;iframe loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/c2frAgQ_8lQ&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id=&quot;demos&quot; tabindex=&quot;-1&quot;&gt;Demos &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#demos&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve created a &lt;a href=&quot;https://github.com/verlok/cap-image-fidelity-to-2x&quot;&gt;GitHub repo&lt;/a&gt; and a &lt;a href=&quot;https://codepen.io/verlok/pen/wvWRgEG&quot;&gt;Codepen&lt;/a&gt;. Feel free to try and fork them.&lt;/p&gt;
&lt;p&gt;Single image with fidelity capped to 2x:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/verlok/cap-image-fidelity-to-2x&quot;&gt;GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://verlok.github.io/cap-image-fidelity-to-2x/&quot;&gt;Live here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/verlok/pen/wvWRgEG&quot;&gt;Codepen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or try &lt;a href=&quot;https://faulty-driving.surge.sh/&quot;&gt;the page shown in the video above&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;🌟 &lt;a href=&quot;https://verlok.github.io/cap-image-fidelity-to-2x/&quot;&gt;Open the live demo&lt;/a&gt; 💻&lt;/p&gt;
&lt;h2 id=&quot;psst-you-can-still-lazy-load-images&quot; tabindex=&quot;-1&quot;&gt;Psst! You can still lazy-load images &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#psst-you-can-still-lazy-load-images&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the best practices to minimize your website’s &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint&lt;/a&gt; is to eagerly load the above-the-fold images, lazy load below-the-fold ones. You can do that by using &lt;code&gt;data-src&lt;/code&gt;, &lt;code&gt;data-srcet&lt;/code&gt;, &lt;code&gt;data-sizes&lt;/code&gt; instead of &lt;code&gt;src&lt;/code&gt;, &lt;code&gt;srcset&lt;/code&gt;, &lt;code&gt;sizes&lt;/code&gt; both in the &lt;code&gt;img&lt;/code&gt; and in the &lt;code&gt;source&lt;/code&gt; tags.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Landscape tablet / computers --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px) &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px) 33vw, 50vw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
            batman_####w.jpg ####w,
            batman_####w.jpg ####w,
            batman_###w.jpg   ###w
        &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Portrait tablet / landscape smartphone --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Larger smartphone(s) --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: ###px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Smallest smartphone --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;batman_###w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Batman Super-man and Wonder&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More about &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp&quot;&gt;lazy loading responsive images&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;to-wrap-up&quot; tabindex=&quot;-1&quot;&gt;To wrap up &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/capping-image-fidelity-2x-minimize-loading-time/#to-wrap-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In web design with responsive images, capping image fidelity on super HiDPI devices is a relatively new best practice, because of the growing number of smartphones spoiling super HiDPI displays.&lt;/p&gt;
&lt;p&gt;Capping image fidelity will improve the rendering speed of your website, as well as your users’ experience and your pages’ &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint&lt;/a&gt; metric.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to optimise for CLS when loading more content asynchronously</title>
		<link href="https://andreaverlicchi.eu/en/blog/optimise-cls-loading-more-content-pagination/"/>
		<updated>2020-08-31T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/optimise-cls-loading-more-content-pagination/</id>
		<content type="html">&lt;p&gt;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.&lt;/p&gt;
&lt;img alt=&quot;A website showing 4 images and a Load More button&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/Hpjjdm7Lao-648.webp&quot; width=&quot;648&quot; height=&quot;430&quot;&gt;
&lt;p&gt;What you might not know is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CLS is measured continuously&lt;/strong&gt;. In fact, its value is also updated while your users scroll your page, if the scroll generates some layout movement&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLS measurement is paused for 500ms&lt;/strong&gt; whenever a user interaction like a click or a keyboard event occurs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Long story short, Cumulative Layout Shift measures every unexpected layout movement occurring while your users interact with the page, including while they scroll down.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When loading more content in our pages, the most common source of CLS is the page footer becoming visible for a while, then being pushed below-the-fold again by new, dynamically added content.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So how to keep CLS from growing when we need to load new content dynamically, e.g. to load a whole new page of products?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/ynap-tech/how-to-optimize-for-cls-when-having-to-load-more-content-3f60f0cf561c&quot;&gt;Continue reading on Medium&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Lazy load responsive images in 2020</title>
		<link href="https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/"/>
		<updated>2020-05-24T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/</id>
		<content type="html">&lt;p&gt;Do you want to boost performance on your website? You can do that by using &lt;strong&gt;responsive images&lt;/strong&gt; and &lt;strong&gt;lazy loading&lt;/strong&gt;! In this article, you will find the &lt;strong&gt;HTML, JavaScript, and CSS code&lt;/strong&gt; to lazy load responsive images, to make browsers use &lt;strong&gt;modern image formats&lt;/strong&gt; like &lt;strong&gt;WebP&lt;/strong&gt; and &lt;strong&gt;Jpeg2000&lt;/strong&gt;, and to enable &lt;strong&gt;native lazy load&lt;/strong&gt; where supported.&lt;/p&gt;
&lt;img alt=&quot;Lazy Load responsive images in 2020&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/gzU4RsZnz1-648.webp&quot; width=&quot;648&quot; height=&quot;432&quot;&gt;
&lt;h2 id=&quot;definitions&quot; tabindex=&quot;-1&quot;&gt;Definitions &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#definitions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Responsive images&lt;/strong&gt; are &lt;code&gt;img&lt;/code&gt; tags that download the right image source depending on your design and the user&#39;s device. You can provide information about your design in the &lt;code&gt;sizes&lt;/code&gt; attribute and a list of image sources in the &lt;code&gt;srcset&lt;/code&gt; attribute. You can also use media queries by wrapping your &lt;code&gt;img&lt;/code&gt; in a &lt;code&gt;picture&lt;/code&gt; tag. More about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images&quot;&gt;responsive images in the MDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lazy loading images&lt;/strong&gt; is a technique that makes your website render faster by &lt;strong&gt;deferring the loading of below-the-fold images&lt;/strong&gt; to when they &lt;strong&gt;enter the viewport&lt;/strong&gt;. Beyond performance, this also allows you to save bandwidth and money, e.g. if you&#39;re paying a CDN service for your images.&lt;/p&gt;
&lt;h2 id=&quot;above-the-fold-first&quot; tabindex=&quot;-1&quot;&gt;Above-the-fold first &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#above-the-fold-first&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Bear in mind that using a script to &lt;strong&gt;lazy load images is a Javascript-based task&lt;/strong&gt; and it&#39;s &lt;strong&gt;relevantly slower than the regular image loading&lt;/strong&gt; (&lt;em&gt;eager loading&lt;/em&gt; from now on) which starts as soon as the HTML document is being parsed.&lt;/p&gt;
&lt;p&gt;☝️ For this reason, the best practice is to &lt;strong&gt;eagerly load above-the-fold images&lt;/strong&gt;, and &lt;strong&gt;lazy load only the below-the-fold images&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At this point, people usually ask:&lt;/p&gt;
&lt;p&gt;💬 &lt;em&gt;My website is responsive, how do I know how many images will be&lt;/em&gt; above-the-fold &lt;em&gt;at page landing?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The answer is: count them! Open the web page in a browser, resize the viewport to the most common dimensions (smartphones, computers, and tablets) maybe using the device emulation tool, and count them.&lt;/p&gt;
&lt;p&gt;If you can see 4 images &lt;em&gt;above-the-fold&lt;/em&gt; in a smartphone viewport, plus only the tip of 4 more images on a desktop viewport, be conservative and eagerly load only 4.&lt;/p&gt;
&lt;h2 id=&quot;now-to-some-code&quot; tabindex=&quot;-1&quot;&gt;Now to some code! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#now-to-some-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&#39;s the HTML markup of an &lt;em&gt;eagerly loaded&lt;/em&gt; responsive image.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Eagerly loaded,
     above-the-fold only --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Eager above&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
    220x280.jpg 220w,
    440x560.jpg 440w
  &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here&#39;s the markup to &lt;em&gt;lazy load&lt;/em&gt; a responsive image.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Lazy loaded,
     below-the-fold only --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Lazy below&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg 220w,
    440x560.jpg 440w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Want to show a low-resolution preview while your lazy images are loading? You can do that by using a small, low-quality image in the &lt;code&gt;src&lt;/code&gt; tag, like the following.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Lazy loaded,
     + low-res preview,
     below-the-fold only --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Lazy below with preview&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;11x14.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg 220w,
    440x560.jpg 440w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/demos/image_srcset_lazy_sizes.html&quot;&gt;Open the 👀 demo&lt;/a&gt;, then your browser&#39;s &lt;strong&gt;developer tools&lt;/strong&gt;, then switch to the &lt;strong&gt;Network panel&lt;/strong&gt;. You will see that the first 2 images are &lt;em&gt;eagerly&lt;/em&gt; loaded just after page landing, while the rest of the images are &lt;em&gt;lazily&lt;/em&gt; loaded &lt;strong&gt;as you scroll down&lt;/strong&gt; the page.&lt;/p&gt;
&lt;p&gt;We&#39;re using the &lt;code&gt;img&lt;/code&gt; HTML tag and not the &lt;code&gt;picture&lt;/code&gt; tag, given that the latter is not necessary in this case. I&#39;ll dig into the &lt;code&gt;picture&lt;/code&gt; tag use cases later in this article. ⏩ &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#picture-tag-use-cases&quot;&gt;Skip to &lt;code&gt;picture&lt;/code&gt; tag use cases&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;script-inclusion&quot; tabindex=&quot;-1&quot;&gt;Script inclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#script-inclusion&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To load the lazy images as they enter the viewport, you need a lazy load script such as &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; which is a lightweight (2.5 kb gzipped), blazing-fast, configurable, SEO-friendly script that I created and I&#39;ve been constantly improving since 2014.&lt;/p&gt;
&lt;p&gt;Here is the simplest way to include it in your page.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdn.jsdelivr.net/npm/vanilla-lazyload@18.0.0/dist/lazyload.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Have a look at the documentation for &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/#-getting-started---script&quot;&gt;more ways to include LazyLoad&lt;/a&gt; in your web pages, like using an &lt;code&gt;async&lt;/code&gt; script with auto-init, using RequireJS, using WebPack or Rollup.&lt;/p&gt;
&lt;h3 id=&quot;lazyload-initialization&quot; tabindex=&quot;-1&quot;&gt;LazyLoad initialization &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#lazyload-initialization&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Including the vanilla-lazyload script gives you a &lt;code&gt;LazyLoad&lt;/code&gt; JS class you can use to load the images identified by the &lt;code&gt;lazy&lt;/code&gt; CSS class. You must create a &lt;code&gt;LazyLoad&lt;/code&gt; instance like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; lazyLoad &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Your custom settings go here&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;minimize-layout-reflow&quot; tabindex=&quot;-1&quot;&gt;Minimize layout reflow &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#minimize-layout-reflow&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When using lazy loading, the images that haven&#39;t started loading collapse to &lt;code&gt;0&lt;/code&gt;-height, only to grow when they&#39;ll have started loading. Layout reflowing would make your website janky, so it&#39;s a best practice to &lt;strong&gt;stabilize your layout&lt;/strong&gt; by occupying the exact amount of space your images will take when loaded, before they start loading.&lt;/p&gt;
&lt;p&gt;The universal solution to do that is to use the vertical padding trick, while in the future you&#39;ll be able to use the &lt;code&gt;aspect-ratio&lt;/code&gt; CSS directive to do it (as I&#39;m writing it&#39;s &lt;a href=&quot;https://twitter.com/Una/status/1260980901934137345&quot;&gt;landed&lt;/a&gt; in Chrome Canary only).&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.image-wrapper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding-bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 150%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* ☝️ image height / width * 100% */&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.image&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&#39;s also a useful SASS mixin to do that (source: &lt;a href=&quot;https://css-tricks.com/snippets/sass/maintain-aspect-ratio-mixin/&quot;&gt;CSS tricks&lt;/a&gt;).&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;aspect-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token parent important&quot;&gt;&amp;amp;&lt;/span&gt;:before &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;padding-top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$height&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;&gt; .content &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info in &lt;a href=&quot;http://andyshora.com/css-image-container-padding-hack.html&quot;&gt;Sizing Fluid Image Containers with a Little CSS Padding Hack&lt;/a&gt; by Andy Shora.&lt;/p&gt;
&lt;h3 id=&quot;avoid-broken-images&quot; tabindex=&quot;-1&quot;&gt;Avoid &amp;quot;broken&amp;quot; images &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#avoid-broken-images&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To avoid lazy images to appear as broken, even for a short amount of time, use CSS. Hide the images that still don&#39;t have neither an &lt;code&gt;src&lt;/code&gt; nor a &lt;code&gt;srcset&lt;/code&gt; attribute set.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;img:not([src]):not([srcset])&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;visibility&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;no-polyfills-required&quot; tabindex=&quot;-1&quot;&gt;No polyfills required &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#no-polyfills-required&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You might be tempted to add one or more polyfills to support Internet Explorer (&lt;em&gt;yes, I named it and it&#39;s 2020&lt;/em&gt;). Don&#39;t do that, &lt;strong&gt;you don&#39;t need any&lt;/strong&gt;. Let me tell you why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Responsive images:&lt;/em&gt; Internet Explorer does not support responsive images, but you don&#39;t need to use a polyfill because &lt;abbr title=&quot;Internet Explorer&quot;&gt;IE&lt;/abbr&gt; gracefully degrades using &lt;strong&gt;the image specified in the &lt;code&gt;src&lt;/code&gt; attribute&lt;/strong&gt;. So choose an image that would appear nice on a regular desktop display, place in the &lt;code&gt;src&lt;/code&gt; attribute, and you&#39;re cool.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;IntersectionObserver:&lt;/em&gt; Internet Explorer does not support the &lt;code&gt;IntersectionObserver&lt;/code&gt; API, which is used by vanilla-lazyload, but you don&#39;t need to provide a polyfill because vanilla-lazyload will detect the support for that API and, if missing, it will loads all images immediately. This leads to the same result as if no LazyLoad was ever used on the page, but it doesn&#39;t throw any errors.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s cool, Internet Explorer is not being used by more than 5% of the users today, and Microsoft is silently replacing it with &lt;a href=&quot;https://www.microsoft.com/edge&quot;&gt;Edge&lt;/a&gt; via Windows Update.&lt;/p&gt;
&lt;p&gt;Anyway if for some reason you want it to work in the same exact way on Internet Explorer, you can use the IntersectionObserver polyfill by including it before vanilla-lazyload.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Don&#39;t do this if you&#39;re not sure! Read above --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdn.jsdelivr.net/npm/intersection-observer@0.10.0/intersection-observer.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdn.jsdelivr.net/npm/vanilla-lazyload@18.0.0/dist/lazyload.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;putting-it-all-together&quot; tabindex=&quot;-1&quot;&gt;Putting it all together &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#putting-it-all-together&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For your convenience here&#39;s all the HTML, JS, and CSS code together.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Eagerly loaded,
     above-the-fold only --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Eager above&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
    220x280.jpg 220w,
    440x560.jpg 440w
  &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Lazy loaded,
     below-the-fold only --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Lazy below&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220x280.jpg 220w,
    440x560.jpg 440w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; lazyLoad &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;elements_selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.lazy&quot;&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;cancel_on_exit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*
Images container to occupy space
when the images aren&#39;t loaded yet
*/&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.image-wrapper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding-bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 150%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* ☝️ image height / width * 100% */&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.image&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* ...other positioning rules */&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
Hide &quot;broken&quot; images before
they start loading
*/&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;img:not([src]):not([srcset])&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;visibility&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that&#39;s it for the simple &lt;code&gt;img&lt;/code&gt; tag.&lt;/p&gt;
&lt;h2 id=&quot;picture-tag-use-cases&quot; tabindex=&quot;-1&quot;&gt;Picture tag use cases &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#picture-tag-use-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Until now, I wrote about the &lt;code&gt;img&lt;/code&gt; tag with the &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; attributes, which is the solution to the vast majority of the responsive images you might need to use on a website or web application. Now, in which cases should you use the &lt;code&gt;picture&lt;/code&gt; tag?&lt;/p&gt;
&lt;h3 id=&quot;different-width-height-ratio&quot; tabindex=&quot;-1&quot;&gt;Different width/height ratio &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#different-width-height-ratio&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use case: you need to show images with different &lt;strong&gt;width/height ratio&lt;/strong&gt; depending on a media query. e.g. you want to show &lt;em&gt;portrait images&lt;/em&gt; on mobile, vertical devices, &lt;em&gt;landscape images&lt;/em&gt; on wider viewports, like tablets and computers.&lt;/p&gt;
&lt;p&gt;Here&#39;s the code you&#39;re gonna need in this case. In order to have eagerly loaded images, just use the plain &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;srcset&lt;/code&gt; attributes, without &lt;code&gt;data-&lt;/code&gt; prefix.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 1024px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1024x576.jpg 1x,
      2048x1152.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 1023px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;640x960.jpg 1x,
      1280x1920.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Portrait or landscape&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1024x576.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/demos/picture_media.html&quot;&gt;Open the 👀 demo&lt;/a&gt;, then your browser&#39;s &lt;strong&gt;developer tools&lt;/strong&gt;, then switch to the &lt;strong&gt;Network panel&lt;/strong&gt;. You will see that it downloads only the image source corresponding to the first matching media query.&lt;/p&gt;
&lt;h3 id=&quot;load-modern-formats-like-webp-and-jpeg2000&quot; tabindex=&quot;-1&quot;&gt;Load modern formats like WebP and Jpeg2000 &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#load-modern-formats-like-webp-and-jpeg2000&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use case: you want browsers to choose the source to &lt;strong&gt;load a modern format like WebP and Jpeg2000&lt;/strong&gt; depending on its support for that format.&lt;/p&gt;
&lt;p&gt;You need the &lt;code&gt;source&lt;/code&gt; tag and the &lt;code&gt;type&lt;/code&gt; attribute containing the MIME type of the images in the &lt;code&gt;data-&lt;/code&gt;/&lt;code&gt;srcset&lt;/code&gt; attribute.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/jp2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1024x576.jp2 1x,
      2048x1152.jp2 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/webp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1024x576.webp 1x,
      2048x1152.webp 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1024x576.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1024x576.jpg 1x,
      2048x1152.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1024px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Jp2, WebP or Jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/demos/picture_type_webp.html&quot;&gt;Open the 👀 demo&lt;/a&gt;, then your browser&#39;s &lt;strong&gt;developer tools&lt;/strong&gt;, then switch to the &lt;strong&gt;Network panel&lt;/strong&gt;. You will see that it downloads only the image source corresponding to the first type that your browser supports.&lt;/p&gt;
&lt;p&gt;💬 &lt;em&gt;Isn&#39;t that markup too long for one image?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yes, it is. And if you have money to invest in image optimization, there other ways to do that. Most of the cloud-based image servers in the market now automatically serve different image formats at the same URL. This means that you can request &lt;code&gt;1024x576.jpg&lt;/code&gt; and you get a WebP or a Jpeg2000 accordingly. &lt;a href=&quot;https://cloudinary.com/&quot;&gt;Cloudinary&lt;/a&gt; and &lt;a href=&quot;https://www.akamai.com/it/it/products/performance/image-and-video-manager.jsp&quot;&gt;Akamai Image &amp;amp; Video Manager&lt;/a&gt; do that, amongst others.&lt;/p&gt;
&lt;h3 id=&quot;image-fidelity-capping-to-2x&quot; tabindex=&quot;-1&quot;&gt;Image fidelity capping to 2x &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#image-fidelity-capping-to-2x&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With the rise of very high density &amp;quot;super retina&amp;quot; displays in newest high-end devices such as the whole iPhone 12 and the whole Google Pixel lineups, capping image fidelity to 2x leads to a big improvement in terms of download speed, and no perceivable quality loss for your users.&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/capping-image-fidelity-2x-minimize-loading-time&quot;&gt;Here&#39;s a new best practice on how to do that.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;native-lazyload&quot; tabindex=&quot;-1&quot;&gt;Native lazyload &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#native-lazyload&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You might have heard or read of &lt;a href=&quot;https://web.dev/native-lazy-loading/&quot;&gt;native lazy-loading&lt;/a&gt; coming to the web. Cool, isn&#39;t it? As of May 2020, it&#39;s supported in Chrome, Firefox, Edge, Opera, and &lt;em&gt;behind a flag&lt;/em&gt; in Safari.&lt;/p&gt;
&lt;p&gt;So 100% browsers support isn&#39;t quite there, but in case you want to enable it on supported browsers, you could go for &lt;a href=&quot;https://www.smashingmagazine.com/2019/05/hybrid-lazy-loading-progressive-migration-native/&quot;&gt;hybrid lazy-loading&lt;/a&gt; by setting the &lt;code&gt;use_native&lt;/code&gt; option of vanilla-lazyload to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;use_native&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;you-might-miss-these-features&quot; tabindex=&quot;-1&quot;&gt;You might miss these features &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#you-might-miss-these-features&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you go for native lazy-loading or hybrid lazyloading, you might miss some &lt;strong&gt;features that JS-driven lazy-loading grants&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;automatic classes application&lt;/strong&gt; on events (&lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;loaded&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;automatic retry loading images&lt;/strong&gt; when the network failed and you&#39;re back online&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;download cancelation&lt;/strong&gt; when images exit the viewport while still loading, to &lt;strong&gt;prioritize the loading of new ones&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;callbacks on events triggered&lt;/strong&gt; (viewport enter/exit, loading started/finished, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Think about it carefully before switching to native lazy-loading. If you don&#39;t mind missing the above features, you&#39;re good to go.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;conclusions&quot; tabindex=&quot;-1&quot;&gt;Conclusions &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#conclusions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is a summary:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/&quot;&gt;vanilla-lazyload&lt;/a&gt; to load your lazy images.&lt;/li&gt;
&lt;li&gt;Don&#39;t load all the images lazily, just the ones &lt;em&gt;below the fold&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;img&lt;/code&gt; for simple responsive images&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;picture&lt;/code&gt; tag to
&lt;ul&gt;
&lt;li&gt;change your images width/height ratio at specific media queries&lt;/li&gt;
&lt;li&gt;conditionally serve your images in modern formats like WebP or Jpeg2000&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Don&#39;t use any polyfill if not strictly required&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Happy lazy loading!&lt;/p&gt;
&lt;h3 id=&quot;about-this-article&quot; tabindex=&quot;-1&quot;&gt;About this article &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#about-this-article&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If something is unclear or you think it could be improved, let me know in the comments or &lt;a href=&quot;https://twitter.com/verlok/&quot;&gt;tweet me&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;☕ If you&#39;ve found this useful, you might want to express your gratitude by &lt;a href=&quot;https://ko-fi.com/verlok&quot;&gt;buying me a coffee&lt;/a&gt;. ☕&lt;/p&gt;
&lt;h3 id=&quot;useful-resources&quot; tabindex=&quot;-1&quot;&gt;Useful resources &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp/#useful-resources&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://alistapart.com/article/responsive-images-in-practice&quot;&gt;Responsive images in practice&lt;/a&gt; @ A List Apart&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images&quot;&gt;Responsive images&lt;/a&gt; @ Mozilla Developer Network&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/responsive-images-css/&quot;&gt;Responsive images in CSS&lt;/a&gt; @ CSS Tricks&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://responsiveimages.org&quot;&gt;Responsive images community group&lt;/a&gt; website&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>How to productively use the new Chromium-based Microsoft Edge browser</title>
		<link href="https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/"/>
		<updated>2020-01-16T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/</id>
		<content type="html">&lt;p&gt;Here’s a practical guide on how to productively use the new Chromium-based Microsoft Edge browser: download it, change the default search engine, install extensions, and more.&lt;/p&gt;
&lt;h2 id=&quot;index&quot; tabindex=&quot;-1&quot;&gt;Index &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#index&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Download Microsoft Edge&lt;/li&gt;
&lt;li&gt;Change the default search engine&lt;/li&gt;
&lt;li&gt;Install extensions from Chrome web store&lt;/li&gt;
&lt;li&gt;Set the dark theme&lt;/li&gt;
&lt;li&gt;Configure one or more profiles&lt;/li&gt;
&lt;li&gt;Become an insider&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;download-for-any-platform&quot; tabindex=&quot;-1&quot;&gt;Download for any platform &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#download-for-any-platform&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;No matter if you are on Windows 10, 8, 7 or on Mac OS, you can &lt;a href=&quot;https://www.microsoft.com/edge&quot;&gt;download Microsoft Edge&lt;/a&gt; for your computer.&lt;/p&gt;
&lt;h2 id=&quot;change-the-default-search-engine&quot; tabindex=&quot;-1&quot;&gt;Change the default search engine &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#change-the-default-search-engine&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After you installed it, the first thing you want to do is to change your default search engine to Google or DuckDuck (unless you really like Bing). You can do that from the Settings panel, Privacy and Services tab.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click on the &lt;code&gt;...&lt;/code&gt; button&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Settings&amp;quot;&lt;/li&gt;
&lt;li&gt;Selecte &amp;quot;Privacy and services&amp;quot; in the left menu&lt;/li&gt;
&lt;li&gt;(scroll down to the bottom)&lt;/li&gt;
&lt;li&gt;Click &amp;quot;Address bar&amp;quot;&lt;/li&gt;
&lt;li&gt;Select your favourite search engine from the &amp;quot;Search engine used in the address bar&amp;quot; drop down&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy usage!&lt;/p&gt;
&lt;h2 id=&quot;install-extensions&quot; tabindex=&quot;-1&quot;&gt;Install extensions &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#install-extensions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Microsoft Edge has its own marketplace for extensions, but on Microsoft Edge you can also &lt;strong&gt;install extensions from the Chrome web store&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/store/collections/edgeextensions/&quot;&gt;Extensions for Microsoft Edge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/webstore/category/extensions&quot;&gt;Extensions from the Chrome Web Store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you visit the Chrome Web Store, Edge shows a blue bar on top telling you that you can install extensions from there. Just click the &amp;quot;Allow extensions from other stores&amp;quot; button and you&#39;re good to go.&lt;/p&gt;
&lt;h2 id=&quot;how-to-set-the-dark-theme&quot; tabindex=&quot;-1&quot;&gt;How to set the dark theme &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#how-to-set-the-dark-theme&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you like dark themes on development stuff like I do, you can activate the dark theme from the Settings panel, Appearance tab.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click on the &lt;code&gt;...&lt;/code&gt; button&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Settings&amp;quot;&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Appearance&amp;quot;&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Dark&amp;quot; from the &amp;quot;Theme&amp;quot; drop down&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;more-profiles&quot; tabindex=&quot;-1&quot;&gt;More? Profiles &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#more-profiles&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are a Chrome user, at your first usage of Microsoft Edge everything gets magically migrated from Chrome to Edge. At least, that&#39;s what happened to me when I started using Edge Dev some months ago.&lt;/p&gt;
&lt;p&gt;You might be interested in creating one or more profile and sync options, so that when you use Edge on your other devices (PC, Other PC, Mac, etc.) you find your passwords, autofill options and browsing history at hand.&lt;/p&gt;
&lt;h2 id=&quot;become-an-insider&quot; tabindex=&quot;-1&quot;&gt;Become an insider &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#become-an-insider&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can also be an insider and use Microsoft Edge early releases. There are 3 channels: Beta, Dev and Canary.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Canary is the most frequently updated (updated every day) but also the most unstable&lt;/li&gt;
&lt;li&gt;Beta is the less frequently updated (every 6 weeks) so is the more stable&lt;/li&gt;
&lt;li&gt;Dev is updated weekly so it&#39;s more stable than the Canary, but less stable than the Beta.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Download any of the above in the &lt;a href=&quot;https://www.microsoftedgeinsider.com/en-gb/download/&quot;&gt;Microsoft Edge Insider Channels page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I personally used Microsoft Edge Dev as my primary browser for months on both Mac and Windows for leisure and development purposes with a very high level of satisfaction. Unfortunately, the latest Dev and Canary versions have stopped working on one of my machines starting January 9th, but I already reported it to Microsoft and I expect a fix soon.&lt;/p&gt;
&lt;h2 id=&quot;is-this-the-end-of-internet-explorer&quot; tabindex=&quot;-1&quot;&gt;Is this the end of Internet Explorer? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#is-this-the-end-of-internet-explorer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are still companies using &lt;a href=&quot;https://www.bairesdev.com/blog/internet-explorer-history/&quot;&gt;Internet Explorer&lt;/a&gt; for some compatibility reasons (old web-based tools or intranet websites). This version of Edge features an &amp;quot;Internet Explorer Mode&amp;quot; so those companies can finally set Microsoft Edge as default browsers for their workers, who will be able to browse the web using a modern browser, without breaking their old tools functionality.&lt;/p&gt;
&lt;h2 id=&quot;help-the-web&quot; tabindex=&quot;-1&quot;&gt;Help the web &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/how-to-productively-use-the-new-chromium-based-microsoft-edge-browser/#help-the-web&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you know companies that are still using Internet Explorer for some compatibility reasons, you should tell them.&lt;/p&gt;
&lt;p&gt;And if you are a web developer like me, you should definitely give Microsoft Edge a try both to test and to develop your websites.&lt;/p&gt;
&lt;p&gt;➡ &lt;a href=&quot;https://www.microsoft.com/edge&quot;&gt;Download Microsoft Edge (stable)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Critical CSS with Jekyll and SASS</title>
		<link href="https://andreaverlicchi.eu/en/blog/critical-css-jekyll-sass-github-pages/"/>
		<updated>2019-06-17T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/critical-css-jekyll-sass-github-pages/</id>
		<content type="html">&lt;p&gt;My blog used to be run by &lt;strong&gt;Jekyll on GitHub pages&lt;/strong&gt; and its CSS was built using SASS. Today I decided to boost performance even more inlining the render-blocking &lt;em&gt;critical&lt;/em&gt; CSS, but even searching the internet I struggled to find an easy way to do it. This post is for you, in case you want to do the same.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/NLErsSG8S0-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Random blurred code&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/NLErsSG8S0-648.jpeg&quot; width=&quot;648&quot; height=&quot;432&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-critical-style&quot; tabindex=&quot;-1&quot;&gt;The critical style &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/critical-css-jekyll-sass-github-pages/#the-critical-style&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the critical SASS file, use the SASS &lt;code&gt;@import&lt;/code&gt; directive to include all the partials that have an impact on the layout of your page. Also include your &lt;em&gt;variables&lt;/em&gt; and &lt;em&gt;mixins&lt;/em&gt; that might be required from the imported partials.&lt;/p&gt;
&lt;p&gt;For instance, I&#39;m importing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;base&lt;/code&gt; partial, which contains the basic rules of the website like the CSS reset and the typography rules,&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;layout&lt;/code&gt; partial, which styles the header and layout of the page,&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;posts_above&lt;/code&gt; partial, which styles the &lt;em&gt;above-the-fold&lt;/em&gt; part of the posts list and the post detail,&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;utils&lt;/code&gt; partial, which contains some helper classes (e.g. &lt;code&gt;visuallyHidden&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;posts_above&lt;/code&gt; partial initially was a single file called &lt;code&gt;posts&lt;/code&gt;, but I decided to split it in two separate files to optimize even more. The other partial, named &lt;code&gt;posts_below&lt;/code&gt;, contains information to style the post footer (the author section, the share button) so it&#39;s &lt;em&gt;not&lt;/em&gt; included here.&lt;/p&gt;
&lt;p&gt;→ Create a &lt;code&gt;critical.scss&lt;/code&gt; file inside the &lt;code&gt;includes&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;File &lt;code&gt;includes/critical.scss&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Import partials for critical css content&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;variables&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mixins&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;base&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;layout&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;posts_above&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pages&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;utils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IMPORTANT: Place this file in the &lt;code&gt;includes&lt;/code&gt; folder! You&#39;ll need to include it in your HTML later.&lt;/p&gt;
&lt;h2 id=&quot;stick-it-in-your-head&quot; tabindex=&quot;-1&quot;&gt;Stick it in your &lt;code&gt;head&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/critical-css-jekyll-sass-github-pages/#stick-it-in-your-head&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Inline the critical CSS inside a &lt;code&gt;style&lt;/code&gt; tag in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of your HTML. You can do that using the following Jekyll code, which is based on the Liquid template engine used in Jekyll.&lt;/p&gt;
&lt;p&gt;→ Open your &lt;code&gt;head.html&lt;/code&gt; partial if you have any.&lt;/p&gt;
&lt;p&gt;File &lt;code&gt;includes/head.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-liquid&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-liquid&quot;&gt;&lt;span class=&quot;token liquid language-liquid&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;capture&lt;/span&gt; critical &lt;span class=&quot;token delimiter punctuation&quot;&gt;%}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token liquid language-liquid&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt; minima_critical&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scss &lt;span class=&quot;token delimiter punctuation&quot;&gt;%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token liquid language-liquid&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;endcapture&lt;/span&gt; &lt;span class=&quot;token delimiter punctuation&quot;&gt;%}&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token liquid language-liquid&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;{{&lt;/span&gt; critical &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function filter&quot;&gt;scssify&lt;/span&gt; &lt;span class=&quot;token delimiter punctuation&quot;&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;the-rest-of-your-stylesheet&quot; tabindex=&quot;-1&quot;&gt;The rest of your stylesheet &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/critical-css-jekyll-sass-github-pages/#the-rest-of-your-stylesheet&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your website is simple enough, you can import the rest of your partials inside a single SCSS file, which you will load asynchronously using JavaScript.&lt;/p&gt;
&lt;p&gt;I for instance imported there all the SASS partials which style the page sections that are likely to appear &lt;em&gt;below-the-fold&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the syntax highlighting style,&lt;/li&gt;
&lt;li&gt;the footer style,&lt;/li&gt;
&lt;li&gt;the pagination style,&lt;/li&gt;
&lt;li&gt;the SVG icons style,&lt;/li&gt;
&lt;li&gt;the iframes and tables styles&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ Put the rest of your SASS rules inside your regular CSS file.&lt;/p&gt;
&lt;p&gt;File &lt;code&gt;assets/main.scss&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;---
---

&lt;span class=&quot;token comment&quot;&gt;// Import partials for below-the-fold content&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;variables&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mixins&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;posts_below&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;syntax-highlighting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;footer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;code&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pagination&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;icons&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;iframes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tables&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: The two lines with a triple dash at the beginning of the file are required by Jekyll to recognize and deploy the file as content.&lt;/p&gt;
&lt;h2 id=&quot;load-the-rest-of-your-stylesheet&quot; tabindex=&quot;-1&quot;&gt;Load the rest of your stylesheet &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/critical-css-jekyll-sass-github-pages/#load-the-rest-of-your-stylesheet&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are many ways to load the rest of your CSS using Javascript, but I&#39;ve decided to use the &lt;a href=&quot;https://www.filamentgroup.com/lab/async-css.html&quot;&gt;modern async technique&lt;/a&gt; which makes a CSS file load with low priority, then apply it to the page when loaded.&lt;/p&gt;
&lt;p&gt;File &lt;code&gt;head.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{{ &#39;/assets/main.css&#39; | relative_url }}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;nope!&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onload&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;media&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;all&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/critical-css-jekyll-sass-github-pages/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Inlining the critical part of your CSS makes your pages to display faster since CSS is in the browser&#39;s critical rendering path.&lt;/p&gt;
&lt;p&gt;Give it a try! If you have any comments, let me know in the comments section below!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Web Share API, the step after PWA</title>
		<link href="https://andreaverlicchi.eu/en/blog/web-share-api-step-by-step/"/>
		<updated>2019-06-14T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/web-share-api-step-by-step/</id>
		<content type="html">&lt;p&gt;Today I experimented with the Web Share API and implemented it on this website, just to begin. Here&#39;s what I did and how you can implement it on your website.&lt;/p&gt;
&lt;p&gt;After I made a Progressive Web Application out of this website, I also removed the AddThis script which was used to add the share buttons ad the end of each posts, because it was slowing down the website. I then realized that, after adding the website to my home screen as a standalone app, users couldn&#39;t share posts anymore.&lt;/p&gt;
&lt;h2 id=&quot;web-share-api-to-the-rescue&quot; tabindex=&quot;-1&quot;&gt;Web Share API to the rescue! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/web-share-api-step-by-step/#web-share-api-to-the-rescue&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;ve added the following script to my website&#39;s post pages:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Detects support for the web share feature&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; supportsShare &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;share&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// No support?&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// - Add a &quot;noShare&quot; class to the document&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// - Don&#39;t do anything else&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;supportsShare&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;documentElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;noShare&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Supported? Get:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// - the share button (DOM element)&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// - the canonicalUrl of the page&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// - the title of the page&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; shareButton &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.post-share&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; canonicalUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;link[rel=canonical]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;href&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerText&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Add a listener to the share button&lt;/span&gt;
  shareButton&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Call navigator share with the title and the canonical URL&lt;/span&gt;
    navigator
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;share&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; canonicalUrl
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// You do whatever you want here&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Thanks for sharing!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Manage errors here&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Share failed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, to hide the share buttons using CSS when the &lt;code&gt;noShare&lt;/code&gt; class is added to the document:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.noShare .post-share&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That easy!&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://caniuse.com/#feat=web-share&quot;&gt;support for the Web Share API&lt;/a&gt; is still little, but at least is supported from Safari and Chrome for Android, so it&#39;ll help whoever installed your PWA in their mobile&#39;s home screen.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Making my blog a Progressive Web Application</title>
		<link href="https://andreaverlicchi.eu/en/blog/this-website-pwa/"/>
		<updated>2019-06-10T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/this-website-pwa/</id>
		<content type="html">&lt;p&gt;Some of my workmates and I took part to a Google Hackathon about Progressive Web Application and we learned a lot, so I&#39;ve decided to enable this website as a PWA. Here&#39;s what I did...&lt;/p&gt;
&lt;p&gt;To make an app installable, you need to add a manifest to your website. Here&#39;s the manifest for this website.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Andrea Verlicchi’s Blog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;short_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AV&#39;s Blog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;icons&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/android-chrome-192x192.png?v=wAXeG66EQW&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;192x192&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/png&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/android-chrome-512x512.png?v=wAXeG66EQW&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;512x512&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/png&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;theme_color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#D90009&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;background_color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#977f34&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;display&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;standalone&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;start_url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to enable your website as a PWA, I reccommend you to start with reading the &lt;a href=&quot;https://developers.google.com/web/tools/workbox/guides/get-started&quot;&gt;Workbox Getting Started&lt;/a&gt; guide.&lt;/p&gt;
&lt;h2 id=&quot;service-worker-file&quot; tabindex=&quot;-1&quot;&gt;Service Worker file &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/this-website-pwa/#service-worker-file&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;m using &lt;a href=&quot;https://developers.google.com/web/tools/workbox/&quot;&gt;Workbox&lt;/a&gt; to enable Service Workers and manage cache strategies etc.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;importScripts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
 * ROUTING RULES
 */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Caching every JS file with the Stale While Revalidate strategy&lt;/span&gt;
workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;routing&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;registerRoute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;.js$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strategies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StaleWhileRevalidate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;cacheName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;js-cache&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Caching every CSS file with the Stale While Revalidate strategy&lt;/span&gt;
workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;routing&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;registerRoute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;.css$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strategies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StaleWhileRevalidate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;cacheName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;css-cache&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Caching every Image file with the Cache First strategy&lt;/span&gt;
workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;routing&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;registerRoute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;.(?:png|jpg|jpeg|svg)$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strategies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CacheFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;cacheName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;image-cache&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;expiration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Plugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;maxEntries&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;maxAgeSeconds&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Caching every post&#39;s HTML with the Network First strategy&lt;/span&gt;
workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;routing&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;registerRoute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;/[^&#92;/]+&#92;/$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strategies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NetworkFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;cacheName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;posts-cache&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;workbox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;expiration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Plugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;maxEntries&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;ve temporarily disabled precaching of other pages because I found out that those information are then added to the routing strategy with the Cache First strategy, whichs is not good in order to make your website always retrieve fresh information.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*
 * PRECACHING
 */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// TURNED OFF BECAUSE THESE RESOURCES WOULD BE CACHE-FIRST ONLY!&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/*workbox.precaching.precacheAndRoute([
  { url: &#39;/&#39;, revision: &#39;20190607&#39; },
  { url: &#39;/about/&#39;, revision: &#39;20190607&#39; },
  { url: &#39;/contact/&#39;, revision: &#39;20190607&#39; }
]);*/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But I&#39;m currently investigating and understanding how to manage this.&lt;/p&gt;
&lt;h2 id=&quot;results&quot; tabindex=&quot;-1&quot;&gt;Results &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/this-website-pwa/#results&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The result is that this website is now:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Installable&lt;/li&gt;
&lt;li&gt;Accessible offline&lt;/li&gt;
&lt;li&gt;Modern :)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you have any hints or comments, please &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out&lt;/a&gt; and let me know!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>A smashing article on hybrid lazy loading</title>
		<link href="https://andreaverlicchi.eu/en/blog/hybrid-lazy-loading-smashing-magazine-article/"/>
		<updated>2019-05-16T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/hybrid-lazy-loading-smashing-magazine-article/</id>
		<content type="html">&lt;p&gt;On &lt;time datetime=&quot;2019-05-06&quot;&gt;May 6th, 2019&lt;/time&gt; I wrote my first article on &lt;strong&gt;Smashing Magazine&lt;/strong&gt;: &lt;a href=&quot;https://www.smashingmagazine.com/2019/05/hybrid-lazy-loading-progressive-migration-native/&quot;&gt;Hybrid Lazy Loading: A Progressive Migration To Native Lazy Loading&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/qontc8aECm-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;A screenshot of the article on Smashing Magazine&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/qontc8aECm-648.png&quot; width=&quot;648&quot; height=&quot;318&quot;&gt;&lt;/picture&gt;
  &lt;figcaption&gt;A screenshot of the article on Smashing Magazine&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Native lazy loading is coming to the web. Since it doesn’t depend on JavaScript, it will revolutionize the way we lazy load content today, making it easier for developers to lazy load images and iframes. But it’s not a feature we can polyfill, and it will take some time before it becomes usable across all browsers. In this article, you’ll learn how it works and how you can progressively replace your JavaScript-driven lazy loading with its native alternative, thanks to hybrid lazy loading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the past few weeks, you might have heard or read about native lazy loading, which is coming to Chromium 75 in the upcoming months.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Yeah, great news, but we’ll have to wait until all browsers support it.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If this was the first thing that crossed your mind, keep reading. I will try and convince you of the opposite.&lt;/p&gt;
&lt;p&gt;Let’s start with a comparison between native lazy loading and the good ol’ JavaScript-driven one.&lt;/p&gt;
&lt;p&gt;→ &lt;a href=&quot;https://www.smashingmagazine.com/2019/05/hybrid-lazy-loading-progressive-migration-native/&quot;&gt;Read the full article&lt;/a&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Native lazy loading and js-based fallback with vanilla-lazyload 12</title>
		<link href="https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/"/>
		<updated>2019-04-11T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/</id>
		<content type="html">&lt;p&gt;On April 6th 2019, Addy Osmany wrote about &lt;a href=&quot;https://addyosmani.com/blog/lazy-loading/&quot;&gt;native image lazy-loading&lt;/a&gt;. Two days later Yvain, a front-end developer from Paris, &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/issues/331&quot;&gt;asked me&lt;/a&gt; if my &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/&quot;&gt;vanilla-lazyload&lt;/a&gt; could be a &lt;strong&gt;loading attribute polyfill&lt;/strong&gt;, inspiring me to develop and release version 12 of the script, which features a new &lt;code&gt;use_native&lt;/code&gt; option to enable native lazy-loading where supported. You can already use it today.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://andreaverlicchi.eu/img/22t26E0XUI-648.webp 648w&quot; sizes=&quot;648px&quot;&gt;&lt;img alt=&quot;Use native in vanilla lazyload&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot; src=&quot;https://andreaverlicchi.eu/img/22t26E0XUI-648.png&quot; width=&quot;648&quot; height=&quot;339&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;wait-what&quot; tabindex=&quot;-1&quot;&gt;Wait... what? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/#wait-what&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In case you missed Addy Osmani&#39;s article, it will be possible to &lt;em&gt;natively&lt;/em&gt; lazy load images through the &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt; attribute on images and iframes, and it&#39;s already possible on Chrome 75 (currently Canary).&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;...&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;iframe&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;...&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;iframe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;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 &lt;em&gt;about to enter the viewport&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The problem is that if you directly assign the &lt;code&gt;src&lt;/code&gt; (and/or &lt;code&gt;srcset&lt;/code&gt;) to the images, browsers that still don&#39;t support native lazy loading would download them all immediately, and this is something you might want to avoid in order to save bandwidth and speed up your website or web application.&lt;/p&gt;
&lt;p&gt;For this reason, I added the &lt;code&gt;use_native&lt;/code&gt; option in version 12 of &lt;em&gt;vanilla-lazyload&lt;/em&gt; which enables native lazy-loading where supported.&lt;/p&gt;
&lt;p&gt;More info on native lazy loading can be found on Addy Osmani&#39;s post &lt;a href=&quot;https://addyosmani.com/blog/lazy-loading/&quot;&gt;native image lazy-loading&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-browser-you-need&quot; tabindex=&quot;-1&quot;&gt;The browser you need &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/#the-browser-you-need&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As of 10th April 2019, native lazy-loading is in the early stages (dev preview) and it&#39;s available only in Chrome 75 (currently Canary), and under a flag. So in order to test it, you need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/chrome/canary/&quot;&gt;Download Chrome Canary&lt;/a&gt; and install it&lt;/li&gt;
&lt;li&gt;In Chrome Canary, go to the URL &lt;em&gt;chrome://flags&lt;/em&gt; and enable the following flags:
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Enable lazy image loading&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Enable lazy iframe loading&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Restart Chrome Canary&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;demo&quot; tabindex=&quot;-1&quot;&gt;Demo &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/#demo&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you have the Chrome Canary browser with the native lazy loading enabled, you can get started visiting the following demo page.&lt;/p&gt;
&lt;p&gt;→ &lt;a href=&quot;https://verlok.github.io/vanilla-lazyload/demos/native_lazyload_conditional.html&quot;&gt;Open the demo&lt;/a&gt; &lt;em&gt;and/or&lt;/em&gt; &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/blob/master/demos/native_lazyload_conditional.html&quot;&gt;Check the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you did everything correctly, that&#39;s what will happen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On Chrome 75 (Canary), LazyLoad will trigger the &lt;strong&gt;native lazy-loading&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;On other browsers and older versions of Chrome, the &lt;strong&gt;js-based lazy loading&lt;/strong&gt; will occur&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;try-it-on-your-website&quot; tabindex=&quot;-1&quot;&gt;Try it on your website! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/#try-it-on-your-website&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to try it yourself, you need to follow the following steps.&lt;/p&gt;
&lt;h3 id=&quot;markup&quot; tabindex=&quot;-1&quot;&gt;Markup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/#markup&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To make sure that your users see your images as soon as possible, I recommend to immediately load the topmost images of your webpage, only the ones that you know that will be placed &lt;em&gt;above-the-fold&lt;/em&gt; in the most common viewports, considering smartphones, tablets and computers.&lt;/p&gt;
&lt;p&gt;To do that, the first images in the page should be loaded using regular &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags. You can use the &lt;code&gt;loading=&amp;quot;eager&amp;quot;&lt;/code&gt; attribute to make sure they load as soon as possible.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;eager-eagle.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;eager&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Eager Eagle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All other &lt;em&gt;below-the-fold&lt;/em&gt; images should be loaded using the &lt;code&gt;data-src&lt;/code&gt;, &lt;code&gt;data-srcset&lt;/code&gt; and &lt;code&gt;data-sizes&lt;/code&gt; attributes instead of &lt;code&gt;src&lt;/code&gt;, &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt;, to avoid an eager loading in browsers not supporting &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy-sloth.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Lazy Sloth&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Link:&lt;/strong&gt; for a complete guide on how to lazy load responsive images, read &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/lazy-load-responsive-images-in-2019-srcset-sizes-more&quot;&gt;more about lazy loading responsive images&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;now-to-the-javascript-code&quot; tabindex=&quot;-1&quot;&gt;Now to the Javascript code! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/#now-to-the-javascript-code&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You&#39;re gonna need vanilla-lazyload version 12.
&lt;br&gt;You can include it via a CDN:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdn.jsdelivr.net/npm/vanilla-lazyload@12.0.0/dist/lazyload.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or install it using npm:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install vanilla-lazyload@12.0.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In your code, set the option &lt;code&gt;use_native&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; when instantiating LazyLoad:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;elements_selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.lazy&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;use_native&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This one&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;use_native: true&lt;/code&gt; flag sets up these contextual behaviors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;where native lazy loading is supported, LazyLoad adds the &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt; attribute to the images, then just swaps the &lt;code&gt;data-*&lt;/code&gt; attributes for the proper ones. Now the browser will manage the lazy loading itself.&lt;/li&gt;
&lt;li&gt;where native lazy loading is NOT supported, the lazy loading continues to be managed by Javascript, leveraging the browser&#39;s IntersectionObserver API.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;to-wrap-up&quot; tabindex=&quot;-1&quot;&gt;To wrap up &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/native-lazy-loading-with-vanilla-lazyload/#to-wrap-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Loading content lazily is very important to &lt;strong&gt;improve a website loading speed&lt;/strong&gt;, browser vendors are finally starting to implement it natively and I can&#39;t wait for it to be available on Edge, Safari and Firefox.&lt;/p&gt;
&lt;p&gt;Until then, you can have &lt;strong&gt;both native lazy loading and js-based lazy loading&lt;/strong&gt; using &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload 12&lt;/a&gt;, just setting the &lt;code&gt;use_native&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Give it a try!&lt;/p&gt;
&lt;p&gt;If you like it, &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;star ⭐ the repo&lt;/a&gt;. If you find something wrong, &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/issues&quot;&gt;file an issue&lt;/a&gt; so I can try and fix it. For any questions, &lt;a href=&quot;https://twitter.com/verlok&quot;&gt;reach me on twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Responsive and accessible table design</title>
		<link href="https://andreaverlicchi.eu/en/blog/tables-look-like-lists-look-like-tables-accessible-responsive-design/"/>
		<updated>2019-03-08T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/tables-look-like-lists-look-like-tables-accessible-responsive-design/</id>
		<content type="html">&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;So let’s say you have an HTML &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; containing some orders, each one having:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a picture&lt;/li&gt;
&lt;li&gt;a description&lt;/li&gt;
&lt;li&gt;a price&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And you need to make it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;look like a list&lt;/strong&gt; on small viewports, typically smartphones&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;look like a table&lt;/strong&gt; on larger viewports, like tablets and computers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;accessible&lt;/strong&gt; (see &lt;a href=&quot;https://www.w3.org/standards/webdesign/accessibility&quot;&gt;accessibility&lt;/a&gt;), e.g. to blind users&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;table-markup&quot; tabindex=&quot;-1&quot;&gt;Table markup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/tables-look-like-lists-look-like-tables-accessible-responsive-design/#table-markup&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&#39;s the markup of the table you&#39;ve got.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;thead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;col&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Photo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;th&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;col&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Description&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;th&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;col&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Price&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;th&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;thead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tbody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/70x100&amp;amp;text=Product&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Description&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;EUR 12.345&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/70x100&amp;amp;text=Product&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Description&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;EUR 12.345&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tbody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The solution in this case would be to &lt;code&gt;display: flex&lt;/code&gt; the rows, then set their cells direction to vertical using &lt;code&gt;flex-direction: column&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;flex-direction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; column&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 400px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;flex-direction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And boom. Here&#39;s the example on codepen.&lt;/p&gt;
&lt;iframe loading=&quot;lazy&quot; height=&quot;350&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Table markup, list layout (on small viewports)&quot; src=&quot;https://codepen.io/verlok/embed/GeWXGy/?height=350&amp;theme-id=light&amp;default-tab=html,result&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/verlok/pen/GeWXGy/&quot;&gt;Table markup, list layout (on small viewports)&lt;/a&gt; by Andrea Verlicchi
  (&lt;a href=&quot;https://codepen.io/verlok&quot;&gt;@verlok&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;h2 id=&quot;but-is-this-really-a-table&quot; tabindex=&quot;-1&quot;&gt;But is this really a table? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/tables-look-like-lists-look-like-tables-accessible-responsive-design/#but-is-this-really-a-table&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Is &lt;code&gt;table&lt;/code&gt; the right tag to use here? Is there a chance that we might have used the &lt;code&gt;table&lt;/code&gt; tag only for layout simplicity? I mean, isn&#39;t it just a &lt;strong&gt;list&lt;/strong&gt; of orders? So why don&#39;t use a &lt;code&gt;ul&lt;/code&gt; instead?&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;photo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/70x100&amp;amp;text=Product&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Description&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;EUR 12.345&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;photo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/70x100&amp;amp;text=Product&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Description&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;EUR 12.345&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, in the CSS, we just need to make the &lt;code&gt;div&lt;/code&gt;s inside the list items to be aligned horizontally, when there&#39;s enough space to do this.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 400px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&#39;s the result:&lt;/p&gt;
&lt;iframe loading=&quot;lazy&quot; height=&quot;350&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;List markup, table layout (on large viewports)&quot; src=&quot;https://codepen.io/verlok/embed/pYeOwq/?height=350&amp;theme-id=light&amp;default-tab=html,result&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/verlok/pen/pYeOwq/&quot;&gt;List markup, table layout (on large viewports)&lt;/a&gt; by Andrea Verlicchi
  (&lt;a href=&quot;https://codepen.io/verlok&quot;&gt;@verlok&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;h2 id=&quot;accessibility-considerations&quot; tabindex=&quot;-1&quot;&gt;Accessibility considerations &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/tables-look-like-lists-look-like-tables-accessible-responsive-design/#accessibility-considerations&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;table&lt;/code&gt;s can be very accessible if you &lt;a href=&quot;https://webaim.org/techniques/tables/data&quot;&gt;code them properly&lt;/a&gt;, but I think it only makes sense to use &lt;code&gt;table&lt;/code&gt;s when the data in each data cell have at least 2 headings: one at the beginning of its column and one at beginning of its row.&lt;/p&gt;
&lt;p&gt;If it&#39;s only a title per each column you have, and you have a few columns, it&#39;s probably better to consider it a list and markup it like a list, using &lt;code&gt;ul&lt;/code&gt; or &lt;code&gt;ol&lt;/code&gt; as you prefer. Make sure you choose properly!&lt;/p&gt;
&lt;p&gt;Last but not least, if you have a non-table markup (&lt;code&gt;ul&lt;/code&gt;, &lt;code&gt;div&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt;) that you are displaying as a table, and you want to make it accessible too, make sure you use &lt;a href=&quot;https://www.w3.org/TR/wai-aria-practices/examples/table/table.html&quot;&gt;ARIA roles&lt;/a&gt; to define your &lt;code&gt;rowgroup&lt;/code&gt;s, your &lt;code&gt;columnheader&lt;/code&gt;s and &lt;code&gt;rowheader&lt;/code&gt;s, your &lt;code&gt;cell&lt;/code&gt;s, etc.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/tables-look-like-lists-look-like-tables-accessible-responsive-design/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can use flexbox to easily make a table look like a list, or a list look like a table. Keep accessibility in mind! When coding tables use table headers for rows and columns. When coding pseudo-tables use ARIA roles to define which is what.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Lazy load responsive images in 2019</title>
		<link href="https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/"/>
		<updated>2019-03-01T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/</id>
		<content type="html">&lt;p&gt;In the latest years, both at my job and as maintainer of a &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;LazyLoad script&lt;/a&gt;, I&#39;ve specialized in &lt;strong&gt;lazy loading&lt;/strong&gt; of &lt;strong&gt;responsive images&lt;/strong&gt;. Today I&#39;m going to show you what HTML, CSS and JavaScript code you need to write &lt;em&gt;in 2019&lt;/em&gt; in order to serve responsive images &lt;em&gt;and&lt;/em&gt; load them lazily. In the second part of the post, I&#39;m also showing how to make the browser &lt;strong&gt;natively pick the WebP image&lt;/strong&gt; when it supports it.&lt;/p&gt;
&lt;h2 id=&quot;old-article&quot; tabindex=&quot;-1&quot;&gt;Old article! 👀 &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#old-article&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Hold on! You&#39;re reading an old version of this article.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp&quot;&gt;Read the &lt;strong&gt;2020 update&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;responsive-lazy-what&quot; tabindex=&quot;-1&quot;&gt;Responsive lazy what? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#responsive-lazy-what&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Responsive images&lt;/strong&gt; are the images that adapt to the user&#39;s screen &lt;em&gt;while&lt;/em&gt; keeping our websites fast by downloading just the right image source for the right &lt;strong&gt;viewport witdh&lt;/strong&gt; (from small devices to large desktop computers), also considering the user&#39;s &lt;strong&gt;screen density&lt;/strong&gt; (retina display, hiDpi, etc.).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lazy loading images&lt;/strong&gt; is a technique to make your website faster by &lt;strong&gt;avoiding to load below the fold images&lt;/strong&gt;, then loading them &lt;strong&gt;as they enter the viewport&lt;/strong&gt;. Beyond performance, this also allows you to save bandwith and money, e.g. if you&#39;re paying a CDN service for your images.&lt;/p&gt;
&lt;h2 id=&quot;got-it-now-show-me-some-code&quot; tabindex=&quot;-1&quot;&gt;Got it! Now show me some code! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#got-it-now-show-me-some-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;→ &lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/demos/image_srcset_lazy_sizes.html&quot;&gt;Take a look at the results&lt;/a&gt; ← that you will achieve. Open your browser&#39;s &lt;strong&gt;developer tools&lt;/strong&gt; and switch to the &lt;strong&gt;network panel&lt;/strong&gt;. You will see that the first images are loaded immediately (or &lt;em&gt;eagerly&lt;/em&gt;) at page landing, while the rest of the images are loaded as you &lt;strong&gt;scroll down&lt;/strong&gt; the document.&lt;/p&gt;
&lt;h3 id=&quot;the-html-markup&quot; tabindex=&quot;-1&quot;&gt;The HTML markup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#the-html-markup&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Here&#39;s the markup of an immediately loaded responsive image.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Immediately loaded, responsive image --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Image 01&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=Img+01&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
		https://via.placeholder.com/220x280?text=Img+01 220w,
		https://via.placeholder.com/440x560?text=Img+01 440w
	&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To make sure that your users will see your images &lt;strong&gt;as soon as possible&lt;/strong&gt;, I recommend to &lt;strong&gt;immediately load the topmost images&lt;/strong&gt; of your webpage, only the ones that will be placed &lt;em&gt;above the fold&lt;/em&gt; in most common viewports, considering smartphones, tablets and computers.&lt;/p&gt;
&lt;p&gt;Always remember that lazy loading is a Javascript-based task, so before any lazy image &lt;strong&gt;can start downloading&lt;/strong&gt;, your Javascript code needs to be &lt;strong&gt;downloaded, parsed and executed&lt;/strong&gt;, your lazy images must be &lt;strong&gt;found in the DOM&lt;/strong&gt;, &lt;strong&gt;their position evaluated&lt;/strong&gt;, and these operations are going to take a while.&lt;/p&gt;
&lt;p&gt;And here&#39;s the markup you&#39;re going to need in order to &lt;em&gt;lazy load&lt;/em&gt; a responsive image.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Lazy loaded responsive image --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Image 03&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=Img+03&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=Img+03 220w,
        https://via.placeholder.com/440x560?text=Img+03 440w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want your lazy images to have a low-quality preview image while they load, you can put a small, low-quality image in the &lt;code&gt;src&lt;/code&gt; tag like the following.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Lazy loaded responsive image with low-quality preview --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Image 03&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/11x14?text=Img+03&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=Img+03&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/220x280?text=Img+03 220w,
        https://via.placeholder.com/440x560?text=Img+03 440w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re using the &lt;code&gt;img&lt;/code&gt; HTML tag and not the &lt;code&gt;picture&lt;/code&gt; tag, since the latter is not necessary in this case. I&#39;ll dig into the &lt;code&gt;picture&lt;/code&gt; tag use cases &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#picture-tag-use-cases&quot;&gt;down below&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;But hey, what about Internet Explorer?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s true, Internet Explorer does not support responsive images, but given that only its latest version stuck around and it&#39;s slowly disappearing from our radars (in the websites we manage, its share is around 4%), I&#39;d suggest NOT to use a responsive images polyfill for it, and just rely on the image specified in the &lt;code&gt;src&lt;/code&gt; (or &lt;code&gt;data-src&lt;/code&gt;) attribute instead.&lt;/p&gt;
&lt;h3 id=&quot;script-inclusion&quot; tabindex=&quot;-1&quot;&gt;Script inclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#script-inclusion&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To load the lazy images as they enter the viewport, you need a lazy load script such as &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; which is a lightweight-as-air (1.9 kb gzipped), configurable, SEO-friendly script that I&#39;ve been developing and improving since 2014. It&#39;s also based on the IntersectionObserver browser API so it&#39;s blazing fast and grants jank-free scrolling also on slower devices.&lt;/p&gt;
&lt;p&gt;Here is the simplest way to include the script in your page.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdn.jsdelivr.net/npm/vanilla-lazyload@11.0.4/dist/lazyload.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Other ways to include LazyLoad in your web pages, like using an &lt;code&gt;async&lt;/code&gt; script with auto-init, using RequireJS, using WebPack or Rollup, are &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/#include-lazyload-in-your-project&quot;&gt;documented here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;lazyload-initialization&quot; tabindex=&quot;-1&quot;&gt;LazyLoad initialization &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#lazyload-initialization&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You need LazyLoad to manage and load all the images with the &lt;code&gt;.lazy&lt;/code&gt; class in the page. You can initialize &lt;code&gt;LazyLoad&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; lazyLoad &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;elements_selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.lazy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// More options here&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;some-css-tricks&quot; tabindex=&quot;-1&quot;&gt;Some CSS Tricks &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#some-css-tricks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are also some features that you can achieve using CSS only. You need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Make not-yet-loaded lazy images to occupy some space&lt;/strong&gt;. If you don&#39;t do so, those images will have height &lt;code&gt;0&lt;/code&gt; and they&#39;ll collapse one next to another. As a result, all of them will enter the viewport all at the same time, nullifying our efforts to load them as they enter the viewport.&lt;/li&gt;
&lt;li&gt;Avoid empty images to appear as broken images&lt;/li&gt;
&lt;li&gt;Resolve a Firefox anomaly that displays the broken image icon while images are loading&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can do all that using this CSS rules:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*
Makes images container to occupy some space
when the images aren&#39;t loaded yet.
This value depends on your layout.
*/&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.imageList li&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 300px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
Avoid empty images to appear as broken
*/&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;img:not([src]):not([srcset])&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;visibility&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
Fixes the Firefox anomaly while images are loading
*/&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@-moz-document&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;url-prefix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token selector&quot;&gt;img:-moz-loading&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token property&quot;&gt;visibility&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;picture-tag-use-cases&quot; tabindex=&quot;-1&quot;&gt;Picture tag use cases &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#picture-tag-use-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Until now, I wrote about the &lt;code&gt;img&lt;/code&gt; tag with the &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; attributes, which is the solution to the vast majority of the responsive images you might need and use on a website or web application. Now, in which cases should you use the &lt;code&gt;picture&lt;/code&gt; tag?&lt;/p&gt;
&lt;h3 id=&quot;different-width-height-ratio&quot; tabindex=&quot;-1&quot;&gt;Different width/height ratio &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#different-width-height-ratio&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use case: you need to show images with different &lt;strong&gt;width/height ratio&lt;/strong&gt; depending on a media query. e.g. you want to show &lt;em&gt;portrait&lt;/em&gt; images on mobile, vertical devices, &lt;em&gt;landscape&lt;/em&gt; on wider viewports, like tablets and computers.&lt;/p&gt;
&lt;p&gt;→ &lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/demos/picture_media.html&quot;&gt;Take a look at the results&lt;/a&gt; ←&lt;/p&gt;
&lt;p&gt;Here&#39;s the code you&#39;re gonna need in this case. In order to have immediately loaded images, just use the plain &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;srcset&lt;/code&gt; attributes, without &lt;code&gt;data-&lt;/code&gt; prefix.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 1024px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/1024x576?text=Horizontal+Image 1x,
      https://via.placeholder.com/2048x1152?text=Horizontal+Image 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 1023px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/640x960?text=Vertical+Image 1x,
      https://via.placeholder.com/1280x1920?text=Vertical+Image 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Stivaletti&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/1024x576?text=Horizontal+Image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;automatically-switch-to-webp&quot; tabindex=&quot;-1&quot;&gt;Automatically switch to WebP &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#automatically-switch-to-webp&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use case: you want the browser to &lt;strong&gt;automatically pick the WebP format&lt;/strong&gt; depending on its support for that format.&lt;/p&gt;
&lt;p&gt;→ &lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/demos/picture_type_webp.html&quot;&gt;Take a look at the results&lt;/a&gt; ←&lt;/p&gt;
&lt;p&gt;Here&#39;s the code! Again, in order to obtain immediately loaded images, just use the plain &lt;code&gt;src&lt;/code&gt;, &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; attributes, without &lt;code&gt;data-&lt;/code&gt; prefix.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/webp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/1024x576?text=WebP+Image 1x,
      https://via.placeholder.com/2048x1152?text=WebP+Image 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/256.jpg?text=1024x576+Jpg+Image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://via.placeholder.com/1024x576?text=Jpg+Image 1x,
      https://via.placeholder.com/2048x1152?text=Jpg+Image 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;data-sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;220px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;An image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;one-more-thing&quot; tabindex=&quot;-1&quot;&gt;&lt;em&gt;One more thing&lt;/em&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#one-more-thing&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The vanilla &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;LazyLoad script&lt;/a&gt; leverages the IntersectionObserver API so, in browser not supporting it like Internet Explorer and older versions of Safari, it will load all images as soon as it executes, which leads more or less to the same result as if no LazyLoad was ever used on the page.&lt;/p&gt;
&lt;p&gt;If you want to load your content lazily in the 100% of the browsers out there (I wouldn&#39;t, but it&#39;s up to you), you need to include the &lt;a href=&quot;https://github.com/w3c/IntersectionObserver/tree/master/polyfill&quot;&gt;IntersectionObserver Polyfill&lt;/a&gt; script before LazyLoad.&lt;/p&gt;
&lt;p&gt;You can either you put the script in the page just before the LazyLoad one, as it follows...&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdn.jsdelivr.net/npm/intersection-observer@0.5.1/intersection-observer.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdn.jsdelivr.net/npm/vanilla-lazyload@11.0.4/dist/lazyload.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...or you can load it the polyfill as a dependency of LazyLoad using &lt;em&gt;RequireJS&lt;/em&gt; or another AMD module loader. &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/blob/master/README.md#include-via-requirejs-without-intersectionobserver-polyfill&quot;&gt;More info here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot; tabindex=&quot;-1&quot;&gt;Conclusions &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#conclusions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is a summary:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Don&#39;t load all the images lazily, just the ones &lt;em&gt;below the fold&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;img&lt;/code&gt; tag to do simple responsive images&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;picture&lt;/code&gt; tag to conditinally serve the WebP version of your images, or to change your images ratio&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/&quot;&gt;vanilla-lazyload&lt;/a&gt; to load your lazy images.&lt;/li&gt;
&lt;li&gt;Optionally use the IntersectionObserver polyfill if you want to load lazily on 100% of the browsers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If something is unclear or could be improved, please &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out&lt;/a&gt; and let me know.&lt;/p&gt;
&lt;p&gt;If you did find this useful, feel free to share it!&lt;/p&gt;
&lt;h3 id=&quot;useful-resources&quot; tabindex=&quot;-1&quot;&gt;Useful resources &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-in-2019-srcset-sizes-more/#useful-resources&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://alistapart.com/article/responsive-images-in-practice&quot;&gt;Responsive images in practice&lt;/a&gt; @ A List Apart&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images&quot;&gt;Responsive images&lt;/a&gt; @ Mozilla Developer Network&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/responsive-images-css/&quot;&gt;Responsive images in CSS&lt;/a&gt; @ CSS Tricks&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://responsiveimages.org&quot;&gt;Responsive images community group&lt;/a&gt; website&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>Check if an element is still inside viewport after a given time</title>
		<link href="https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/"/>
		<updated>2018-08-27T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/</id>
		<content type="html">&lt;p&gt;What would you do if somebody asked you to load a DOM element only if it &lt;strong&gt;stays inside the viewport for a given time&lt;/strong&gt;? You would use &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt;, wouldn&#39;t you? 😉 This is exactly what the GitHub community asked for as new feature in LazyLoad, to &lt;strong&gt;avoid loading elements which users skipped&lt;/strong&gt; by &lt;strong&gt;scrolling fast beyond them&lt;/strong&gt;. In this post, I&#39;d like to share the solution with you.&lt;/p&gt;
&lt;p&gt;There are a couple of ways of doing this. The first one is check the element&#39;s posistion over time, the second one leverages &lt;code&gt;IntersectionObserver&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-slow-way-without-intersectionobserver&quot; tabindex=&quot;-1&quot;&gt;The (slow) way without IntersectionObserver &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#the-slow-way-without-intersectionobserver&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This way is much slower that using &lt;code&gt;IntersectionObserver&lt;/code&gt; because it implies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;watching browser’s &lt;code&gt;scroll&lt;/code&gt; and &lt;code&gt;resize&lt;/code&gt; events to call a (throttled) callback&lt;/li&gt;
&lt;li&gt;in the callback, loop through every watched element and call a &lt;code&gt;isInsideViewport&lt;/code&gt; function to check if they are inside the viewport&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;isInsideViewport&lt;/code&gt; function then checks a &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/blob/support/8.x/src/lazyload.viewport.js&quot;&gt;bunch of things&lt;/a&gt; like the element&#39;s &lt;code&gt;getBoundingClientRect&lt;/code&gt;, the window&#39;s &lt;code&gt;innerHeight&lt;/code&gt;, &lt;code&gt;pageYOffset&lt;/code&gt;, etc. and returns a boolean&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these only to know when elements enter the viewport.&lt;/p&gt;
&lt;p&gt;To know whether or not a given element stayed inside the viewport for a given time, you should do something like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;when the element enters the viewport, &lt;code&gt;setTimeout&lt;/code&gt; a function. Let&#39;s call it &lt;code&gt;isStillInsideViewport&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;in the &lt;code&gt;isStillInsideViewport&lt;/code&gt; function, check if the element is still inside the viewport calling &lt;code&gt;isInsideViewport&lt;/code&gt; on that element, then:
&lt;ul&gt;
&lt;li&gt;if it is, load it and remove it from the watched elements&lt;/li&gt;
&lt;li&gt;if it&#39;s NOT, don&#39;t load it and keep watching it&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Quite straightforward as a thought, but not that fast executing.&lt;/p&gt;
&lt;h2 id=&quot;the-way-with-intersectionobserver&quot; tabindex=&quot;-1&quot;&gt;The way with IntersectionObserver &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#the-way-with-intersectionobserver&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This way is much faster because it only implies the following.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you set an &lt;code&gt;IntersectionObserver&lt;/code&gt; and use it to observe all your watched elements&lt;/li&gt;
&lt;li&gt;it calls a &lt;code&gt;onIntersection&lt;/code&gt; function each time an element intersects with the viewport&lt;/li&gt;
&lt;li&gt;you can do the loading logic inside the &lt;code&gt;onIntersection&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No need to watch browser’s &lt;code&gt;scroll&lt;/code&gt; nor &lt;code&gt;resize&lt;/code&gt; events.&lt;/p&gt;
&lt;h3 id=&quot;first-idea&quot; tabindex=&quot;-1&quot;&gt;First idea &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#first-idea&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My first thought was to do it without &lt;code&gt;IntersectionObserver&lt;/code&gt;, meaning I&#39;d have to check the &amp;quot;is inside viewport&amp;quot; state after a timeout.&lt;/p&gt;
&lt;p&gt;Turns out there is not an elegant way to check if an element is inside the viewport with &lt;code&gt;IntersectionObserver&lt;/code&gt;. All you get are callbacks when an element intersects with the viewport.&lt;/p&gt;
&lt;h3 id=&quot;discovering-thresholds&quot; tabindex=&quot;-1&quot;&gt;Discovering thresholds &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#discovering-thresholds&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;But wait, what is that &lt;code&gt;IntersectionObserver&lt;/code&gt;&#39;s &lt;code&gt;thresholds&lt;/code&gt; option in the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API&quot;&gt;doc&lt;/a&gt;? 😲&lt;/p&gt;
&lt;p&gt;Says MDN:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Either a single number or an array of numbers which indicate at what percentage of the target&#39;s visibility the observer&#39;s callback should be executed. If you only want to detect when visibility passes the 50% mark, you can use a value of 0.5. If you want the callback run every time visibility passes another 25%, you would specify the array [0, 0.25, 0.5, 0.75, 1]. The default is 0 (meaning as soon as even one pixel is visible, the callback will be run). A value of 1.0 means that the threshold isn&#39;t considered passed until every pixel is visible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After I fiddled around with the option and tried the result in a specific &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/blob/master/demos/delay_test.html&quot;&gt;delay load demo&lt;/a&gt;, I found out that passing &lt;code&gt;0&lt;/code&gt; to the &lt;code&gt;thresholds&lt;/code&gt; option (which is the default value), the &lt;code&gt;onIntersection&lt;/code&gt; function is called also when the element &lt;em&gt;leaves&lt;/em&gt; the viewport.&lt;/p&gt;
&lt;h3 id=&quot;ultimate-solution&quot; tabindex=&quot;-1&quot;&gt;Ultimate solution &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#ultimate-solution&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that I knew when an element &lt;strong&gt;leaves the viewport&lt;/strong&gt;, it&#39;s &lt;strong&gt;much easier to solve the main problem&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The solution, ultimately, is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;when an element enters the viewport, &lt;code&gt;setTimeout&lt;/code&gt; a function to load the element&lt;/li&gt;
&lt;li&gt;store each timeout ID in a &lt;code&gt;data-&lt;/code&gt; attribute of the related element&lt;/li&gt;
&lt;li&gt;let the element load when the timeout occurs&lt;/li&gt;
&lt;li&gt;if the element leaves the viewport before the timeout is executed, cancel the timeout with &lt;code&gt;clearTimeout&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s linear and easy! 😊&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;show-me-the-code&quot; tabindex=&quot;-1&quot;&gt;Show me the code! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#show-me-the-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can find the full code in vanilla-lazyload&#39;s &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/blob/master/src/lazyload.js&quot;&gt;&lt;code&gt;lazyload.js&lt;/code&gt;&lt;/a&gt; file + related imports. If you don&#39;t feel like jumping from one file to another, you could also open the bundled file &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/blob/master/dist/lazyload.es2015.js&quot;&gt;&lt;code&gt;lazyload.es2015.js&lt;/code&gt;&lt;/a&gt; from the &lt;code&gt;dist&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;simplified version&lt;/strong&gt; of the code is provided below for your convenience.&lt;/p&gt;
&lt;h3 id=&quot;setting-intersectionobserver&quot; tabindex=&quot;-1&quot;&gt;Setting IntersectionObserver &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#setting-intersectionobserver&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; gObserver &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IntersectionObserver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onIntersection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;rootMargin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0px&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;rootMargin&lt;/code&gt; option set to &lt;code&gt;0px&lt;/code&gt; here means: &amp;quot;observe the actual viewport size&amp;quot;. You could pass any CSS length in order to expand the observed area. E.g. passing &lt;code&gt;300px&lt;/code&gt; would expand it by that length on top, right, bottom, and left.&lt;/p&gt;
&lt;h3 id=&quot;onintersection-function&quot; tabindex=&quot;-1&quot;&gt;onIntersection function &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#onintersection-function&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This function is called each time an intersection occurs and the parameter is the set of entries that intersected with the viewport.&lt;/p&gt;
&lt;p&gt;Assuming &lt;code&gt;watchedElements&lt;/code&gt; are the elements being watched by the script (see below), after each intersection they should be purged from the elements we already dealt with (loaded).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;purgeElements&lt;/code&gt; function is out of the scope of this post, but it returns a subset of the watchedElements.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;onIntersection&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;entries&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  entries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;manageIntersection&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  watchedElements &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;purgeElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;watchedElements&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;manageintersection-function&quot; tabindex=&quot;-1&quot;&gt;manageIntersection function &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#manageintersection-function&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This function is called on each entry that intersected with the viewport. Both on enter and exit.&lt;/p&gt;
&lt;p&gt;On enter, it starts the delayed loading of the element. On exit, it cancels it.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;manageIntersection&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; element &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isIntersecting&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;delayLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; delayTime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;cancelDelayLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;isintersecting-utility-function&quot; tabindex=&quot;-1&quot;&gt;isIntersecting utility function &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#isintersecting-utility-function&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is a utility function to understand whether or not an entry is intersecting with the viewport.&lt;/p&gt;
&lt;p&gt;Note that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;entry.isIntersecting&lt;/code&gt; needs fallback because it is &lt;code&gt;null&lt;/code&gt; on some versions of Microsoft Edge&lt;/li&gt;
&lt;li&gt;&lt;code&gt;entry.intersectionRatio&lt;/code&gt; is not enough alone because it could be &lt;code&gt;0&lt;/code&gt; on some intersecting elements&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;isIntersecting&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isIntersecting &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;intersectionRatio &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;delayload-function&quot; tabindex=&quot;-1&quot;&gt;delayLoad function &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#delayload-function&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is the function that delays the load of the element by &lt;code&gt;delayTime&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;getTimeoutData&lt;/code&gt; and &lt;code&gt;setTimeoutData&lt;/code&gt; are utility functions to get and set the timeout ID from a data-attribute on the element.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;delayLoad&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; delayTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; timeoutId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getTimeoutData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timeoutId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// timeout was already set, do nothing&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  timeoutId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;loadAndUnobserve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;cancelDelayLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; delayTime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setTimeoutData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeoutId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;canceldelayload-function&quot; tabindex=&quot;-1&quot;&gt;cancelDelayLoad function &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#canceldelayload-function&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This function&#39;s duty is to cancel the element timeout, if it&#39;s set.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;cancelDelayLoad&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; timeoutId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getTimeoutData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;timeoutId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// do nothing if timeout doesn&#39;t exist&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;clearTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timeoutId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;deleteTimeoutData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;loadandunobserve-function&quot; tabindex=&quot;-1&quot;&gt;loadAndUnobserve function &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#loadandunobserve-function&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This immediately loads the element, and takes it away from the &lt;code&gt;IntersectionObserver&lt;/code&gt;&#39;s observed elements.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;loadAndUnobserve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Here&#39;s what you actually do something with the element&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;revealElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  gObserver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unobserve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;at-my-signal-unleash-hell&quot; tabindex=&quot;-1&quot;&gt;At my signal, unleash hell! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#at-my-signal-unleash-hell&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We did everything good until now, but we didn&#39;t start anything yet! We need a set of &lt;code&gt;watchedElements&lt;/code&gt; to observe with our &lt;code&gt;IntersectionObserver&lt;/code&gt;, or nothing will happen.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; watchedElements &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;img&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
watchedElements&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; gObserver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;all-together-now&quot; tabindex=&quot;-1&quot;&gt;All together now &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#all-together-now&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can find a working version of the code above on CodeSandbox for you to play around with it!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://codesandbox.io/s/mzokk46vlx&quot;&gt;&lt;img src=&quot;https://codesandbox.io/static/img/play-codesandbox.svg&quot; alt=&quot;Check if an element is still inside viewport after a given time&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;final-words&quot; tabindex=&quot;-1&quot;&gt;Final words &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/#final-words&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;See how easy is it to check if an element is still inside the viewport after some time using &lt;code&gt;IntersectionObserver&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;For more information about how to create LazyLoad using &lt;code&gt;IntersectionObserver&lt;/code&gt;, see &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/check-if-element-still-inside-viewport-after-given-time/using-intersection-observers-to-create-vanilla-lazyload&quot;&gt;Intersection Observer and Lazy Load of elements&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Is there something you would have done differently, or do you agree with what I did here? Please &lt;a href=&quot;https://andreaverlicchi.eu/contact/&quot;&gt;reach out&lt;/a&gt; and let me know!&lt;/p&gt;
&lt;p&gt;If you want to show some love to LazyLoad, &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;star it on GitHub&lt;/a&gt;! ⭐&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Create a JavaScript library using ES2015 modules, Gulp, Rollup and Jest</title>
		<link href="https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/"/>
		<updated>2017-09-09T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/</id>
		<content type="html">&lt;p&gt;Let&#39;s see how to write a JavaScript library using &lt;a href=&quot;https://babeljs.io/learn-es2015/&quot;&gt;ES2015&lt;/a&gt; transpiled with &lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt;, featuring &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import&quot;&gt;ES modules&lt;/a&gt; packed up using &lt;a href=&quot;https://rollupjs.org/&quot;&gt;Rollup&lt;/a&gt; via &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/gulp.js&quot;&gt;Gulp&lt;/a&gt;, and &lt;a href=&quot;https://facebook.github.io/jest/&quot;&gt;Jest&lt;/a&gt; to test your code.&lt;/p&gt;
&lt;p&gt;Here I&#39;m sharing the experience I had while developing my &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt; script, since at the time I didn&#39;t find anything that explained how to use those libraries together, especially &lt;strong&gt;Rollup and Jest&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;installing-gulp&quot; tabindex=&quot;-1&quot;&gt;Installing Gulp &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#installing-gulp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Gulp is a &lt;strong&gt;task runner&lt;/strong&gt; similar to &lt;a href=&quot;https://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt; for automating painful or time-consuming tasks in your development workflow. I chose to migrate &lt;strong&gt;from Grunt to Gulp&lt;/strong&gt; because the latter is blazing fast, being it based on Node&#39;s &lt;a href=&quot;https://medium.freecodecamp.org/node-js-streams-everything-you-need-to-know-c9141306be93&quot;&gt;streams&lt;/a&gt; instead of the file system.&lt;/p&gt;
&lt;p&gt;In order to use Gulp, you need to install Gulp locally to your project, to do so:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev gulp&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A good option to use Gulp is to install its command line executable with:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; gulp-cli&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For more information, I would suggest to read &lt;a href=&quot;https://css-tricks.com/gulp-for-beginners/&quot;&gt;Gulp for beginners&lt;/a&gt; on CSS tricks.&lt;/p&gt;
&lt;h2 id=&quot;configuring-gulp&quot; tabindex=&quot;-1&quot;&gt;Configuring gulp &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#configuring-gulp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Gulp execution requires a configuration file named &lt;code&gt;gulpfile.js&lt;/code&gt;. Create an empty one for now, I&#39;m going to show you what to put in it, step by step.&lt;/p&gt;
&lt;h3 id=&quot;1-linting-source-files&quot; tabindex=&quot;-1&quot;&gt;1. Linting source files &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#1-linting-source-files&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Being JavaScript a dynamic and loosely-typed language, is especially prone to developer errors. Linting tools like &lt;a href=&quot;https://eslint.org/&quot;&gt;ESLint&lt;/a&gt; allow developers to discover problems with their JavaScript code without executing it.&lt;/p&gt;
&lt;p&gt;To install ESLint for Gulp, just run:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev gulp-eslint&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in your empty &lt;code&gt;gulpfile.js&lt;/code&gt; add:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; gulp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; eslint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-eslint&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NODE_ENV&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;release&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./src/**/*.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// ----------- linting --------------&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eslint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eslint&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eslint&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;failAfterError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; fails if errors&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// --&gt; pipe more stuff here&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NOTE: Setting the &lt;code&gt;process.env.NODE_ENV&lt;/code&gt; variable is necessary to match the task we&#39;re running in the Babel configuration. I&#39;ll explain this &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#3-transpiling-to-es5-with-babel&quot;&gt;in a while&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;2-bundling-modules-with-rollup&quot; tabindex=&quot;-1&quot;&gt;2. Bundling modules with Rollup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#2-bundling-modules-with-rollup&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger, such as a library. It uses the new standardized format for code modules included in the ES2015 revision of JavaScript, today.&lt;/p&gt;
&lt;p&gt;Long story short, Rollup reads your main JavaScript file and generates a bigger file with all the modules included, automatically.&lt;/p&gt;
&lt;p&gt;Install rollup with:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev gulp-rollup gulp-rename&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in your gulpfile, just add a pipe command:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ----------- rolling up --------------&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rollup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;umd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;moduleName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;LazyLoad&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src/lazyload.js&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that Rollup has to produce a &lt;code&gt;umd&lt;/code&gt; type of module, the produced module name will be &lt;code&gt;LazyLoad&lt;/code&gt;, and the entry point to start looking for dependencies is &lt;code&gt;./src/lazyload.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since I want to distribute a version of the script which is not transpiled in ES5, I save it to &lt;code&gt;lazyload.es2015.js&lt;/code&gt; piping the &lt;code&gt;rename&lt;/code&gt; command and the &lt;code&gt;dest&lt;/code&gt; one.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lazyload.es2015.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFolder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; writing rolledup&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;destFolder&lt;/code&gt; is a JavaScript variable and it&#39;s just set to  &lt;code&gt;./dist&lt;/code&gt; inside our &lt;code&gt;gulpfile.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;NOTE: &lt;a href=&quot;https://webpack.github.io/&quot;&gt;Webpack&lt;/a&gt; is a similar bundling script which might be preferrable to bundle complex applications, but I noticed that the final code generated by Webpack would be much heavier, so Rollup worked better for me.&lt;/p&gt;
&lt;h3 id=&quot;3-transpiling-to-es5-with-babel&quot; tabindex=&quot;-1&quot;&gt;3. Transpiling to ES5 with Babel &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#3-transpiling-to-es5-with-babel&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Until now, we have bundled all our modules in a single file which will work in modern browsers only. Of course we also want to produce a file which is readable by &lt;em&gt;not so modern&lt;/em&gt; browsers.&lt;/p&gt;
&lt;p&gt;To install babel and its ES2015 preset, plus a plugin to transform &lt;code&gt;Object.assign()&lt;/code&gt; to ES5, do:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev babel-core gulp-babel babel-preset-es2015 babel-plugin-transform-object-assign&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, to babelize our previously rolled-up JavaScript and save it to &lt;code&gt;lazyload.js&lt;/code&gt;, let&#39;s require &lt;code&gt;gulp-babel&lt;/code&gt; and add the following pipe to our &lt;code&gt;gulpfile.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; babel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-babel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ----------- babelizing --------------&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;babel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lazyload.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFolder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; writing babelized es5 js&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The babel configuration has to be stored in an external &lt;code&gt;.babelrc&lt;/code&gt; file, that in my case looks like that:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;ignore&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;node_modules/**&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;env&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;presets&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;es2015&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;transform-object-assign&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;release&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;presets&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;es2015&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;modules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;sourceMap&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;transform-object-assign&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may have noticed that I configured two &lt;code&gt;env&lt;/code&gt;s differently:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;release&lt;/code&gt; is the one used by Rollup, in Gulp. Remember? We set it in the &lt;code&gt;gulpfile.js&lt;/code&gt; using &lt;code&gt;process.env.NODE_ENV = &amp;quot;release&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test&lt;/code&gt; is the one used by Jest (explanation below)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-minifying-with-uglify&quot; tabindex=&quot;-1&quot;&gt;4. Minifying with Uglify &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#4-minifying-with-uglify&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mishoo/UglifyJS2&quot;&gt;Uglify JS&lt;/a&gt; is a JavaScript compressor toolkit commonly used to minify the distribution version of JavaScript libraries.&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev gulp-uglify&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, add the following require and pipe to our &lt;code&gt;gulpfile.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; uglify &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-uglify&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ----------- minifying --------------&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;uglify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lazyload.min.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFolder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; writing uglified&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;all-together-now&quot; tabindex=&quot;-1&quot;&gt;All together now &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#all-together-now&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is how your &lt;code&gt;gulpfile.js&lt;/code&gt; should look like at the end:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; gulp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; eslint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-eslint&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; rollup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-rollup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; rename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-rename&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; babel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-babel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; uglify &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gulp-uglify&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; destFolder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NODE_ENV&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;release&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./src/**/*.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// ----------- linting --------------&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eslint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eslint&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eslint&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;failAfterError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; failing if errors&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// ----------- rolling up --------------&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rollup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;umd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;moduleName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;LazyLoad&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src/lazyload.js&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lazyload.es2015.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFolder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; writing rolledup&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// ----------- babelizing --------------&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;babel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lazyload.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFolder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; writing babelized ES5&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// ----------- minifying --------------&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;uglify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lazyload.min.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFolder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// --&gt; writing uglified&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;watch&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./src/**/*.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Other watchers&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;quot;watch&amp;quot;&lt;/code&gt; part is so that if we run the &lt;code&gt;gulp watch&lt;/code&gt; command, &lt;code&gt;gulp&lt;/code&gt; watches the &lt;code&gt;src&lt;/code&gt; folder for changes and re-creates the dist files automatically. Sweet.&lt;/p&gt;
&lt;h2 id=&quot;running-gulp&quot; tabindex=&quot;-1&quot;&gt;Running Gulp &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#running-gulp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can now build your library executing Gulp in single run:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;gulp&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or make it watch for changes in your &lt;code&gt;src&lt;/code&gt; files if you&#39;re still developing:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;gulp &lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;making-jest-work-along-with-rollup&quot; tabindex=&quot;-1&quot;&gt;Making Jest work along with Rollup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#making-jest-work-along-with-rollup&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;ll write another in-depth post about how I used Jest to test modules which would become private uglified variables and functions, but the point here is how to make Jest work together with Rollup, since the two require different Babel configuration.&lt;/p&gt;
&lt;p&gt;As we saw, the Babel configuration is split in two &lt;code&gt;env&lt;/code&gt;s and the one set and used by Jest is &lt;code&gt;test&lt;/code&gt;. This is because Jest just needs the &lt;code&gt;presets&lt;/code&gt; object to contain &lt;code&gt;[&amp;quot;es2015&amp;quot;]&lt;/code&gt;, whereas rollup requires &lt;code&gt;[&amp;quot;es2015&amp;quot;, {&amp;quot;modules&amp;quot;: false}]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you did what I explained correctly, Jest should work out of the box.&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev jest
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; jest-cli&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then just launch jest like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More information on Jest on the &lt;a href=&quot;https://facebook.github.io/jest/docs/en/getting-started.html&quot;&gt;Get Started&lt;/a&gt; page.&lt;/p&gt;
&lt;h2 id=&quot;further-steps&quot; tabindex=&quot;-1&quot;&gt;Further steps &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/create-a-javascript-library-using-es2015-modules-gulp-rollup-jest/#further-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A more advanced configuration would be to configure &lt;code&gt;npm&lt;/code&gt; to be the command line interface for the build and the tests, so that we could run &lt;code&gt;npm run build&lt;/code&gt; and &lt;code&gt;npm run test&lt;/code&gt; to launch either the build or the tests, or better include the testing process in the build so whenever our tests fail, the build fails too. I will do that as next steps.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Intersection Observer and lazy loading of elements</title>
		<link href="https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/"/>
		<updated>2017-09-04T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/</id>
		<content type="html">&lt;p&gt;In August 2017 a new exciting browser API finally &lt;a href=&quot;https://hacks.mozilla.org/2017/08/intersection-observer-comes-to-firefox/&quot;&gt;gained&lt;/a&gt; quite &lt;a href=&quot;https://caniuse.com/#search=IntersectionObserver&quot;&gt;wide support&lt;/a&gt;: the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API&quot;&gt;Intersection Observer API&lt;/a&gt;, which we can use to know when two DOM elements intersect, or when a given DOM element &lt;strong&gt;enters the browser viewport&lt;/strong&gt;. The lazy loading of images is just the case.&lt;/p&gt;
&lt;p&gt;About 3 years and 500 commits ago, I gave birth to a new vanilla javascript &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;lazy load script&lt;/a&gt;, currently known as &lt;code&gt;vanilla-lazyload&lt;/code&gt; on &lt;a href=&quot;https://www.npmjs.com/package/vanilla-lazyload&quot;&gt;npm&lt;/a&gt; and &lt;a href=&quot;https://cdnjs.com/libraries/vanilla-lazyload&quot;&gt;cdnjs&lt;/a&gt;, and starred by &lt;strong&gt;1,135 people on GitHub&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-switch-to-intersection-observer&quot; tabindex=&quot;-1&quot;&gt;The switch to Intersection Observer &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/#the-switch-to-intersection-observer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As the community around my script started to grow, &lt;a href=&quot;https://github.com/si14&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;https://github.com/ricardobrandao&quot;&gt;members&lt;/a&gt; requested it to support the Intersection Observer API, amongst &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/issues?q=label%3Aenhancement+is%3Aclosed&quot;&gt;other enhancements&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So I decided to make my script&#39;s fans happy, and I did it. The resulting source code is &lt;strong&gt;40% smaller&lt;/strong&gt;, and vanilla-lazyload is now &lt;strong&gt;much faster&lt;/strong&gt; than its previous version. (by the way, if you know how to measure a script performance precisely, please comment)&lt;/p&gt;
&lt;h2 id=&quot;how-to-create-an-intersection-observer&quot; tabindex=&quot;-1&quot;&gt;How to create an Intersection Observer &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/#how-to-create-an-intersection-observer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The implementation is quite simple: you create a new Intersection Observer instance specifying &lt;strong&gt;a callback function&lt;/strong&gt; to be called whenever an intersection event occurs, and a couple of options: &lt;strong&gt;root&lt;/strong&gt; and &lt;strong&gt;rootMargin&lt;/strong&gt;, that are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;root&lt;/code&gt;: the element you want to &lt;strong&gt;test the intersection against&lt;/strong&gt;, &lt;code&gt;null&lt;/code&gt; meaning the browser viewport&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rootMargin&lt;/code&gt;: in case you want to &lt;strong&gt;expand or shrink&lt;/strong&gt; the effective size of the &lt;code&gt;root&lt;/code&gt; element&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; myObserver &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IntersectionObserver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;/* do something */&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;rootMargin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;300px 0&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the intersection observer is created and assigned to a variable, you can start observing on a target element with:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; elementToObserve &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;observeMe&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
myObserver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;elementToObserve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;creating-the-observer&quot; tabindex=&quot;-1&quot;&gt;Creating the observer &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/#creating-the-observer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since I need to test the intersection of a set of images / elements &lt;strong&gt;against the scrolling container&lt;/strong&gt; (the viewport, or any element styled with &lt;code&gt;overflow: scroll&lt;/code&gt;), I create a new &lt;code&gt;IntersectionObserver&lt;/code&gt; and store it in the LazyLoad property &lt;code&gt;_observer&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_observer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IntersectionObserver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onIntersection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;container &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; document &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;container&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;rootMargin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;threshold &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;px&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;onIntersection&lt;/code&gt; is a function, which I explain below&lt;/li&gt;
&lt;li&gt;&lt;code&gt;settings.container&lt;/code&gt; is the scrolling container, defaulting to &lt;code&gt;document&lt;/code&gt;, passed by LazyLoad user in the options object&lt;/li&gt;
&lt;li&gt;&lt;code&gt;settings.threshold&lt;/code&gt; is the amount of pixels beyond the scrolling container where to start loading the images / elements, defaulting to &lt;code&gt;300&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-onintersection-function&quot; tabindex=&quot;-1&quot;&gt;The onIntersection function &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/#the-onintersection-function&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The point is that whenever a DOM element intersects with the scrolling container, the &lt;code&gt;onIntersection&lt;/code&gt; function is called. Here goes the function definition:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;onIntersection&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    entries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isIntersecting&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; element &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;revealElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_observer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unobserve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;entries&lt;/code&gt; argument is passed &lt;strong&gt;all the elements being observed&lt;/strong&gt; by the observer which calls this function. So we need to &lt;strong&gt;cycle through each entry&lt;/strong&gt; and know whether or not &lt;strong&gt;it is intersecting&lt;/strong&gt; with the &lt;code&gt;root&lt;/code&gt; element. Fortunately, the &lt;code&gt;isIntersecting&lt;/code&gt; property does this exactly, so:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if the entry is not intersecting, we just ignore this entry, returning&lt;/li&gt;
&lt;li&gt;if the entry is intersecting, we &lt;strong&gt;start loading the element source&lt;/strong&gt; calling &lt;code&gt;revealElement&lt;/code&gt;, then &lt;strong&gt;we &lt;code&gt;unobserve&lt;/code&gt; this specific entry&lt;/strong&gt; since its loading is already started and we don&#39;t need to keep watching it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;observing-an-element&quot; tabindex=&quot;-1&quot;&gt;Observing an element &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/#observing-an-element&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Isn&#39;t something missing? Yes it is! The code explained until now accomplishes nothing, if we don&#39;t &lt;strong&gt;tell our observer to observe an element&lt;/strong&gt;, or more than one in our case. What we need to do is:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_elements&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_observer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Being &lt;code&gt;this._elements&lt;/code&gt; the set of elements that LazyLoad has found inside &lt;code&gt;this._container&lt;/code&gt; by a specific selector, purged by the ones that are already being processed (to deal with cases of &lt;em&gt;infinite scroll&lt;/em&gt;, or other DOM updating cases).&lt;/p&gt;
&lt;h2 id=&quot;fallback&quot; tabindex=&quot;-1&quot;&gt;Fallback &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/#fallback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since &lt;em&gt;not every browser are created equal&lt;/em&gt; we need to test the support for &lt;code&gt;IntersectionObserver&lt;/code&gt; before we use it. The way to do it is simple:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;IntersectionObserver&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my case, on browsers where &lt;code&gt;IntersectionObserver&lt;/code&gt; is not supported, LazyLoad will load &lt;strong&gt;all the images at once&lt;/strong&gt;. Therefore, if you need to load lots of images and your user base is browsing with a consistent share of older browsers, you should use LazyLoad a version less than 9. See &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload/blob/master/CHANGELOG.md&quot;&gt;changelog&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-intersection-observers-to-create-vanilla-lazyload/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That&#39;s it! Intersection Observer makes your code much smaller, faster and more legible. If you&#39;re not using it already, you should definetly start playing around with it.&lt;/p&gt;
&lt;p&gt;And don&#39;t forget, if you have a very long page stuffed with images and other content, you should load them lazily using a lazy load script, and your best choice is &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;vanilla-lazyload&lt;/a&gt;!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Using CSS variables as a spacing unit</title>
		<link href="https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/"/>
		<updated>2017-06-14T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/</id>
		<content type="html">&lt;p&gt;Here I show you how you can CSS variables, popular name of &lt;em&gt;CSS custom properties&lt;/em&gt;, to &lt;strong&gt;scale your layout spaces&lt;/strong&gt; across different media queries.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The advantage: shorter, lighter, easier-to-maintain CSS files.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To demonstrate this, I created &lt;a href=&quot;https://codepen.io/verlok/pen/owzLPm?editors=1100&quot;&gt;CSS vars based layout spacing&lt;/a&gt; on Codepen. Find it embedded at the end of this post.&lt;/p&gt;
&lt;h2 id=&quot;what-are-css-variables&quot; tabindex=&quot;-1&quot;&gt;What are CSS variables &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/#what-are-css-variables&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;CSS variables one of the next big things in CSS. They&#39;re not &lt;a href=&quot;http://caniuse.com/#feat=css-variables&quot;&gt;widely supported&lt;/a&gt; (spoiler: Internet Explorer is missing) for current browsers market share, but it&#39;s time we start playing with them, don&#39;t you think? They might be useful when developing our next wonderful project!&lt;/p&gt;
&lt;p&gt;The advantage of CSS variables is that we can assign a value to a name, and refer to the value using a name.&lt;/p&gt;
&lt;h2 id=&quot;how-to-define-a-css-variable&quot; tabindex=&quot;-1&quot;&gt;How to define a CSS variable &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/#how-to-define-a-css-variable&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;CSS variables can be defined at any point, and they are inherited to all the children of the DOM element they&#39;re applied to.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;--base-spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we defined a CSS var named &lt;code&gt;--base-spacing&lt;/code&gt; and we assigned it a value of &lt;code&gt;15px&lt;/code&gt;. The variable is defined in the &lt;code&gt;html&lt;/code&gt; element so it will be available in our whole document.&lt;/p&gt;
&lt;p&gt;(Yeah, CSS vars must start with a double hyphen (&lt;code&gt;--&lt;/code&gt;), which is ugly, but bare with me)&lt;/p&gt;
&lt;h2 id=&quot;difference-with-sass-variables&quot; tabindex=&quot;-1&quot;&gt;Difference with SASS variables &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/#difference-with-sass-variables&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In case you&#39;re thinking: &amp;quot;So what? I&#39;m already using SASS and my &lt;code&gt;_variables.scss&lt;/code&gt; has plenty of variables!&amp;quot; - Well, it&#39;s not quite the same.&lt;/p&gt;
&lt;p&gt;SASS variables are pre-processed so they are transformed to a fixed, static CSS value. When the CSS is loaded, &lt;strong&gt;the variable is lost&lt;/strong&gt; and only its value remains, spread out in all of its usages.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A SASS variable cannot be changed after the CSS is loaded. CSS variables can be changed using media queries, javascript, or the developer tools of your favourite browser.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;how-to-use-a-css-variable&quot; tabindex=&quot;-1&quot;&gt;How to use a CSS variable &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/#how-to-use-a-css-variable&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We want the &lt;code&gt;--base-spacing&lt;/code&gt; variable to be a spacing unit to be used in paddings and margins across our page. So what do we do?&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.box&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-spacing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-spacing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-spacing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s great! Now we&#39;re using our CSS variable as a spacing unit, like we would do with a SASS variable, but... we can now change it!&lt;/p&gt;
&lt;h2 id=&quot;changing-css-variables-values&quot; tabindex=&quot;-1&quot;&gt;Changing CSS variables values &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/#changing-css-variables-values&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is where the magic happens. CSS variables values can be re-assigned like you would do with any other CSS property, using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;media queries&lt;/li&gt;
&lt;li&gt;javascript&lt;/li&gt;
&lt;li&gt;the developer tools of your favourite browser&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first thing you can do to understand the power of CSS variables is &lt;strong&gt;open the developer tools&lt;/strong&gt;, locate the variable in your CSS file, and &lt;strong&gt;change its value&lt;/strong&gt;. &lt;a href=&quot;https://codepen.io/verlok/pen/owzLPm?editors=1100&quot;&gt;Try it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our case, we want to enlarge spaces on wider screens, so we just do the following:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 500px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;--base-spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 30px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s it. This simple variable reassignment will make all of our paddings and margins scale since we used a variable to define theis values.&lt;/p&gt;
&lt;h2 id=&quot;demo&quot; tabindex=&quot;-1&quot;&gt;DEMO &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/#demo&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is what I&#39;m talking about.&lt;/p&gt;
&lt;p data-height=&quot;265&quot; data-theme-id=&quot;dark&quot; data-slug-hash=&quot;owzLPm&quot; data-default-tab=&quot;css,result&quot; data-user=&quot;verlok&quot; data-embed-version=&quot;2&quot; data-pen-title=&quot;CSS vars based layout spacing&quot; class=&quot;codepen&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/verlok/pen/owzLPm/&quot;&gt;CSS vars based layout spacing&lt;/a&gt; by Andrea Verlicchi (&lt;a href=&quot;https://codepen.io/verlok&quot;&gt;@verlok&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://production-assets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;h2 id=&quot;endless-possibilities&quot; tabindex=&quot;-1&quot;&gt;Endless possibilities &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/using-css-variables-to-scale-layout-spaces/#endless-possibilities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you master CSS variables, you can go far beyond and let your users decide the spacing of your layout, the main color, or anything else.&lt;/p&gt;
&lt;p&gt;You just need some input fields and a few lines of javascript, like &lt;a href=&quot;https://www.twitter.com/wesbos&quot;&gt;@wesbos&lt;/a&gt; is demonstrating here.&lt;/p&gt;
&lt;p data-height=&quot;265&quot; data-theme-id=&quot;dark&quot; data-slug-hash=&quot;adQjoY&quot; data-default-tab=&quot;css,result&quot; data-user=&quot;wesbos&quot; data-embed-version=&quot;2&quot; data-pen-title=&quot;Update CSS Variables with JS&quot; class=&quot;codepen&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/wesbos/pen/adQjoY/&quot;&gt;Update CSS Variables with JS&lt;/a&gt; by Wes Bos (&lt;a href=&quot;https://codepen.io/wesbos&quot;&gt;@wesbos&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://production-assets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
</content>
	</entry>
	
	<entry>
		<title>Changing text color for contrast based on background lightness</title>
		<link href="https://andreaverlicchi.eu/en/blog/changing-text-color-for-contrast-based-on-background-lightness/"/>
		<updated>2017-06-02T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/changing-text-color-for-contrast-based-on-background-lightness/</id>
		<content type="html">&lt;p&gt;If you had to change the color of some fixed-positioned text based on the lightness of its scrolling background, how would you do that? CSS filters, blend modes? But what if you had to support all browsers, including Internet Explorer? Here are a couple of ways to do that using CSS &lt;code&gt;clip&lt;/code&gt; and &lt;code&gt;clip-path&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s the result using &lt;code&gt;clip&lt;/code&gt; - wide browser support&lt;/p&gt;
&lt;iframe loading=&quot;lazy&quot; height=&quot;200&quot; scrolling=&quot;no&quot; title=&quot;Text color change at background using clip&quot; src=&quot;https://codepen.io/verlok/embed/VWZeBL/?height=194&amp;amp;theme-id=light&amp;amp;default-tab=result&amp;amp;embed-version=2&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; style=&quot;width: 100%;&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/verlok/pen/VWZeBL/&quot;&gt;Text color change at background using clip&lt;/a&gt; by Andrea Verlicchi (&lt;a href=&quot;https://codepen.io/verlok&quot;&gt;@verlok&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;And here&#39;s the result using &lt;code&gt;clip-path&lt;/code&gt; - modern browsers only&lt;/p&gt;
&lt;iframe loading=&quot;lazy&quot; height=&quot;200&quot; scrolling=&quot;no&quot; title=&quot;Text color change at background using clip-path&quot; src=&quot;https://codepen.io/verlok/embed/owvYjx/?height=265&amp;amp;theme-id=light&amp;amp;default-tab=result&amp;amp;embed-version=2&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; style=&quot;width: 100%;&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/verlok/pen/owvYjx/&quot;&gt;Text color change at background using clip-path&lt;/a&gt; by Andrea Verlicchi (&lt;a href=&quot;https://codepen.io/verlok&quot;&gt;@verlok&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;What happens here that the content is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;wrapped by a box with class &lt;code&gt;clipper&lt;/code&gt; which clips its content&lt;/li&gt;
&lt;li&gt;copied inside every container :(&lt;/li&gt;
&lt;li&gt;positioned with &lt;code&gt;position: fixed&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Being the content in position fixed, the content sticks to our browser window, but is&#39;t clipped by the moving clipping elements.&lt;/p&gt;
&lt;p&gt;This solutions has 2 problems, though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;there&#39;s a bug in IE and Edge which makes the content&#39;s block children invisible. It works with inline elements, though, but it&#39;s a hack&lt;/li&gt;
&lt;li&gt;we need to copy the content inside every container&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Can you think of a better solution? If you do, please add it to the comments!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Responsive images, an HTML 5.1 standard</title>
		<link href="https://andreaverlicchi.eu/en/blog/responsive-images-a-html-51-standard/"/>
		<updated>2017-04-10T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/responsive-images-a-html-51-standard/</id>
		<content type="html">&lt;p&gt;It&#39;s official. Responsive images have been a &lt;a href=&quot;https://www.w3.org/TR/html51/&quot;&gt;W3C recommendation&lt;/a&gt; since November 2016, featuring the brand new &lt;code&gt;picture&lt;/code&gt; tag and new attributes for the &lt;code&gt;img&lt;/code&gt; tag: &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-responsive-images&quot; tabindex=&quot;-1&quot;&gt;Why responsive images? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-a-html-51-standard/#why-responsive-images&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Back in 2010, Ethan Marcotte started talking of &lt;a href=&quot;https://alistapart.com/article/responsive-web-design&quot;&gt;responsive web design&lt;/a&gt;, an approach to web design aimed at allowing webpages to be viewed in response to the size of the browser viewport.&lt;/p&gt;
&lt;p&gt;That was revolutionary, but suddenly we developers had a new problem to face: in a responsive website, &lt;strong&gt;how big should the website&#39;s image files be&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;The initial approach was to use one large image for all viewport sizes, so that images looked great on large screens even if they had to be scaled down on smaller devices, but soon this turned out to be a bad practice: &lt;em&gt;slower connections&lt;/em&gt; on mobile devices and &lt;em&gt;less performing CPUs&lt;/em&gt; were slowing down the website and making user experience worse.&lt;/p&gt;
&lt;p&gt;Developers then started to use javascript to &lt;em&gt;pick the right image size&lt;/em&gt; based on the viewport, that&#39;s when scripts like &lt;a href=&quot;https://github.com/scottjehl/picturefill&quot;&gt;picturefill&lt;/a&gt; came about.&lt;/p&gt;
&lt;p&gt;But the thing is that javascript is slower than pure HTML: it must be downloaded, parsed and executed before the browser could even start downloading the images. The web needed something native to go back to defining images in the HTML to allow browsers to start downloading them as soon as possible.&lt;/p&gt;
&lt;p&gt;That&#39;s why a group of independent designers and developers who go by the name of &lt;a href=&quot;http://ricg.io/&quot;&gt;Responsive Images Community Group&lt;/a&gt;, started proposing new tags and attributes.&lt;/p&gt;
&lt;h2 id=&quot;what-are-responsive-images&quot; tabindex=&quot;-1&quot;&gt;What are responsive images? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-a-html-51-standard/#what-are-responsive-images&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&amp;quot;Responsive images&amp;quot; is the name given to the technique of &lt;strong&gt;defining more than one source per each image&lt;/strong&gt;, and making browsers &lt;strong&gt;to download the best one&lt;/strong&gt;, depending on the following factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;browser viewport, or your website layout&lt;/li&gt;
&lt;li&gt;device pixel density&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Users have different pixel densities depending on the monitor of their device. Standard devices have a pixel density of 1, meaning the monitor has 1 device pixel per CSS pixel, while the newest HiDpi monitors - including &amp;quot;Retina&amp;quot; displays - have a higher density. For example, a pixel density of 2 means that the monitor has 2x2 device pixels per CSS pixel, and so forth.&lt;/p&gt;
&lt;p&gt;HiDpi displays are great when rendering vectors, like fonts or SVG images. But when it comes to rendering images, browsers will just stretch the original image, making it blurry on devices that are supposed to deliver a better quality.&lt;/p&gt;
&lt;h2 id=&quot;supporting-hidpi-displays&quot; tabindex=&quot;-1&quot;&gt;Supporting hiDpi displays &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-a-html-51-standard/#supporting-hidpi-displays&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The simplest of things you can do with the new &lt;code&gt;srcset&lt;/code&gt; attribute is to support different pixel densities. You just need to specify different sources for your image, describing each one with the &lt;code&gt;x&lt;/code&gt; descriptor, which indicates the pixel density of the image source. Like that:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shirt_300w.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shirt_300w.jpg 1x, shirt_600w.jpg 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A beautiful shirt&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;300&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;380&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we want to display an image of 300 x 380 &lt;em&gt;CSS&lt;/em&gt; pixels. The standard density image is &lt;code&gt;shirt_300w.jpg&lt;/code&gt; and it&#39;s described by the &lt;code&gt;1x&lt;/code&gt; descriptor. The double-density image is &lt;code&gt;shirt_300w.jpg&lt;/code&gt;, and it needs to be 600 x 760 pixels.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; browsers that understand the new &lt;code&gt;srcset&lt;/code&gt; attribute will ignore the &lt;code&gt;src&lt;/code&gt; one, which is still required.&lt;/p&gt;
&lt;p&gt;This is already a good result to deliver the best image quality to our users, but what if in our responsive layout, the image size varies depending on the available space?&lt;/p&gt;
&lt;h2 id=&quot;different-image-sizes&quot; tabindex=&quot;-1&quot;&gt;Different image sizes &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-a-html-51-standard/#different-image-sizes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s suppose that our image must be wide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;300 pixels on small (&amp;lt; 600) viewports&lt;/li&gt;
&lt;li&gt;600 pixels on medium (&amp;gt; 600) viewports&lt;/li&gt;
&lt;li&gt;1200 pixels on large (&amp;gt; 1200) viewports&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How do we make sure that our users always get the image size that best fits their viewport &lt;em&gt;and&lt;/em&gt; pixel density?&lt;/p&gt;
&lt;p&gt;We can define images of these sizes:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Density / Viewport width&lt;/th&gt;
&lt;th&gt;&amp;lt; 600&lt;/th&gt;
&lt;th&gt;&amp;gt;= 600&lt;/th&gt;
&lt;th&gt;&amp;gt;= 1200&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1x&lt;/td&gt;
&lt;td&gt;300 x 380&lt;/td&gt;
&lt;td&gt;600 x 760&lt;/td&gt;
&lt;td&gt;1200 x 1520&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2x&lt;/td&gt;
&lt;td&gt;600 x 760&lt;/td&gt;
&lt;td&gt;1200 x 1520&lt;/td&gt;
&lt;td&gt;2400 x 3040&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you can see, we&#39;re using 4 different image sizes. I would advice to name the images with their width on the name, since it&#39;s much clearer to understand.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;300 x 380 - shirt_300w.jpg&lt;/li&gt;
&lt;li&gt;600 x 760 - shirt_600w.jpg&lt;/li&gt;
&lt;li&gt;1200 x 1520 - shirt_1200w.jpg&lt;/li&gt;
&lt;li&gt;2400 x 3040 - shirt_2400w.jpg&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To markup this in our HTML, we must do:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shirt_300w.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
		shirt_300w.jpg   300w,
		shirt_600w.jpg   600w,
		shirt_1200w.jpg 1200w,
		shirt_2400w.jpg 2400w
	&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A beautiful shirt&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 1200px) 1200px,
         (min-width: 600px) 600px,
         300px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this markup, the browser knows the space that the image will occupy on the screen (through &lt;code&gt;sizes&lt;/code&gt;) and all the available image sources that we prepared for our users (through &lt;code&gt;srcset&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;At this point, the browser will choose what image source to download based on the information we provided and the information it knows about our user, such as screen density, cached files, connection speed, etc.&lt;/p&gt;
&lt;h2 id=&quot;browser-support&quot; tabindex=&quot;-1&quot;&gt;Browser support &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-a-html-51-standard/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;srcset&lt;/code&gt; attribute is supported across all browsers except Internet Explorer. Fortunately, there&#39;s an official &lt;a href=&quot;https://github.com/scottjehl/picturefill/&quot;&gt;polyfill&lt;/a&gt; that we can use to emulate native browser behavior on legacy browsers.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Responsive images? You don&#39;t need the picture tag</title>
		<link href="https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/"/>
		<updated>2015-12-21T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/</id>
		<content type="html">&lt;p&gt;Say you have a responsive website layout where images are sized at 100% of the container, but &lt;strong&gt;the container is not always as wide as the viewport&lt;/strong&gt;. Do we need to use the &lt;code&gt;picture&lt;/code&gt; tag, or the &lt;code&gt;img&lt;/code&gt; tag is enough? &lt;strong&gt;The &lt;code&gt;img&lt;/code&gt; tag can do it&lt;/strong&gt;, using its &lt;code&gt;sizes&lt;/code&gt; and &lt;code&gt;srcset&lt;/code&gt; attributes. Here&#39;s how.&lt;/p&gt;
&lt;h2 id=&quot;the-images-layout&quot; tabindex=&quot;-1&quot;&gt;The images layout &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/#the-images-layout&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The images in the layout are wide as follows:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Viewport Width&lt;/th&gt;
&lt;th&gt;Images width&lt;/th&gt;
&lt;th&gt;Container width&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0 to 767 px&lt;/td&gt;
&lt;td&gt;1/2 of container&lt;/td&gt;
&lt;td&gt;100% with no padding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From 768 px to 1023 px&lt;/td&gt;
&lt;td&gt;1/3 of container&lt;/td&gt;
&lt;td&gt;100% with 30 px padding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From 1024 px to 1279 px&lt;/td&gt;
&lt;td&gt;1/4 of container&lt;/td&gt;
&lt;td&gt;100% with 30 px padding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From 1280 px up&lt;/td&gt;
&lt;td&gt;1/4 of container&lt;/td&gt;
&lt;td&gt;1280 px with 30 px padding&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;units-we-can-use-in-the-sizes-attribute&quot; tabindex=&quot;-1&quot;&gt;Units we can use in the &lt;code&gt;sizes&lt;/code&gt; attribute &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/#units-we-can-use-in-the-sizes-attribute&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When using the &lt;code&gt;img&lt;/code&gt; tag, in the &lt;code&gt;sizes&lt;/code&gt; attribute, you can specify how wide your images will display at different media queries, not only using the viewport width (&lt;code&gt;vw&lt;/code&gt;) unit (as you could find googling around) but &lt;strong&gt;using any length&lt;/strong&gt; and also &lt;strong&gt;using CSS &lt;code&gt;calc()&lt;/code&gt;&lt;/strong&gt; if you have to deal with paddings or container&#39;s &lt;code&gt;max-width&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Viewport Width&lt;/th&gt;
&lt;th&gt;Images width&lt;/th&gt;
&lt;th&gt;Container width&lt;/th&gt;
&lt;th&gt;Image width in CSS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0 to 767 px&lt;/td&gt;
&lt;td&gt;1/2 of container&lt;/td&gt;
&lt;td&gt;100% with no padding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;50vw&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From 768 px to 1023 px&lt;/td&gt;
&lt;td&gt;1/3 of container&lt;/td&gt;
&lt;td&gt;100% with 30 px padding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;calc(( 100vw - 60 px ) / 3)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From 1024 px to 1279 px&lt;/td&gt;
&lt;td&gt;1/4 of container&lt;/td&gt;
&lt;td&gt;100% with 30 px padding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;calc(( 100vw - 60 px ) / 4)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From 1280 px up&lt;/td&gt;
&lt;td&gt;1/4 of container&lt;/td&gt;
&lt;td&gt;1280 px with 30 px padding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;305 px&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;See &lt;a href=&quot;https://codepen.io/verlok/pen/JGXeyz?editors=110&quot;&gt;this pen&lt;/a&gt; which uses media queries and CSS to specify &lt;code&gt;img&lt;/code&gt; widths, and &lt;a href=&quot;https://codepen.io/verlok/pen/adNQqX?editors=110&quot;&gt;this pen&lt;/a&gt; which specifies the &lt;code&gt;sizes&lt;/code&gt; inside the &lt;code&gt;img&lt;/code&gt; tag.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Confused? If you need a more extensive explication, please read &lt;a href=&quot;https://ericportis.com/posts/2014/srcset-sizes/&quot;&gt;srcset and sizes&lt;/a&gt; by Eric Portis, in my opinion the best article about using &lt;code&gt;img&lt;/code&gt; with &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;calculating-optimized-image-sizes-based-on-spacing-and-device-orientation&quot; tabindex=&quot;-1&quot;&gt;Calculating optimized image sizes based on spacing and device / orientation &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/#calculating-optimized-image-sizes-based-on-spacing-and-device-orientation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We want our images to be optimized at most common resolutions, we need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define which are the most common screen resolutions / densities&lt;/li&gt;
&lt;li&gt;Decide which are the resolutions / densities that we want to optimize for&lt;/li&gt;
&lt;li&gt;Calculate what the image sizes will be at these resolutions / densities&lt;/li&gt;
&lt;li&gt;Scale our images to those image sizes&lt;/li&gt;
&lt;li&gt;Markup the &lt;code&gt;img&lt;/code&gt;s in our HTML 2. List all the image sizes in the &lt;code&gt;srcset&lt;/code&gt; attribute, using the &lt;code&gt;w&lt;/code&gt; descriptor 2. List all the image widths in the &lt;code&gt;sizes&lt;/code&gt; attribute, as defined in the table above&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To define the screen resolutions and decide which ones to optimize for, we can use any tool like Google Analytics to get some information about our users and the devices they mostly use.&lt;/p&gt;
&lt;p&gt;After some &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1BCeWGXOevUHlL8l9ti2i81C9BgSsHtybO9Z9WAYpfnQ/edit&quot;&gt;calculations&lt;/a&gt;, the resulting image sizes were the following:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device &amp;amp; orientation&lt;/th&gt;
&lt;th&gt;Screen width&lt;/th&gt;
&lt;th&gt;Img width (css px)&lt;/th&gt;
&lt;th&gt;Img height (css px)&lt;/th&gt;
&lt;th&gt;Screen density&lt;/th&gt;
&lt;th&gt;Img width (px)&lt;/th&gt;
&lt;th&gt;Img height (px)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;iPhone 4/5/5s&lt;/td&gt;
&lt;td&gt;320&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;td&gt;186&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;320&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;372&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iPhone 6&lt;/td&gt;
&lt;td&gt;375&lt;/td&gt;
&lt;td&gt;187&lt;/td&gt;
&lt;td&gt;217&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;374&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;435&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iPhone 5/5s landscape&lt;/td&gt;
&lt;td&gt;568&lt;/td&gt;
&lt;td&gt;284&lt;/td&gt;
&lt;td&gt;330&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;568&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;660&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iPhone 6 landscape&lt;/td&gt;
&lt;td&gt;667&lt;/td&gt;
&lt;td&gt;333&lt;/td&gt;
&lt;td&gt;387&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;666&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;774&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iPad / mini&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;236&lt;/td&gt;
&lt;td&gt;274&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;472&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;549&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iPad / mini landscape&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;td&gt;241&lt;/td&gt;
&lt;td&gt;280&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;482&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;560&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PC with 1280w up&lt;/td&gt;
&lt;td&gt;1280&lt;/td&gt;
&lt;td&gt;305&lt;/td&gt;
&lt;td&gt;355&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;305&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;355&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PC with 1280w and HiDPI&lt;/td&gt;
&lt;td&gt;1280&lt;/td&gt;
&lt;td&gt;305&lt;/td&gt;
&lt;td&gt;355&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;610&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;709&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PC with more than 1280w&lt;/td&gt;
&lt;td&gt;1920&lt;/td&gt;
&lt;td&gt;305&lt;/td&gt;
&lt;td&gt;355&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;305&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;355&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;to-the-code&quot; tabindex=&quot;-1&quot;&gt;To the code! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/#to-the-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The code of the POC that I created is on GitHub in &lt;a href=&quot;https://www.github.com/verlok/responsiveImagesTagsCompared&quot;&gt;this repo&lt;/a&gt;, and the &lt;a href=&quot;http://verlok.github.io/responsiveImagesTagsCompared&quot;&gt;live demo is here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;picture-markup&quot; tabindex=&quot;-1&quot;&gt;picture markup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/#picture-markup&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 320px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/320x372 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 375px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/374x435 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 568px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/568x660 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 667px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/666x774 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 768px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/472x549 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 1024px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/241x280 1x, http://placehold.it/482x560 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 1280px)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/305x355 1x, http://placehold.it/610x709 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/305x355&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A product image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;img-markup&quot; tabindex=&quot;-1&quot;&gt;img markup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/#img-markup&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://placehold.it/305x355&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
		http://placehold.it/241x280 241w,
		http://placehold.it/305x355 305w,
		http://placehold.it/320x372 320w,
		http://placehold.it/374x435 374w,
		http://placehold.it/472x549 472w,
		http://placehold.it/482x560 482w,
		http://placehold.it/568x660 578w,
		http://placehold.it/610x709 610w,
		http://placehold.it/666x774 666w
	&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 1280px) 305px,
            (min-width: 1024px) calc((100vw - 60px) / 4),
            (min-width: 768px) calc((100vw - 60px) / 3),
            50vw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A product image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/responsive-images-you-dont-need-picture-tag/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;picture&lt;/code&gt; markup turns out to be more verbose, and we&#39;re still not supporting single density displays under 768px.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;img&lt;/code&gt; markup is shorter and less repetitive, and lets the browser calculate what is the better image to use considering resolution AND pixel density.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;You don&#39;t need the &lt;code&gt;picture&lt;/code&gt; tag.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The reason is that using the &lt;code&gt;img&lt;/code&gt; you&#39;ll have to write &lt;strong&gt;much less code&lt;/strong&gt; to support &lt;strong&gt;much more devices and screen densities&lt;/strong&gt;. Given the ability to use CSS&#39; &lt;code&gt;calc()&lt;/code&gt; function in the length expression of the &lt;code&gt;sizes&lt;/code&gt; attribute, we can do even complex calculations to define the right image to use even in complex layouts.&lt;/p&gt;
&lt;p&gt;Note that the &lt;code&gt;picture&lt;/code&gt; and &lt;code&gt;img&lt;/code&gt; tags are comparable only when all the images have the &lt;strong&gt;same ratio over multiple media queries&lt;/strong&gt;. If the images ratio change to adapt images to devices ratios, the &lt;code&gt;picture&lt;/code&gt; tag is the only way to go.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Lazy load of responsive images with srcset and LazyLoad</title>
		<link href="https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/"/>
		<updated>2015-04-20T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/</id>
		<content type="html">&lt;p&gt;It&#39;s now possible (yes, today!) to have &lt;strong&gt;lazy loading&lt;/strong&gt; on &lt;strong&gt;responsive images&lt;/strong&gt; to make our images to adapt to users screens &lt;em&gt;and&lt;/em&gt; keep our website fast. YAY! &#92;o/ In this article, we&#39;ll see what markup we need to write and which Javascript libraries we&#39;re gonna need to do that.&lt;/p&gt;
&lt;h2 id=&quot;old-article&quot; tabindex=&quot;-1&quot;&gt;Old article! 👀 &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#old-article&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Hold on! You&#39;re reading an old version of this article.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/lazy-load-responsive-images-in-2020-srcset-sizes-picture-webp&quot;&gt;Read the &lt;strong&gt;2020 update&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;responsive-lazy-what&quot; tabindex=&quot;-1&quot;&gt;Responsive lazy what? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#responsive-lazy-what&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Responsive images&lt;/strong&gt; is a technique to make the images in your website to adapt to the &lt;strong&gt;viewport witdh&lt;/strong&gt; and &lt;strong&gt;screen density&lt;/strong&gt; (1x, 2x - retina display, etc.). To understand how to do this, you can read &lt;a href=&quot;http://alistapart.com/article/responsive-images-in-practice&quot;&gt;Responsive images in practise&lt;/a&gt; and you can find more info at the &lt;a href=&quot;http://responsiveimages.org/&quot;&gt;responsive images community group website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lazy loading images&lt;/strong&gt; is a technique to make your website faster by &lt;strong&gt;avoiding to load images&lt;/strong&gt; that the user might never see on his viewport, then &lt;strong&gt;loading them as they enter the viewport&lt;/strong&gt;. Beyond performance, this also allows you to save bandwith (and money, if you&#39;re paying a CDN service for your images).&lt;/p&gt;
&lt;h2 id=&quot;implementation&quot; tabindex=&quot;-1&quot;&gt;Implementation &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#implementation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://verlok.github.io/img_srcset_lazyload&quot;&gt;Take a look at the results&lt;/a&gt; we&#39;re going to achieve using this techniques together.&lt;/p&gt;
&lt;p&gt;If you open your browser inspector in the network panel, you would see that the first images are loaded &amp;quot;normally&amp;quot; by the browser at page landing, but the rest of the images are loaded as you scroll down the document.&lt;/p&gt;
&lt;h3 id=&quot;the-markup&quot; tabindex=&quot;-1&quot;&gt;The markup &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#the-markup&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Here&#39;s the markup you&#39;re gonna need to lazy load a responsive image.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Image loaded normally by the browser --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;
		img/41494516WM_10r_n_f.jpg 668w,
		img/41494516WM_10_n_f.jpg  334w,
		img/41494516WM_9r_n_f.jpg  446w,
		img/41494516WM_9_n_f.jpg   223w
	&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 361px) 50vw,
        (min-width: 481px) 33.333vw,
        (min-width: 769px) 25vw,
        (min-width: 1025px) 20vw,
        100vw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Image loaded lazily by javascript --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;img/41494516WM_10r_n_f.jpg 668w,
        img/41494516WM_10_n_f.jpg 334w,
        img/41494516WM_9r_n_f.jpg 446w,
        img/41494516WM_9_n_f.jpg 223w&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(min-width: 361px) 50vw,
        (min-width: 481px) 33.333vw,
        (min-width: 769px) 25vw,
        (min-width: 1025px) 20vw,
        100vw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we&#39;re using the &lt;code&gt;img&lt;/code&gt; HTML tag and &lt;strong&gt;not&lt;/strong&gt; the &lt;code&gt;picture&lt;/code&gt;. The latter is not necessary because we&#39;re not changing the image ratio in this case.&lt;/p&gt;
&lt;h3 id=&quot;script-inclusion&quot; tabindex=&quot;-1&quot;&gt;Script inclusion &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#script-inclusion&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First of all, we need a library to load the lazy images as they enter the viewport. There are a couple of libraries to have your images loaded lazily, but to have lazy loading of &lt;em&gt;responsive&lt;/em&gt; images you&#39;re gonna need the one that I wrote: &lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/&quot;&gt;LazyLoad&lt;/a&gt; (read about all its advantages &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/a-new-lazyload-to-improve-your-website-performance&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Furthermore, as not all browser are supporting responsive images, we need to include Filament Group&#39;s &lt;a href=&quot;https://github.com/scottjehl/picturefill&quot;&gt;picturefill&lt;/a&gt; library, a polyfill which allows us fill the gap and make responsive images work in all browsers. Note that this library won&#39;t be necessary when all browsers you need to support will support responsive images.&lt;/p&gt;
&lt;p&gt;So we&#39;re going to include those 2 scripts:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;js/vendor/lazyload.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;js/vendor/picturefill.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;script-initialization&quot; tabindex=&quot;-1&quot;&gt;Script initialization &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#script-initialization&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;What we need to do is create a new instance of &lt;code&gt;LazyLoad&lt;/code&gt; to transform that &lt;code&gt;data-srcset&lt;/code&gt; attribute into a proper &lt;code&gt;srcset&lt;/code&gt; attribute. This would be enough for browsers that natively support &lt;em&gt;responsive images&lt;/em&gt; but, for the rest of them, we need to call &lt;code&gt;picturefill&lt;/code&gt; soon after &lt;code&gt;LazyLoad&lt;/code&gt; has modified the DOM.&lt;/p&gt;
&lt;p&gt;We can do all of that using this command:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*var myLazyLoad = */&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LazyLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;data_src&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;data_srcset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;srcset&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;show_while_loading&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//best for progressive JPEG&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;callback_set&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;picturefill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;img&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For further reference about what we did here, see &lt;a href=&quot;http://verlok.github.io/vanilla-lazyload/&quot;&gt;LazyLoad documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-stylesheet&quot; tabindex=&quot;-1&quot;&gt;The stylesheet &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#the-stylesheet&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are also some features that can be achieved only using our CSS. We need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make empty images to occupy some space. If we don&#39;t do so, all the empty images will be collapsed one to another and they will enter the viewport all at the same time, nullifying our efforts to load them lazily.&lt;/li&gt;
&lt;li&gt;Avoid empty images to appear as broken images&lt;/li&gt;
&lt;li&gt;(if we used the &lt;code&gt;show_while_loading&lt;/code&gt; option, as we did) Resolve a Firefox anomaly that displays the broken image icon while images are loading&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can do all that using this CSS rules:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*
Makes images container to occupy some space
when the images aren&#39;t loaded yet.
This value depends on your layout.
*/&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.imageList li&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 300px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/*
Avoid empty images to appear as broken
*/&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;img:not([src]):not([srcset])&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;visibility&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/*
Fixes Firefox anomaly during images load time
*/&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@-moz-document&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;url-prefix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token selector&quot;&gt;img:-moz-loading&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token property&quot;&gt;visibility&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;thats-it&quot; tabindex=&quot;-1&quot;&gt;That&#39;s it! &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/lazy-load-responsive-images-srcset/#thats-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It was very easy, wasn&#39;t it? If you didn&#39;t yet, &lt;a href=&quot;http://verlok.github.io/img_srcset_lazyload&quot;&gt;take a look at the demo&lt;/a&gt; of what we achieved here.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Advanced sprite generation using Compass (SASS)</title>
		<link href="https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/"/>
		<updated>2015-03-06T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/</id>
		<content type="html">&lt;p&gt;Spriting is a way to improve performance in your website by putting many images (or icons) in a single larger image, in order to make a single HTTP request instead of many. Here&#39;s how you can make sprites using Compass.&lt;/p&gt;
&lt;h2 id=&quot;the-simple-way&quot; tabindex=&quot;-1&quot;&gt;The simple way &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#the-simple-way&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The simpler way to create a sprite with Compass requires you to import a folder of images in your project, then generate a class for each sprite. You can do that by using the following code:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Required Compass tool import&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;compass/utilities/sprites&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Importing all the png images under the flags folder&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;flags/*.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Generate a CSS class for each sprite&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; all-flags-sprites&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example of CSS output:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.flags-it,
.flags-de,
.flags-fr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;/images/flags-s34fe0604ab.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; no-repeat&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.flags-it&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;background-position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.flags-de&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;background-position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0 -32px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.flags-fr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;background-position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0 -64px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be enough for your needs... but you want more, don&#39;t you?&lt;/p&gt;
&lt;h2 id=&quot;the-advanced-way&quot; tabindex=&quot;-1&quot;&gt;The advanced way &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#the-advanced-way&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Skipping all the others way you can do sprites generation with Compass, I found out that if you have to do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate dimensions of the box equals to the sprite ones&lt;/li&gt;
&lt;li&gt;Use an offset inside the box&lt;/li&gt;
&lt;li&gt;Spacing sprites inside the sprite map&lt;/li&gt;
&lt;li&gt;Manage 1x, 2x, 3x density displays&lt;/li&gt;
&lt;li&gt;Optimize sprite generation time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The only way to do spriting with Compass is to create your own mixins which use Compass base mixins under the hood.&lt;/p&gt;
&lt;h3 id=&quot;images-and-folders-structure&quot; tabindex=&quot;-1&quot;&gt;Images and folders structure &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#images-and-folders-structure&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To have the images in single density, double density and maybe triple density, we need to provide the images in 1x, 2x and maybe 3x size.&lt;/p&gt;
&lt;p&gt;So, supposing you will create a sprite map containing &lt;strong&gt;flags&lt;/strong&gt;, you can have the following folders under our images folder:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;flagsSprite1x - &lt;em&gt;flags images @ single density&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;france.png&lt;/li&gt;
&lt;li&gt;germany.png&lt;/li&gt;
&lt;li&gt;italy.png&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;flagsSprite2x - &lt;em&gt;flags images @ double density&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;france.png&lt;/li&gt;
&lt;li&gt;germany.png&lt;/li&gt;
&lt;li&gt;italy.png&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;flagsSprite3x - &lt;em&gt;...triple density&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And if we&#39;re were going to create also an &lt;strong&gt;icons&lt;/strong&gt; sprite map, we&#39;d have to create the folders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iconsSprite1x
&lt;ul&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;iconsSprite2x
&lt;ul&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;iconsSprite3x
&lt;ul&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let&#39;s take a look at the SASS partials you should create.&lt;/p&gt;
&lt;h3 id=&quot;sass-partials&quot; tabindex=&quot;-1&quot;&gt;SASS partials &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#sass-partials&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To guarantee the maximum flexibility and the smallest build time, I suggest you to use the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;_variables.scss - all your variables&lt;/li&gt;
&lt;li&gt;_mixins.scss - all your mixins&lt;/li&gt;
&lt;li&gt;one partial file for set of images
&lt;ul&gt;
&lt;li&gt;_flagsSprite.scss - flags&lt;/li&gt;
&lt;li&gt;_iconsSprite.scss - icons&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s see what to put in our partials, one by one.&lt;/p&gt;
&lt;h3 id=&quot;mixins-scss&quot; tabindex=&quot;-1&quot;&gt;_mixins.scss &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#mixins-scss&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Here&#39;s some mixins you might want to include in your mixins file. You can find the explanation of what they do right in the code comments.&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*
Makes possible to use a n-ple density sprite
Automatically adapts background-size and offset when $multiplier is greater than 1
Allows you to use automatic size generation, which is automatically adapted when $multiplier is greater than 1

Required parameters:
- $sprite - the sprite name
- $spriteMap - the spriteMap variable
- $spriteUrl - the sprite map url of the sprite

Optional parameters:
- $multiplier (1) - the sprite density (1 for single density, 2 for retina, 3, etc.)
- $renderSize (false) - tells the mixin to render width and height of the box containing the sprite
- $offsetX (0) - the horizontal offset (px) for the image in the box
- $offsetY (0) - the vertical offset (px) for the image in the box
*/&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNxSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$spriteMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$spriteUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$renderSize&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$offsetX&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$offsetY&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$spritePosition&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprite-position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spriteMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetX&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetY&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent &lt;span class=&quot;token variable&quot;&gt;$spriteUrl&lt;/span&gt; no-repeat &lt;span class=&quot;token function&quot;&gt;nth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spritePosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;nth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spritePosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;@if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;image-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sprite-path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spriteMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;image-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sprite-path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spriteMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;@if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$renderSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;image-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sprite-file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spriteMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;image-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sprite-file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spriteMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multiplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
Utility mixin to use single and double density sprite, with double density media query included

Required parameters:
- $sprite - the sprite name
- $sprite1xMap - the spriteMap variable for the 1x sprites
- $sprite2xMap - the spriteMap variable for the 2x sprites
- $sprite1xUrl - the sprite map url of the 1x sprites
- $sprite2xUrl - the sprite map url of the 2x sprites

Optional parameters:
- $renderSize (false) - tells the mixin to render width and height of the box containing the sprite
- $offsetX (0) - the horizontal offset (px) for the image in the box
- $offsetY (0) - the vertical offset (px) for the image in the box
*/&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;use1x2xSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite1xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite2xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite1xUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite2xUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$renderSize&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$offsetX&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$offsetY&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNxSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite1xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite1xUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$renderSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-min-device-pixel-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;min-resolution&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 144dpi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNxSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite2xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sprite2xUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$renderSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;variables-scss&quot; tabindex=&quot;-1&quot;&gt;_variables.scss &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#variables-scss&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is the file where you define all the variables for your site, that you&#39;re going to use across all your scss files.&lt;/p&gt;
&lt;p&gt;Here you should define the spacing between sprites in sprite map images.&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Generic spacing (at 1x) for sprites&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$spacing-sprites-generic&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;flagssprite-scss&quot; tabindex=&quot;-1&quot;&gt;_flagsSprite.scss &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#flagssprite-scss&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is the file where you define the variables and the mixins for your flag sprites.&lt;/p&gt;
&lt;p&gt;I suggest to &lt;code&gt;@import&lt;/code&gt; your &lt;code&gt;_flagsSprite.scss&lt;/code&gt; only in files that requires flag sprites. This &lt;strong&gt;speeds up build time&lt;/strong&gt; a lot, by avoiding frequent images check on the file system.&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// flagsSprite MAPS and URLS&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$flagsSprite1xMap&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprite-map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;flagsSprite1x/*.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$spacing&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$spacing-sprites-generic&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$flagsSprite2xMap&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprite-map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;flagsSprite2x/*.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$spacing&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$spacing-sprites-generic&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; 2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$flagsSprite1xUrl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;sprite-url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$flagsSprite1xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$flagsSprite2xUrl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;sprite-url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$flagsSprite2xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// flagsSprite mixin&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;flagsSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spriteName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$renderSize&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$offsetX&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$offsetY&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;use1x2xSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$spriteName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$flagsSprite1xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$flagsSprite2xMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$flagsSprite1xUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$flagsSprite2xUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$renderSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$offsetY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;style-scss-standard-usage&quot; tabindex=&quot;-1&quot;&gt;style.scss - standard usage &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#style-scss-standard-usage&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you don&#39;t need space around your sprite and you don&#39;t want Compass to generate box dimensions for you, you can simply do the following.&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;compass/utilities/sprites&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_variables&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_flagsSprite&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Simple usage&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.exampleSimple &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;flagsSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;italy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That will produce the following:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.exampleSimple&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;../img/flagsSprite1x-s479625030c.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; no-repeat 0 -882px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-min-device-pixel-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;min-resolution&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 144dpi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.exampleSimple&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;../img/flagsSprite2x-s9a855cf705.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; no-repeat 0 -882px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 32px 2048px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;style-scss-with-box-size-generation&quot; tabindex=&quot;-1&quot;&gt;style.scss - with box size generation &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#style-scss-with-box-size-generation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you want Compass to generate box dimensions for you, you should do the following.&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;compass/utilities/sprites&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_variables&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_flagsSprite&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.exampleWithDimensions &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;flagsSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;italy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That will produce the following:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.exampleWithDimensions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;../img/flagsSprite1x-s479625030c.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; no-repeat 0 -882px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 32px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 32px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-min-device-pixel-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;min-resolution&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 144dpi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.exampleWithDimensions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;../img/flagsSprite2x-s9a855cf705.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; no-repeat 0 -882px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 32px 2048px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 32px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 32px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;style-scss-with-offset-management&quot; tabindex=&quot;-1&quot;&gt;style.scss - with offset management &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#style-scss-with-offset-management&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you don&#39;t want Compass to generate box dimensions for you, but you want to use an offset inside the box, you should do the following.&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;compass/utilities/sprites&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_variables&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_flagsSprite&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.exampleWithPadding &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;flagsSprite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;italy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 10&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 10&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 52px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 52px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That will produce the following:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.exampleWithPadding&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;../img/flagsSprite1x-s479625030c.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; no-repeat 10px -872px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 52px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 52px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-min-device-pixel-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;min-resolution&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 144dpi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.exampleWithPadding&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;../img/flagsSprite2x-s9a855cf705.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; no-repeat 10px -872px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 32px 2048px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;thats-it&quot; tabindex=&quot;-1&quot;&gt;That&#39;s it &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/advanced-sprite-generation-using-compass-sass/#thats-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Automatic sprite generation using Compass considering all the factors can be quite complex, but if you follow this guide it will be easy and also easier to maintain.&lt;/p&gt;
&lt;p&gt;You you found any issues with this post, please &lt;a href=&quot;https://twitter.com/verlok&quot;&gt;tweet me&lt;/a&gt; and I&#39;ll fix it.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>A new LazyLoad to improve your website performance</title>
		<link href="https://andreaverlicchi.eu/en/blog/a-new-lazyload-to-improve-your-website-performance/"/>
		<updated>2014-11-20T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/a-new-lazyload-to-improve-your-website-performance/</id>
		<content type="html">&lt;p&gt;In the latest days I&#39;ve been working on websites performance optimization and I realized that there is no way to take advantage of the &lt;strong&gt;progressive JPEG&lt;/strong&gt; image format on websites if you&#39;re using &lt;a href=&quot;https://github.com/tuupola/jquery_lazyload&quot; title=&quot;Mika Tuupola&quot;&gt;jQuery_lazyload&lt;/a&gt;. So after sending a pull request to its author, I decided to write my own lazy load, which turned out to be better, because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it&#39;s 6x faster&lt;/li&gt;
&lt;li&gt;it allows you to &lt;a href=&quot;https://andreaverlicchi.eu/en/blog/a-new-lazyload-to-improve-your-website-performance/lazy-load-responsive-images-srcset&quot;&gt;lazy load responsive images&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;it doesn&#39;t depend on jQuery&lt;/li&gt;
&lt;li&gt;it best supports the progressive JPEG format&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More information on the &lt;a href=&quot;https://github.com/verlok/vanilla-lazyload&quot;&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>CSS 3 only spinning &quot;loading&quot; animation</title>
		<link href="https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/"/>
		<updated>2012-10-03T00:00:00Z</updated>
		<id>https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/</id>
		<content type="html">&lt;p&gt;We used GIF images to create animations for years, but they aren&#39;t pretty to be used over gradients or pictures (no alpha channel, no anti-aliasing) of which modern web sites are full. There are many workarounds to animate PNG images instead, but...&lt;/p&gt;
&lt;p&gt;I want to show you a solution I found to create a &amp;quot;loading&amp;quot; animation from scratch, using only CSS 3, without images.&lt;/p&gt;
&lt;h2 id=&quot;results-first&quot; tabindex=&quot;-1&quot;&gt;Results first &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#results-first&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p data-height=&quot;265&quot; data-theme-id=&quot;0&quot; data-slug-hash=&quot;bWmvON&quot; data-default-tab=&quot;css,result&quot; data-user=&quot;verlok&quot; data-embed-version=&quot;2&quot; data-pen-title=&quot;CSS 3 only spinning circle quarter - loading animation&quot; class=&quot;codepen&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/verlok/pen/bWmvON/&quot;&gt;CSS 3 only spinning circle quarter - loading animation&lt;/a&gt; by Andrea Verlicchi (&lt;a href=&quot;https://codepen.io/verlok&quot;&gt;@verlok&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://production-assets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;h2 id=&quot;what-happens-here&quot; tabindex=&quot;-1&quot;&gt;What happens here &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#what-happens-here&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The core of this is to draw a quarter of circle and animate it.
Read on to know the bottom-up steps to do it.&lt;/p&gt;
&lt;h2 id=&quot;1-create-a-circle&quot; tabindex=&quot;-1&quot;&gt;1. Create a circle &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#1-create-a-circle&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Inner masked circle --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;maskedCircle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Spinning circle (inner circle) */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading .maskedCircle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 12px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3px solid white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;2-mask-one-quarter-of-the-circle&quot; tabindex=&quot;-1&quot;&gt;2. Mask one quarter of the circle &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#2-mask-one-quarter-of-the-circle&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Mask of the quarter of circle --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mask&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Inner masked circle --&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;maskedCircle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Spinning circle mask */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading .mask&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 12px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 12px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;3-make-both-spin-around&quot; tabindex=&quot;-1&quot;&gt;3. Make both spin around &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#3-make-both-spin-around&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- We make this div spin --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;spinner&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Mask of the quarter of circle --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mask&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Inner masked circle --&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;maskedCircle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Animation keyframes */&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@keyframes&lt;/span&gt; spin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token selector&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token selector&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;360deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* Spinner */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading .spinner&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 26px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 26px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;animation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; spin 1s infinite linear&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;4-wrap-everything-in-a-loading-container-that-will-be-centered-inside-its-parent&quot; tabindex=&quot;-1&quot;&gt;4. Wrap everything in a &amp;quot;loading&amp;quot; container, that will be centered inside its parent &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#4-wrap-everything-in-a-loading-container-that-will-be-centered-inside-its-parent&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Loading animation container --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- We make this div spin --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;spinner&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Mask of the quarter of circle --&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mask&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Inner masked circle --&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;maskedCircle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Loading animation container */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 28px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 28px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -14px 0 0 -14px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;resulting-html-and-css-code&quot; tabindex=&quot;-1&quot;&gt;Resulting HTML and CSS code: &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#resulting-html-and-css-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Loading animation container --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- We make this div spin --&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;spinner&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Mask of the quarter of circle --&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mask&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Inner masked circle --&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;maskedCircle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Animation keyframes - you need to add prefixes */&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@keyframes&lt;/span&gt; spin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token selector&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token selector&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;360deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* Loading animation container */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 28px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 28px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -14px 0 0 -14px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* Spinning circle (inner circle) */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading .maskedCircle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 12px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3px solid white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* Spinning circle mask */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading .mask&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 12px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 12px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* Spinner */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.loading .spinner&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 26px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 26px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;animation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; spin 1s infinite linear&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isn&#39;t that cool?&lt;/p&gt;
&lt;p&gt;It works perfectly on all desktop browsers like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Internet Explorer 10+&lt;/li&gt;
&lt;li&gt;Edge&lt;/li&gt;
&lt;li&gt;Chrome&lt;/li&gt;
&lt;li&gt;Firefox&lt;/li&gt;
&lt;li&gt;Safari&lt;/li&gt;
&lt;li&gt;Opera&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and also for all major mobile browsers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Safari Mobile&lt;/li&gt;
&lt;li&gt;Chrome Mobile&lt;/li&gt;
&lt;li&gt;Firefox Mobile&lt;/li&gt;
&lt;li&gt;Opera Mobile&lt;/li&gt;
&lt;li&gt;Internet Explorer Mobile (Windows Phone 8 only)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the moment, Windows Phone 7&#39;s Internet Explorer won&#39;t animate the figure.&lt;/p&gt;
&lt;h2 id=&quot;the-fallbacks&quot; tabindex=&quot;-1&quot;&gt;The fallbacks? &lt;a class=&quot;header-anchor&quot; href=&quot;https://andreaverlicchi.eu/en/blog/css-3-only-spinning-loading-animation/#the-fallbacks&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Need a fallback to see the animation in older browsers? If you read so far, you probably do.&lt;/p&gt;
&lt;p&gt;Although the fallback is not the purpose of this article, let&#39;s say that the best solution would be preparing &lt;strong&gt;a sprite with all the frames&lt;/strong&gt; of the animation at a constant distance one from each other, use the sprite as background of a DOM element, and &lt;strong&gt;animate the background with Javascript&lt;/strong&gt;.&lt;/p&gt;
</content>
	</entry>
</feed>
