Components Easy
CodePen Embed
Lazy-loaded CodePen iframe that defers creation until the user clicks a placeholder, keeping page load fast.
Open in Lab
MCP
css javascript
Targets: HTML
Code
:root {
color-scheme: dark;
font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
background: #080808;
color: #e2e8f0;
}
.stage {
max-width: 1280px;
margin: 0 auto;
padding: 2rem 1.5rem;
}
@media (max-width: 480px) {
.stage { padding: 1.5rem 1rem; }
.cp-placeholder { padding: 1.25rem; }
}
/* โโโ Grid โโโ */
.embeds-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
gap: 1.5rem;
}
/* โโโ Embed wrapper โโโ */
.cp-embed {
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.09);
overflow: hidden;
background: rgba(255, 255, 255, 0.02);
}
/* โโโ Placeholder (before iframe loads) โโโ */
.cp-placeholder {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
gap: 1.5rem;
padding: 1.5rem;
min-height: 180px;
}
.cp-meta {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.cp-logo {
display: flex;
align-items: center;
gap: 7px;
font-size: 0.8rem;
font-weight: 600;
color: rgba(255, 255, 255, 0.35);
letter-spacing: 0.02em;
}
.cp-title {
font-size: 1rem;
font-weight: 600;
color: #f8fafc;
line-height: 1.3;
}
.cp-author {
font-size: 0.8rem;
color: rgba(255, 255, 255, 0.35);
}
/* โโโ Run button โโโ */
.cp-run-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 18px;
border-radius: 8px;
font-size: 0.8125rem;
font-weight: 500;
font-family: inherit;
color: #f8fafc;
background: rgba(79, 70, 229, 0.2);
border: 1px solid rgba(79, 70, 229, 0.3);
cursor: pointer;
transition: background 0.15s, border-color 0.15s;
}
.cp-run-btn:hover {
background: rgba(79, 70, 229, 0.35);
border-color: rgba(79, 70, 229, 0.45);
}<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CodePen Embed</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<main class="stage">
<div class="embeds-grid">
<!-- Lazy CodePen embed -->
<!-- Replace data-pen-user and data-pen-hash with your CodePen username and pen hash -->
<div
class="cp-embed"
data-pen-user="stealthis"
data-pen-hash="abcXYZ"
data-pen-title="Glow Metric Card"
data-pen-tabs="html,css,result"
data-pen-height="400"
>
<div class="cp-placeholder">
<div class="cp-meta">
<div class="cp-logo">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M24 8.18L12 0 0 8.18v7.64L12 24l12-8.18V8.18zm-2 1.48v4.68l-3.34-2.34 3.34-2.34zM13 3.35l7.94 5.4-3.44 2.41L13 8.31V3.35zm-2 0v4.96L7.5 11.16 4.06 8.75 11 3.35zM2 9.66l3.34 2.34L2 14.34V9.66zm9 11-7.94-5.4 3.44-2.41L11 15.7v4.96zm1-6.61-2.9-2.05L12 9.95l2.9 2.05L12 14.05zm1 6.61V15.7l4.5-3.16 3.44 2.41L13 20.66z"/>
</svg>
CodePen
</div>
<p class="cp-title">Glow Metric Card</p>
<p class="cp-author">by stealthis</p>
</div>
<button class="cp-run-btn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"/>
</svg>
Run Pen
</button>
</div>
</div>
<!-- Second example -->
<div
class="cp-embed"
data-pen-user="stealthis"
data-pen-hash="defABC"
data-pen-title="Filter Search Bar"
data-pen-tabs="html,css,result"
data-pen-height="400"
>
<div class="cp-placeholder">
<div class="cp-meta">
<div class="cp-logo">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M24 8.18L12 0 0 8.18v7.64L12 24l12-8.18V8.18zm-2 1.48v4.68l-3.34-2.34 3.34-2.34zM13 3.35l7.94 5.4-3.44 2.41L13 8.31V3.35zm-2 0v4.96L7.5 11.16 4.06 8.75 11 3.35zM2 9.66l3.34 2.34L2 14.34V9.66zm9 11-7.94-5.4 3.44-2.41L11 15.7v4.96zm1-6.61-2.9-2.05L12 9.95l2.9 2.05L12 14.05zm1 6.61V15.7l4.5-3.16 3.44 2.41L13 20.66z"/>
</svg>
CodePen
</div>
<p class="cp-title">Filter Search Bar</p>
<p class="cp-author">by stealthis</p>
</div>
<button class="cp-run-btn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"/>
</svg>
Run Pen
</button>
</div>
</div>
</div>
</main>
<script>
document.querySelectorAll('.cp-embed').forEach(embed => {
const btn = embed.querySelector('.cp-run-btn');
btn.addEventListener('click', () => {
const user = embed.dataset.penUser;
const hash = embed.dataset.penHash;
const tabs = embed.dataset.penTabs || 'html,css,result';
const height = embed.dataset.penHeight || '400';
const src = `https://codepen.io/${user}/embed/${hash}?default-tab=${tabs}&theme-id=dark`;
const iframe = document.createElement('iframe');
iframe.src = src;
iframe.height = height;
iframe.width = '100%';
iframe.title = embed.dataset.penTitle || 'CodePen Embed';
iframe.setAttribute('allowfullscreen', '');
iframe.style.border = 'none';
iframe.style.borderRadius = '0 0 10px 10px';
embed.innerHTML = '';
embed.appendChild(iframe);
});
});
</script>
</body>
</html>CodePen Embed
A lightweight CodePen embed that shows a styled placeholder with the pen title and a โRunโ button. The actual <iframe> is only created when the user clicks โ keeping Time to Interactive fast on pages with many embeds.
Features
- Zero iframe cost until user interaction
- Shows pen title, author, and a preview placeholder
- Builds the full
//codepen.io/.../embed/URL on click - Configurable default tabs (
html,css,resultetc.) - Multiple embeds on the same page stay independent
When to use
- Documentation pages with live code examples
- Tutorial or blog posts with interactive demos
- Any page embedding multiple CodePens