Greetings. Here's a translation of the article "Ruthlessly Eliminating Layout Shift On Netlify.com" published on November 25, 2020 by author Zach Leatherman.
On the Netlify website, we have a small banner that appears at the top to drive traffic to new and interesting things happening in the Netlify world.
This banner has two parts:
An advanced HTML feature that only old-school developers know about: hyperlink.
( )
, :
. ⚠️⚠️⚠️ . JavaScript JavaScript .
JavaScript
localStorage
, , . - URL- , , . - .
, . , HTML ().
(, ) JavaScript 2 3 <body>
, :
? . . JavaScript , .
1, . JavaScript JavaScript .
JavaScript- : , , - .
Update: GitHub .
HTML CSS
opacity
, , JavaScript.
.banner--hide announcement-banner,
announcement-banner[hidden] {
display: none;
}
[data-banner-close] {
opacity: 0;
pointer-events: none;
}
.banner--show-close [data-banner-close] {
opacity: 1;
pointer-events: auto;
}
<announcement-banner>
<a href="https://www.netlify.com/sustainability/">Read about our Sustainability</a>
<button type="button" data-banner-close>Close</button>
</announcement-banner>
JavaScript
banner-helper.js
, <head>
:
// CTA , JSON
let ctaUrl = "https://www.netlify.com/sustainability/";
let savedCtaUrl = localStorage.getItem("banner--cta-url");
if(savedCtaUrl === ctaUrl) {
document.documentElement.classList.add("banner--hide");
}
banner.js
, ( - ):
class Banner extends HTMLElement {
connectedCallback() {
// , , ,
// -
// .
this.classList.add("banner--show-close");
let button = this.getButton();
if(button) {
button.addEventListener("click", () => {
this.savePreference();
this.close();
});
}
}
getButton() {
return this.querySelector("[data-banner-close]");
}
savePreference() {
let cta = this.querySelector("a[href]");
if(cta) {
let ctaUrl = cta.getAttribute("href");
localStorage.setItem("banner--cta-url", ctaUrl);
}
}
close() {
this.setAttribute("hidden", true);
}
}
window.customElements.define("announcement-banner", Banner);
, -, .
And since we inserted the re-views script in <head>
when the user hides the banner and navigates to a new page, the banner will also be hidden before the first render.
Pretty good for such small changes!
The next goal will be to improve the display of web fonts.