HTML/CSS/JS snippet library
HTML snippets
1. Modern HTML5 base structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="referrer" content="strict-origin-when-cross-origin">
<title>SEO-optimised title</title>
<meta name="description" content="A compelling description for search results.">
<link rel="canonical" href="https://example.com/page">
<!-- Preconnect to external fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Styles -->
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<h1>Main content</h1>
</main>
</body>
</html>
2. Semantic, accessible layout
<header role="banner">
<nav aria-label="Main navigation">
<ul>
<li><a href="/en/" aria-current="page">Home</a></li>
<li><a href="/services">Services</a></li>
</ul>
</nav>
</header>
<main id="main-content" role="main">
<article>
<header>
<h1>Article title</h1>
<p>Published on <time datetime="2026-07-04">4 July 2026</time></p>
</header>
<section aria-labelledby="sec-intro">
<h2 id="sec-intro">Introduction</h2>
<p>Descriptive content...</p>
</section>
</article>
<aside aria-label="Related resources">
<h3>Useful links</h3>
</aside>
</main>
<footer role="contentinfo">
<p>© 2026 Codedge. All rights reserved.</p>
</footer>
3. Structured contact form
<form action="/submit" method="POST" class="form-container" novalidate>
<div class="form-group">
<label for="user-name">Full name</label>
<input type="text" id="user-name" name="name" required minlength="3" autocomplete="name">
</div>
<div class="form-group">
<label for="user-email">Email address</label>
<input type="email" id="user-email" name="email" required autocomplete="email">
</div>
<div class="form-group">
<label for="user-message">Message</label>
<textarea id="user-message" name="message" rows="5" required minlength="10" placeholder="Write here..."></textarea>
</div>
<button type="submit" class="submit-btn">Send request</button>
</form>
4. Responsive image with picture and WebP
<picture>
<!-- Large screens (desktop), WebP first -->
<source media="(min-width: 1024px)" srcset="image-large.webp" type="image/webp">
<source media="(min-width: 1024px)" srcset="image-large.jpg" type="image/jpeg">
<!-- Small screens (mobile), WebP first -->
<source srcset="image-small.webp" type="image/webp">
<!-- Standard fallback image -->
<img src="image-small.jpg" alt="Image description" loading="lazy" decoding="async" width="600" height="400">
</picture>
5. Responsive video iframe (anti-CLS)
<div class="video-container">
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"
title="Example video"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
loading="lazy">
</iframe>
</div>
<style>
.video-container {
position: relative;
width: 100%;
aspect-ratio: 16 / 9; /* Fixes CLS without the padding-top hack */
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 8px;
}
</style>
CSS snippets
1. Modern CSS reset
/* Reset based on modern best practices */
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: #ffffff;
color: #1a1a1a;
text-rendering: optimizeLegibility;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
height: auto;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
html:focus-within {
scroll-behavior: smooth;
}
2. Flexbox centring and alignment
/* Perfect centring inside a container */
.flex-center {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Flexible, responsive row with gap */
.flex-row {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
justify-content: space-between;
align-items: center;
}
/* Force a flex column on small screens */
@media (max-width: 640px) {
.flex-row {
flex-direction: column;
align-items: stretch;
}
}
3. Auto-responsive grid (no media queries)
/* Generates dynamic columns based on the space available */
.auto-grid {
display: grid;
/* At least 280px, at most 1 share of the remaining space */
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
/* Grid for asymmetric layouts (300px sidebar + flexible main) */
.layout-grid {
display: grid;
grid-template-columns: 300px minmax(0, 1fr);
gap: 2rem;
}
@media (max-width: 768px) {
.layout-grid {
grid-template-columns: 1fr;
}
}
4. CSS variables and native dark mode
/* Root values for the base light theme */
:root {
--primary-color: #007bf0;
--bg-color: #ffffff;
--text-color: #1a1a1a;
--border-color: #e5e7eb;
}
/* Switches on the system's native dark mode */
@media (prefers-color-scheme: dark) {
:root {
--primary-color: #3b82f6;
--bg-color: #111827;
--text-color: #f9fafb;
--border-color: #374151;
}
}
/* Custom properties in practice */
body {
background-color: var(--bg-color);
color: var(--text-color);
border-color: var(--border-color);
}
5. Hover and UI effects
/* Glossy button effect with a smooth transition */
.btn-interactive {
position: relative;
display: inline-flex;
padding: 0.75rem 1.5rem;
background-color: var(--primary-color, #007bf0);
color: #fff;
border-radius: 6px;
overflow: hidden;
transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
}
.btn-interactive:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0, 123, 240, 0.25);
background-color: #0060be;
}
.btn-interactive:active {
transform: translateY(1px);
}
6. CSS carousel with scroll snap
/* Magnetic horizontal scrolling container */
.carousel-snap {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
gap: 1rem;
padding: 1rem 0;
}
/* A single carousel item */
.carousel-item {
flex: 0 0 80%; /* 80% of the parent's width */
scroll-snap-align: center;
border-radius: 8px;
background: #2a2a2a;
}
7. Multi-line text truncation
/* Limits text to an exact number of lines with an ellipsis (...) */
.truncate-lines-3 {
display: -webkit-box;
-webkit-line-clamp: 3; /* Maximum number of lines */
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
/* The classic single-line truncation */
.single-line-ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
JavaScript snippets
1. Event delegation on dynamic elements
// Listen for clicks on the whole container to catch buttons created on the fly
const container = document.querySelector('.dynamic-list');
container.addEventListener('click', (event) => {
// Find the target element with the specific class
const deleteBtn = event.target.closest('.btn-delete');
if (deleteBtn) {
const item = deleteBtn.closest('.list-item');
item.remove(); // Removes the matching element
}
});
2. Debounce and throttle optimisations
// Debounce: runs the function only after N milliseconds of inactivity
function debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// Throttle: runs the function at most once every N milliseconds
function throttle(fn, limit) {
let inThrottle = false;
return function (...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// Example: throttle on scroll, or debounce on search input
window.addEventListener('scroll', throttle(() => console.log('Scrolled!'), 200));
3. Fetch API call with async/await
async function fetchData(url = '') {
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error: status ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error during the fetch call:', error);
return null;
}
}
4. LocalStorage JSON Helper
const storage = {
// Saves an object by converting it to a JSON string
set(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
return true;
} catch (e) {
console.error('LocalStorage write error:', e);
return false;
}
},
// Reads the object back and deserialises it
get(key) {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
} catch (e) {
console.error('LocalStorage read error:', e);
return null;
}
}
};
5. Intersection Observer for lazy loading and animation
// Creates an observer that tracks when elements become visible on screen
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible'); // Adds the class that starts the CSS transitions
observer.unobserve(entry.target); // Stops observing the element once it has fired
}
});
}, {
threshold: 0.15, // Fires when 15% of the element is visible
rootMargin: '0px 0px -50px 0px' // Bottom margin, to fire slightly earlier
});
// Starts the observer on every chosen target
document.querySelectorAll('.animate-on-scroll').forEach(el => observer.observe(el));
UI snippets
2. Reusable content card
<article class="content-card" data-content-card>
<div class="content-card__topline">
<span class="content-card__badge">Guide</span>
<button class="content-card__save" type="button" data-card-save aria-pressed="false">
Save
</button>
</div>
<h2>Web accessibility basics</h2>
<p>The essential checklist for focus, alt text, contrast and keyboard navigation.</p>
<dl class="content-card__meta">
<div><dt>Time</dt><dd>18 min</dd></div>
<div><dt>Level</dt><dd>Beginner</dd></div>
</dl>
<a class="content-card__link" href="#">Open resource</a>
</article>
<style>
.content-card {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 360px;
padding: 1rem;
border: 1px solid #d8dde6;
border-top: 4px solid #14b8a6;
border-radius: 8px;
background: #fff;
color: #172033;
}
.content-card__topline {
display: flex;
justify-content: space-between;
gap: .75rem;
align-items: center;
}
.content-card__badge {
color: #64748b;
font-size: .75rem;
font-weight: 800;
text-transform: uppercase;
}
.content-card__save {
border: 1px solid #cbd5e1;
border-radius: 999px;
background: #fff;
cursor: pointer;
padding: .45rem .7rem;
}
.content-card__save[aria-pressed="true"] {
background: #fff7ed;
border-color: #fb923c;
color: #c2410c;
}
.content-card h2 { margin: 0; font-size: 1.35rem; line-height: 1.2; }
.content-card p { margin: 0; color: #475569; line-height: 1.6; }
.content-card__meta {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: .65rem;
margin: auto 0 0;
}
.content-card__meta div { background: #f8fafc; border-radius: 6px; padding: .7rem; }
.content-card__meta dt { color: #64748b; font-size: .72rem; font-weight: 800; text-transform: uppercase; }
.content-card__meta dd { margin: .2rem 0 0; font-weight: 800; }
.content-card__link {
display: inline-flex;
justify-content: center;
border-radius: 6px;
border: 1px solid #0f766e;
background: #123743;
color: #f8fbff;
font-weight: 800;
padding: .75rem .9rem;
text-decoration: none;
}
.content-card__link:hover,
.content-card__link:focus-visible {
background: #a8f0df;
border-color: #0f766e;
color: #10201f;
}
</style>
<script>
document.querySelectorAll('[data-card-save]').forEach((button) => {
button.addEventListener('click', () => {
const active = button.getAttribute('aria-pressed') === 'true';
button.setAttribute('aria-pressed', String(!active));
});
});
</script>
3. Accessible responsive header
<nav class="site-header" data-accessible-header aria-label="Main navigation">
<a class="site-header__brand" href="/en/">Brand</a>
<button class="site-header__toggle" type="button" data-header-toggle
aria-controls="site-header-menu" aria-expanded="false">
Menu
</button>
<ul class="site-header__menu" id="site-header-menu" data-header-menu>
<li><a href="/en/" data-header-link aria-current="page">Home</a></li>
<li><a href="/en/resources/" data-header-link>Resources</a></li>
<li><a href="/en/projects/" data-header-link>Projects</a></li>
<li><a href="/en/contact/" data-header-link>Contact</a></li>
</ul>
</nav>
<style>
.site-header {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
min-height: 4rem;
padding: .85rem 1rem;
background: #172033;
color: #fff;
}
.site-header__brand,
.site-header__menu a {
color: inherit;
text-decoration: none;
}
.site-header__brand { font-weight: 900; }
.site-header__menu {
display: flex;
gap: .25rem;
align-items: center;
list-style: none;
margin: 0;
padding: 0;
}
.site-header__menu a {
display: inline-flex;
border-radius: 999px;
padding: .55rem .75rem;
font-weight: 700;
}
.site-header__menu a:hover,
.site-header__menu a:focus-visible,
.site-header__menu a[aria-current="page"] {
background: rgba(255, 255, 255, .12);
}
.site-header__toggle {
display: none;
border: 1px solid rgba(255, 255, 255, .24);
border-radius: 999px;
background: transparent;
color: inherit;
cursor: pointer;
font: inherit;
font-weight: 800;
padding: .55rem .75rem;
}
.site-header a:focus-visible,
.site-header button:focus-visible {
outline: 2px solid #67e8f9;
outline-offset: 3px;
}
@media (max-width: 720px) {
.site-header { flex-wrap: wrap; }
.site-header__toggle { display: inline-flex; }
.site-header__menu {
display: none;
flex-basis: 100%;
flex-direction: column;
align-items: stretch;
padding-top: .75rem;
}
.site-header.is-open .site-header__menu { display: flex; }
.site-header__menu a { border-radius: 6px; width: 100%; }
}
</style>
<script>
function initAccessibleHeader(selector = '[data-accessible-header]') {
const header = document.querySelector(selector);
if (!header) return;
const toggle = header.querySelector('[data-header-toggle]');
const links = [...header.querySelectorAll('[data-header-link]')];
function setOpen(open) {
header.classList.toggle('is-open', open);
toggle.setAttribute('aria-expanded', String(open));
}
toggle.addEventListener('click', (event) => {
event.stopPropagation();
setOpen(toggle.getAttribute('aria-expanded') !== 'true');
});
links.forEach((link) => link.addEventListener('click', () => setOpen(false)));
document.addEventListener('click', (event) => {
if (!header.contains(event.target)) setOpen(false);
});
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') setOpen(false);
});
}
initAccessibleHeader();
</script>
4. Contact form with validation
<form class="contact-form" data-contact-form novalidate>
<div class="field">
<label for="name">Name</label>
<input id="name" name="name" required minlength="2" data-validate="name"
aria-describedby="name-error" aria-invalid="false">
<p class="error" id="name-error"></p>
</div>
<div class="field">
<label for="email">Email</label>
<input id="email" name="email" type="email" required data-validate="email"
aria-describedby="email-error" aria-invalid="false">
<p class="error" id="email-error"></p>
</div>
<div class="field">
<label for="message">Message</label>
<textarea id="message" name="message" required minlength="12" data-validate="message"
aria-describedby="message-error" aria-invalid="false"></textarea>
<p class="error" id="message-error"></p>
</div>
<button type="submit" data-submit-button>Send request</button>
<p class="status" data-form-status role="status" aria-live="polite"></p>
</form>
<style>
.contact-form {
display: grid;
gap: 1rem;
max-width: 520px;
padding: 1rem;
border: 1px solid #d8dde6;
border-radius: 8px;
}
.field { display: grid; gap: .4rem; }
.field label { font-weight: 800; }
.field input,
.field textarea {
width: 100%;
border: 1px solid #cbd5e1;
border-radius: 6px;
font: inherit;
padding: .75rem .8rem;
}
.field textarea { min-height: 8rem; resize: vertical; }
.field input:focus,
.field textarea:focus {
border-color: #0ea5e9;
box-shadow: 0 0 0 3px rgba(14, 165, 233, .18);
outline: 0;
}
.field [aria-invalid="true"] { border-color: #ef4444; }
.error { min-height: 1.2rem; margin: 0; color: #b91c1c; font-size: .9rem; }
.status { margin: 0; color: #047857; font-weight: 700; }
button[type="submit"] {
border: 0;
border-radius: 6px;
background: #0f172a;
color: #fff;
cursor: pointer;
font: inherit;
font-weight: 800;
padding: .8rem 1rem;
}
button[disabled] { cursor: wait; opacity: .7; }
</style>
<script>
function initValidatedContactForm(selector = '[data-contact-form]') {
const form = document.querySelector(selector);
if (!form) return;
const fields = [...form.querySelectorAll('[data-validate]')];
const status = form.querySelector('[data-form-status]');
const submit = form.querySelector('[data-submit-button]');
function getMessage(field) {
const value = field.value.trim();
if (field.required && !value) return 'This field is required.';
if (field.type === 'email' && !field.validity.valid) return 'Enter a valid email address.';
if (field.minLength > 0 && value.length < field.minLength) {
return 'Enter at least ' + field.minLength + ' characters.';
}
return '';
}
function validate(field) {
const error = document.getElementById(field.id + '-error');
const message = getMessage(field);
field.setAttribute('aria-invalid', message ? 'true' : 'false');
if (error) error.textContent = message;
return !message;
}
fields.forEach((field) => {
field.addEventListener('input', () => validate(field));
field.addEventListener('blur', () => validate(field));
});
form.addEventListener('submit', (event) => {
event.preventDefault();
const valid = fields.map(validate).every(Boolean);
if (!valid) {
fields.find((field) => field.getAttribute('aria-invalid') === 'true')?.focus();
status.textContent = 'Check the highlighted fields.';
return;
}
submit.disabled = true;
submit.textContent = 'Sending';
status.textContent = 'Message ready to send.';
});
}
initValidatedContactForm();
</script>