Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <h1>
	Lazy loading JS by visibility
</h1>

<p>
	Here’s a neat trick.
</p>

<p>
	<a href="https://twitter.com/FredKSchott">Fred K. Schott</a>
	gives an impressive presentation of
	<a href="https://www.youtube.com/watch?v=mgkwZqVkrwo">Astro</a>,
	a framework-agnostic architecture for building web sites and web apps.
</p>

<iframe
	title="YouTube video player"
	width="560"
	height="315"
	src="https://www.youtube-nocookie.com/embed/mgkwZqVkrwo?rel=0&controls=0&fs=0&start=2356&end=2373"
	allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
	allowfullscreen
></iframe>

<blockquote>
	<p>
		We add a script to the end of your page.
		It’s inline. It essentially runs almost immediately,
		and that is what is going to create that
		<a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">Intersection Observer</a>.
		It’s going to do a dynamic import of the things that you need,
		and it’s going to call React render on that component.
	</p>
</blockquote>

<p>
	During the presentation, Fred demonstrates dynamically loading JS using
	<a href="https://jasonformat.com/islands-architecture/">"Islands Architecture"</a>,
	a strategy
	where small HTML placeholders are progressively upgraded with dynamic or interactive content as-needed.
</p>

<p>
	The demonstration involves
	waiting on the viewport visibility of a <code>div</code> placeholder before loading some JS.
</p>

<p>
	The entire setup contributes less than 200 bytes to the page when gzipped.
</p>

<pre><code>&lt;div data-astro-id="3459833264469372"&gt;&lt;/div&gt;
&lt;script type="module"&gt;

<b -com>/* scaffolding put before the code */</b>
<mark>((o=new IntersectionObserver((([{isIntersecting,target}])=>{isIntersecting&&(o.disconnect(),</mark>

<b -com>/* code run when the section is visible */</b>
<b -var>Promise</b>.<b -ent>all</b>([
	<b -key>import</b>(<b -str>'https://cdn.skypack.dev/react'</b>),
	<b -key>import</b>(<b -str>'https://cdn.skypack.dev/react-dom'</b>),
]).<b -ent>then</b>( ([
	{ <b -con>default</b>: <b -var>React</b> },
	{ <b -con>default</b>: <b -var>ReactDOM</b> },
]) => <b -var>ReactDOM</b>.<b -ent>render</b>(
	<b -var>React</b>.<b -ent>createElement</b>(<b -str>'strong'</b>, {},
		<b -str>'This was rendered with React!'</b>,
	),
	<b -ent>target</b>,
) )

<b -com>/* scaffolding put after the code */</b>
<mark>)})))=>{o.observe(document.querySelector('[data-astro-id="3459833264469372"]'))})()</mark>
&lt;/script&gt;</code></pre>

<p>
	Neat trick, right?
</p>

<p>
	It can be used once, or multiple times in different places.
	JS can be loaded by <a href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/observe">element visibility</a>,
	a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia">media query</a>,
	a <a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe">container query</a>,
	any <a href="https://developer.mozilla.org/en-US/docs/Web/Events">event</a>,
	any <a href="https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver/observe">asset</a>,
	any <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback">idle period</a>,
	or any mix of these,
	and any other condition that’s helpful.
</p>

<p>
	Below is a live demonstration.
</p>
<p style="margin:25vh 0">👇</p>

<div data-astro-id="3459833264469372">&nbsp;</div>
<script type="module">
((
	o = new IntersectionObserver(
		([{ isIntersecting, target }]) => {
			if (isIntersecting) {
				o.disconnect()
				Promise.all([
					import('https://cdn.skypack.dev/react'),
					import('https://cdn.skypack.dev/react-dom')
				]).then(
					([{ default: React }, { default: ReactDOM }]) => ReactDOM.render(
						React.createElement('strong', {},
							'This was rendered with React!'
						),
						target
					)
				)
			}
		}
	),
	f = document.createDocumentFragment(),
) => o.observe(
	document.querySelector('[data-astro-id="3459833264469372"]')
))()
</script>

<p style="margin:25vh 0">👆</p>

<p>
	Above is a live demonstration.
</p>

<hr />

<p>
	That’s all.
</p>

<p>
	It just seems like a neat trick.
</p>
              
            
!

CSS

              
                * {
	box-sizing: border-box;
}

body {
	align-items: center;
	display: flex;
	font: 125%/1.5 system-ui, -apple-system;
	flex-flow: column wrap;
	margin: 1em 1em 4em;
	overflow-wrap: anywhere;
	tab-size: 2;
	-webkit-text-size-adjust: none;
}

body > * {
	max-width: 34rem;
}

blockquote {
	box-shadow: inset .75em 0 0 #039be5;
	font: italic 125%/1.5 Roboto, serif;
	margin-inline-start: 0;
	padding-left: 2em;
}

@media (max-width: 640px) {
	blockquote {
		box-shadow: inset .5em 0 0 #039be5;
	}
}

pre, code {
	font: 85%/inherit SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
}

pre, p code {
	background: #f6f8fa;
	border-radius: 6px;
}

p code {
	padding: .25em .365em;
}

pre {
	display: flex;
	padding: 1em;
	overflow: scroll;
	max-width: 100%;
}

pre > code {
	display: block;
	min-width: 60em;
}

pre b {
	font-weight: normal;
}

iframe {
	border: 0;
	width: 100%;
}

strong {
	background-color: #84ff6f;
	border-radius: 1em;
	padding: 1em;
}

hr {
	background:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 150 640 80'%3E%3Cpath d='M130 192c6-7 4-18 0-21-9-6-17 6-13 18 4 13 14 21 28 24 29 5 88-27 126-37 27-8 44 3 54 16-19-14-36-9-54-6-41 8-82 40-127 35-21-3-35-24-34-40l1-4c3-10 7-14 12-15 11-3 23 18 7 30z' /%3E%3Cpath d='M120 199c-8-7-16-18-24-23-79-53-120 18-79 39 6 3 19 5 28-8-11 9-24 6-29 1-14-12-9-29 7-36 26-10 49 0 70 15 14 9 18 13 30 18-7 0-3-8-10-13l7 7zM487 190c-6 8-4 19 1 22 9 6 18-6 14-18-5-13-15-22-30-24-31-6-94 27-134 37-29 7-47-4-57-16 20 13 38 9 57 5 43-7 87-39 134-34 22 3 38 24 37 40l-1 4c-3 10-8 14-13 15-12 3-24-18-8-31z' /%3E%3Cpath d='M497 179c9 8 18 19 26 24 83 52 126-18 83-39-7-3-20-5-30 8 12-9 25-6 31-1 14 11 9 28-8 36-27 10-52-1-73-15-15-9-19-13-32-18 7 0 4 8 10 12l-7-7z' /%3E%3C/svg%3E") 0
		/ 100% auto no-repeat
	;
	border: 0;
	height: 5em;
	margin-block-end: 3em;
	margin-block-start: 3em;
	width: 100%;
}

[-var] { color: #e36209; }
[-ent] { color: #6f42c1; }
[-key] { color: #d73a49; }
[-str] { color: #136203; }
[-con] { color: #005cc5; }
[-com] { color: #6a737d; }
              
            
!

JS

              
                
              
            
!
999px

Console