From d0e7fcfc0652c8e5b6af0b584838b605efb92a8a Mon Sep 17 00:00:00 2001 From: Caleb Jasik Date: Tue, 24 Aug 2021 01:18:05 -0500 Subject: [PATCH] Lazy load the youtube embed to boost homepage loading times (#1205) --- www/src/components/BaseHead.astro | 1 + www/src/components/YouTube.astro | 51 +++++++++++++++++++ www/src/components/YouTube.css | 82 +++++++++++++++++++++++++++++++ www/src/pages/index.astro | 8 +-- 4 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 www/src/components/YouTube.astro create mode 100644 www/src/components/YouTube.css diff --git a/www/src/components/BaseHead.astro b/www/src/components/BaseHead.astro index 08206b831..d57da1d89 100644 --- a/www/src/components/BaseHead.astro +++ b/www/src/components/BaseHead.astro @@ -35,5 +35,6 @@ const { title, description, canonicalURL } = Astro.props; + diff --git a/www/src/components/YouTube.astro b/www/src/components/YouTube.astro new file mode 100644 index 000000000..f31a5c42d --- /dev/null +++ b/www/src/components/YouTube.astro @@ -0,0 +1,51 @@ +--- +const onload = ` +const link = (rel, href) => { + document.querySelector(\`[rel='\${rel}'][href='\${href}']\`) || document.head.append( + Object.assign( + document.createElement('link'), + { + rel, + href: href + } + ) + ) +}; +const preconnect = () => { + link('preconnect', 'https://googleads.g.doubleclick.net'); + link('preconnect', 'https://static.doubleclick.net'); + link('preconnect', 'https://www.google.com'); + link('preconnect', 'https://www.youtube-nocookie.com'); +}; +const host = this.parentNode; +const v = host.getAttribute('v'); +const iframe = Object.assign( + document.createElement('iframe'), + { + src: \`https://www.youtube-nocookie.com/embed/\${v}?autoplay=1\`, + allow: 'accelerometer;autoplay;encrypted-media;gyroscope;picture-in-picture', + allowFullscreen: true, + } +); +const button = Object.assign( + document.createElement('button'), + { + style: \`background-image:url('https://i.ytimg.com/vi/\${v}/hqdefault.jpg')\`, + onpointerenter: preconnect, + onfocus: preconnect, + onclick(event) { + event.currentTarget.replaceWith(iframe) + }, + } +); + +button.setAttribute('aria-label', host.getAttribute('alt')); + +host.replaceChildren(button); +`.replace(/[\n\r\t]+/g, '') +--- + + + {Astro.props.alt} + + diff --git a/www/src/components/YouTube.css b/www/src/components/YouTube.css new file mode 100644 index 000000000..76917c9c8 --- /dev/null +++ b/www/src/components/YouTube.css @@ -0,0 +1,82 @@ +lite-youtube { + background: #000; + contain: content; + display: block; + max-width: 720px; + position: relative; +} + +/* responsive iframe with a 16:9 aspect ratio (thanks https://css-tricks.com/responsive-iframes/) */ + +lite-youtube::after { + content: ''; + display: block; + padding-bottom: calc(100% / (16 / 9)); +} + +lite-youtube > iframe { + border: 0; + height: 100%; + inset: 0; + position: absolute; + width: 100%; +} + +/* YT's actual play button svg */ + +lite-youtube > a, +lite-youtube > button { + cursor: pointer; + display: block; + height: 100%; + inset: 0; + position: absolute; + width: 100%; +} + +lite-youtube > a > img { + display: block; + height: 100%; + object-fit: cover; + width: 100%; +} + +lite-youtube > a::after, +lite-youtube > button::after { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 68 48'%3E%3Cpath fill='red' fill-opacity='.8' d='M66.5 7.7c-.8-2.9-2.5-5.4-5.4-6.2C55.8.1 34 0 34 0S12.2.1 6.9 1.6c-3 .7-4.6 3.2-5.4 6.1a89.6 89.6 0 000 32.5c.8 3 2.5 5.5 5.4 6.3C12.2 47.9 34 48 34 48s21.8-.1 27.1-1.6c3-.7 4.6-3.2 5.4-6.1C68 35 68 24 68 24s0-11-1.5-16.3z'/%3E%3Cpath fill='%23fff' d='M45 24L27 14v20'/%3E%3C/svg%3E"); + display: block; + width: 68px; + height: 48px; + position: absolute; + inset: calc(50% - 68px / 2) calc(50% - 48px / 2) auto auto; + transition: filter 0.1s cubic-bezier(0, 0, 0.2, 1); +} + +lite-youtube > button { + background: #000 50% 50% / cover; + border: none; +} + +/* gradient */ + +lite-youtube button::before { + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAQAAAC58SIOAAAAaklEQVR42nWOUQrAMAhD1e7+B9kZ1zqYKAk6yMfLa8Ca3CbbxL+cTJgNNeDhTZmdQXb24/KAPNNFjDf2CQSMJGCVViveAKuy1AZYFaCqcrVkA4NgGeTKYlg/Jvhio/w6LuvQNV1U3sS31wvH7lU36biAMgAAAABJRU5ErkJggg==') + top repeat-x; + content: ''; + display: block; + height: 60px; + padding-bottom: 50px; + position: absolute; + top: 0; + transition: all 0.2s cubic-bezier(0, 0, 0.2, 1); + width: 100%; +} + +lite-youtube > button::after { + filter: grayscale(100%); +} + +lite-youtube:hover > button::after, +lite-youtube button:focus::after { + filter: none; +} diff --git a/www/src/pages/index.astro b/www/src/pages/index.astro index ef31a9606..6ef6ad710 100644 --- a/www/src/pages/index.astro +++ b/www/src/pages/index.astro @@ -6,6 +6,8 @@ import Logo from '../components/Logo.astro'; import Article from '../components/Article.astro'; import Tagline from '../components/Tagline.astro'; import MainHeader from '../components/MainHeader.astro'; +import YouTube from '../components/YouTube.astro'; +import "../components/YouTube.css"; let title = 'Astro'; let description = 'Build faster websites with less client-side JavaScript'; @@ -26,9 +28,7 @@ let lang = 'en';
-
- -
+ @@ -90,7 +90,7 @@ let lang = 'en'; background:rgba(255, 255, 255, 0.1); margin-bottom: 1rem; } - .videoWrapper iframe { + .videoWrapper > iframe { position: absolute; top: 0; left: 0;