HCJ Cheatsheet

Everything you need to build a top-notch developer website. Reference-ready, template-portable.

HTML — Structure & Semantics

HTML

Boilerplate — Every Page Starts Here

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="Your site description for SEO">
  <meta property="og:title" content="Your Name | Developer">
  <meta property="og:image" content="og-image.png">
  <link rel="icon" href="favicon.ico">
  <link rel="stylesheet" href="styles.css">
  <title>Your Name | Developer</title>
</head>
<body>
  <!-- content -->
  <script src="main.js" defer></script>
</body>
</html>

Semantic Layout Tags

Use these for structure, SEO, and accessibility:

TagPurpose
<header>Site or section header, nav
<nav>Navigation links
<main>Primary page content (1 per page)
<section>Thematic grouping with heading
<article>Self-contained content (post, card)
<aside>Tangentially related content
<footer>Footer, credits, links
<figure> / <figcaption>Image + caption wrapper
<time datetime="">Machine-readable dates
<address>Contact info

Text & Inline Elements

TagMeaning
<h1>–<h6>Headings (one h1 per page)
<p>Paragraph
<strong>Strong importance (bold)
<em>Emphasis (italic)
<span>Inline container (styling only)
<div>Block container (layout only)
<a href>Hyperlink
<abbr title>Abbreviation with tooltip
<code> / <pre>Inline / block code
<br> / <hr>Line break / thematic break

Links & Media Attributes

<!-- Link -->
<a
  href="/about"
  target="_blank"         open new tab
  rel="noopener noreferrer" security
  aria-label="About me"
>About</a>

<!-- Image -->
<img
  src="photo.webp"
  alt="Descriptive alt text"  required!
  width="800" height="600"  prevent CLS
  loading="lazy"
  decoding="async"
>

Forms & Inputs

<form action="" method="post" novalidate>
  <label for="email">Email</label>
  <input
    type="email"
    id="email"
    name="email"
    required
    autocomplete="email"
    placeholder="[email protected]"
  >
  <button type="submit">Send</button>
</form>

<!-- Input types: text email password number
  tel url search date range color file checkbox
  radio submit reset button -->

Lists

<!-- Unordered -->
<ul>
  <li>Item</li>
</ul>

<!-- Ordered -->
<ol start="1" reversed>
  <li>First</li>
</ol>

<!-- Description list (great for key/value) -->
<dl>
  <dt>JavaScript</dt>
  <dd>Language of the web</dd>
</dl>

Head Meta Tags You Need

<!-- SEO -->
<meta name="description" content="...">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://yoursite.com/">

<!-- Open Graph (social sharing) -->
<meta property="og:title" content="...">
<meta property="og:description" content="...">
<meta property="og:image" content="og.png">
<meta property="og:url" content="...">

<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">

<!-- Performance -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preload" as="image" href="hero.webp">

CSS — Styles & Variables

CSS

CSS Custom Properties (Variables) — The Foundation

/* styles.css — put variables in :root */
:root {
  /* Colors */
  --color-bg:       #0a0a0f;
  --color-surface:  #13131a;
  --color-text:     #e8e8f0;
  --color-muted:    #7070a0;
  --color-accent:   #6ee7f7;
  --color-border:   #2a2a3d;

  /* Typography */
  --font-sans:    'Inter', sans-serif;
  --font-display: 'Syne', sans-serif;
  --font-mono:    'JetBrains Mono', monospace;

  /* Spacing scale */
  --sp-xs: 4px;   --sp-sm: 8px;
  --sp-md: 16px;  --sp-lg: 24px;
  --sp-xl: 40px;  --sp-2xl: 64px;

  /* Radii */
  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 20px;

  /* Transitions */
  --transition: all 0.2s ease;
  --transition-slow: all 0.4s ease;
}

/* Use like: color: var(--color-accent); */
/* Override for dark mode: */
@media (prefers-color-scheme: light) {
  :root { --color-bg: #ffffff; }
}

CSS Reset / Base

/* Modern minimal reset */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0; padding: 0;
}
html {
  scroll-behavior: smooth;
  text-size-adjust: 100%;
}
body {
  font-family: var(--font-sans);
  background: var(--color-bg);
  color: var(--color-text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img, video { max-width: 100%; display: block; }
button { cursor: pointer; border: none; background: none; }
a { color: inherit; text-decoration: none; }

Selectors Reference

SelectorTargets
.classClass
#idID (use sparingly)
el > childDirect children
el + siblingAdjacent sibling
el ~ siblingsAll siblings after
[attr="val"]Attribute value
:hover :focus :activeState
:nth-child(2n+1)Formula-based
:not(.class)Negation
::before ::afterPseudo-elements
:is(h1,h2,h3)Matches any in list
:where()Zero-specificity :is()
:has(img)Parent with child

Typography System

h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
h1 { font-size: clamp(2rem, 5vw, 4rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2.5rem); }
p  { max-width: 65ch; } /* optimal line length */

/* Fluid font scale */
font-size: clamp(min, preferred, max);
font-size: clamp(1rem, 2.5vw, 1.5rem);

/* Text utilities */
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden; /* truncation trio */

-webkit-line-clamp: 3; /* multi-line clamp */
display: -webkit-box;
-webkit-box-orient: vertical;

Backgrounds & Visual FX

/* Gradient backgrounds */
background: linear-gradient(135deg, #0a0a0f, #1c1c28);
background: radial-gradient(ellipse at 50% 0%, #6ee7f733, transparent 70%);

/* Glassmorphism */
background: rgba(255,255,255,0.05);
backdrop-filter: blur(16px) saturate(180%);
border: 1px solid rgba(255,255,255,0.1);

/* Box shadows */
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
box-shadow: 0 0 0 2px var(--color-accent); focus ring
box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);

/* Layered glow */
box-shadow:
  0 0 20px rgba(110,231,247,0.3),
  0 0 60px rgba(110,231,247,0.1);

/* Noise texture overlay */
background-image: url("noise.svg");

/* Clip path shapes */
clip-path: polygon(0 0, 100% 0, 100% 90%, 0 100%);

Transitions & Animations

/* Transition */
transition: transform 0.2s ease, opacity 0.2s ease;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

/* Keyframe animation */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}
.element {
  animation: fadeUp 0.6s ease forwards;
  animation-delay: 0.1s;
}

/* Stagger children */
.item:nth-child(1) { animation-delay: 0.1s; }
.item:nth-child(2) { animation-delay: 0.2s; }

/* Respect user preferences */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; }
}

Useful Properties Quicklist

PropertyNotes
aspect-ratio: 16/9Maintain ratio
object-fit: coverImage fill
overflow: clipNo scrollbar unlike hidden
gap: 1remFlex/grid spacing
place-items: centergrid center shorthand
inset: 0top/right/bottom/left: 0
pointer-events: noneClick-through
user-select: nonePrevent text selection
will-change: transformGPU hint (use sparingly)
isolation: isolateNew stacking context
contain: layout stylePerf isolation
scroll-snap-type: xCarousel snap
accent-color: var(--c)Style form inputs

Layout — Flexbox & Grid

CSS

Flexbox

/* Container */
.flex {
  display: flex;
  flex-direction: row | column;
  flex-wrap: wrap;
  justify-content: flex-start | center | space-between | space-around | space-evenly;
  align-items: stretch | center | flex-start | flex-end | baseline;
  align-content: start | center; /* multi-line */
  gap: 16px; /* or row-gap / column-gap */
}

/* Child */
.item {
  flex: 1;          /* grow, shrink, basis */
  flex: 0 0 200px;  /* fixed width */
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: auto | 50%;
  align-self: center;
  order: -1;        /* reorder visually */
  min-width: 0;     /* CRITICAL: prevents overflow */
}

CSS Grid

/* Container */
.grid {
  display: grid;

  /* Common patterns */
  grid-template-columns: repeat(3, 1fr);
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  grid-template-columns: 250px 1fr; sidebar + main
  grid-template-columns: 1fr min(65ch, 100%) 1fr; centered

  grid-template-rows: auto 1fr auto; header/main/footer
  gap: 24px 16px; row / column
}

/* Child placement */
.item {
  grid-column: 1 / 3;    spans 2 cols
  grid-column: 1 / -1;   full width
  grid-row: 2 / 4;
  grid-area: header;     named areas
  place-self: center;
}

Page Layout Patterns

/* Holy Grail layout */
.page {
  display: grid;
  grid-template:
    "header header" auto
    "nav    main  " 1fr
    "footer footer" auto
    / 200px 1fr;
  min-height: 100dvh;
}

/* Sticky footer */
.page {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}
.main { flex: 1; }

/* Center anything */
.center {
  display: grid;
  place-items: center;
}

/* Content width with bleed */
.container {
  width: min(1200px, 100% - 2rem);
  margin-inline: auto;
}

Positioning

/* Position values */
position: static;   /* default, in flow */
position: relative; /* offset from normal */
position: absolute; /* relative to nearest positioned ancestor */
position: fixed;    /* relative to viewport */
position: sticky;   /* hybrid, needs top/left */

/* Centering with absolute */
.overlay {
  position: absolute;
  inset: 0; /* fills parent */
}
.centered {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}

/* Sticky nav */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
}

Responsive Design

CSS

Media Queries

/* Mobile-first approach (recommended) */
/* Base = mobile styles */

@media (min-width: 640px)  { /* sm  */ }
@media (min-width: 768px)  { /* md  */ }
@media (min-width: 1024px) { /* lg  */ }
@media (min-width: 1280px) { /* xl  */ }
@media (min-width: 1536px) { /* 2xl */ }

/* User preferences */
@media (prefers-color-scheme: dark) { }
@media (prefers-reduced-motion: reduce) { }
@media (hover: none) { } /* touch device */

/* Containers (component-level) */
.card { container-type: inline-size; }
@container (min-width: 400px) {
  .card-inner { display: flex; }
}

Fluid & Responsive Units

UnitMeaning
vw / vhViewport width/height
dvw / dvhDynamic viewport (mobile-safe)
svh / lvhSmall / large viewport
remRoot font-size relative
emParent font-size relative
chWidth of "0" character
clamp(a,b,c)Fluid between min and max
min() / max()Choose smallest/largest
%Relative to parent
Pro: Use min(100%, 600px) instead of max-width: 600px; width: 100%.

JavaScript — DOM & Scripting

JS

DOM Selection & Manipulation

// Select elements
const el  = document.querySelector('.class');
const all = document.querySelectorAll('li');
const id  = document.getElementById('main');

// Modify content
el.textContent = 'Safe text';       // XSS-safe
el.innerHTML = '<b>Bold</b>';         // parsed HTML

// Classes
el.classList.add('active');
el.classList.remove('active');
el.classList.toggle('active');
el.classList.contains('active');    // → bool

// Attributes
el.setAttribute('aria-expanded', 'true');
el.getAttribute('href');
el.removeAttribute('hidden');
el.dataset.id;         // data-id attribute

// Styles
el.style.transform = 'translateY(0)';
getComputedStyle(el).getPropertyValue('--var');

Events

// Add / remove listeners
el.addEventListener('click', handler);
el.removeEventListener('click', handler);

// Common events
// click dblclick mouseenter mouseleave
// keydown keyup keypress
// submit input change focus blur
// scroll resize load DOMContentLoaded
// touchstart touchend
// pointerdown pointermove pointerup

// Event object
function handler(e) {
  e.preventDefault();   // stop default
  e.stopPropagation(); // stop bubbling
  e.target;            // element clicked
  e.currentTarget;     // element with listener
  e.key;               // keyboard key
  e.clientX; e.clientY; // mouse position
}

// Event delegation (efficient)
document.addEventListener('click', (e) => {
  if (e.target.matches('.btn')) { /* handle */ }
});

Async / Fetch / APIs

// Fetch API
async function getData(url) {
  try {
    const res = await fetch(url, {
      method: 'GET',
      headers: { 'Content-Type': 'application/json' },
    });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return await res.json();
  } catch (err) {
    console.error(err);
  }
}

// Intersection Observer (scroll reveal)
const observer = new IntersectionObserver(
  (entries) => entries.forEach(e => {
    if (e.isIntersecting) e.target.classList.add('visible');
  }),
  { threshold: 0.1 }
);
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));

// ResizeObserver
const ro = new ResizeObserver(entries => { /* ... */ });
ro.observe(el);

Modern JS Essentials

// Destructuring
const { name, age = 0 } = user;
const [first, ...rest] = arr;

// Spread / Rest
const merged = { ...defaults, ...overrides };
const copy   = [...arr, newItem];

// Optional chaining
user?.address?.city;
arr?.[0]?.name;
fn?.();

// Nullish coalescing
const val = input ?? 'default';

// Template literals
const html = `<li class="item">${name}</li>`;

// Array methods
arr.map(x => x * 2);
arr.filter(x => x > 0);
arr.reduce((acc, x) => acc + x, 0);
arr.find(x => x.id === id);
arr.some(x => x.active);
arr.every(x => x.valid);
arr.flat(Infinity);
arr.flatMap(x => [x, x * 2]);

// Object methods
Object.keys(obj); Object.values(obj); Object.entries(obj);
Object.fromEntries(entries);

Storage & State

// localStorage (persists)
localStorage.setItem('key', JSON.stringify(data));
const data = JSON.parse(localStorage.getItem('key'));
localStorage.removeItem('key');

// sessionStorage (tab-scoped)
sessionStorage.setItem('key', value);

// URL state (shareable)
const params = new URLSearchParams(location.search);
params.get('tab');
params.set('tab', 'projects');
history.pushState(null, '', `?${params}`);

// Simple state pattern
const state = { theme: 'dark', menuOpen: false };
function setState(key, val) {
  state[key] = val;
  render();
}

Useful Browser APIs

// Clipboard
await navigator.clipboard.writeText('copied!');

// Web Animations API
el.animate(
  [{ opacity: 0 }, { opacity: 1 }],
  { duration: 400, easing: 'ease', fill: 'forwards' }
);

// matchMedia
const dark = matchMedia('(prefers-color-scheme: dark)').matches;

// Scroll
el.scrollIntoView({ behavior: 'smooth', block: 'start' });
scrollTo({ top: 0, behavior: 'smooth' });

// Debounce utility
function debounce(fn, ms) {
  let t;
  return (...args) => { clearTimeout(t); t = setTimeout(() => fn(...args), ms); };
}
const onResize = debounce(() => { /* ... */ }, 200);

// Dialog (native modal)
dialog.showModal(); dialog.close();

Performance & Best Practices

PERF

Image Optimization

<picture>
  <source type="image/avif"
          srcset="img.avif">
  <source type="image/webp"
          srcset="img.webp">
  <img src="img.jpg"
       alt="..."
       loading="lazy"
       decoding="async"
       width="800"
       height="450">
</picture>
Format priority: AVIF → WebP → JPG/PNG

Font Loading

/* Preconnect in <head> */
<link rel="preconnect"
      href="https://fonts.googleapis.com">

/* CSS font-display */
@font-face {
  font-family: 'MyFont';
  src: url('font.woff2') format('woff2');
  font-display: swap;
  /* swap = text visible immediately */
  /* optional = skips if slow */
}

/* Self-host for best perf */
/* Use fontsource npm packages */

Core Web Vitals Tips

MetricTarget
LCP (load)< 2.5s
INP (interact)< 200ms
CLS (shift)< 0.1

Prevent CLS: always set width/height on images. Improve LCP: preload hero image. Improve INP: avoid long tasks, use requestIdleCallback.

Script Loading

<!-- defer: executes after HTML parse -->
<script src="main.js" defer></script>

<!-- async: downloads in parallel, runs ASAP -->
<script src="analytics.js" async></script>

<!-- module: deferred + ESM -->
<script type="module" src="app.js"></script>

/* Dynamic import */
const { fn } = await import('./module.js');

CSS Performance

/* Use transform/opacity for animation */
/* (composited, no layout/paint) */
transform: translateX(100px);
opacity: 0;

/* Avoid animating: */
/* width, height, top, left, margin */
/* These trigger layout (expensive) */

/* Contain layout for widgets */
.widget {
  contain: layout style paint;
}

/* Critical CSS inline in <head> */
/* Use tools: Critical, PurgeCSS */

Resource Hints

<!-- In <head> -->

<!-- DNS lookup -->
<link rel="dns-prefetch" href="//cdn.example.com">

<!-- Early connection -->
<link rel="preconnect" href="https://fonts.gstatic.com">

<!-- Preload critical assets -->
<link rel="preload" as="image" href="hero.webp">
<link rel="preload" as="font"
      href="font.woff2" crossorigin>

<!-- Prefetch next pages -->
<link rel="prefetch" href="/projects">

Accessibility (A11y)

A11Y

ARIA & Roles

<!-- Landmark roles (prefer semantic HTML) -->
role="banner"      → <header>
role="navigation"  → <nav>
role="main"        → <main>
role="complementary" → <aside>
role="contentinfo" → <footer>

<!-- Labels -->
aria-label="Close menu"
aria-labelledby="heading-id"
aria-describedby="desc-id"

<!-- States -->
aria-expanded="true|false"
aria-hidden="true"      hide from SR
aria-live="polite"      dynamic updates
aria-current="page"    active nav link
aria-disabled="true"
tabindex="0"            make focusable
tabindex="-1"           focusable by JS only

Focus & Keyboard

/* NEVER remove focus outline without replacement */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 4px;
}
:focus:not(:focus-visible) {
  outline: none; /* hide for mouse only */
}

/* Skip to main content */
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
}
.skip-link:focus { top: 0; }

/* Trap focus in modals */
// query all focusable, on Tab wrap around
const focusable = modal.querySelectorAll(
  'button,a,[tabindex]:not([tabindex="-1"])'
);

Color & Contrast

LevelNormal textLarge text
AA4.5:13:1
AAA7:14.5:1
Tools: Chrome DevTools accessibility panel, WebAIM Contrast Checker, axe DevTools extension, NVDA / VoiceOver screen readers.

Checklist

✅ All images have meaningful alt text (or alt="" for decorative)

✅ Logical heading hierarchy (h1→h2→h3)

✅ All interactive elements keyboard-accessible

✅ Form inputs have associated <label>

✅ Color is not the only way to convey info

✅ Sufficient color contrast (4.5:1 minimum)

✅ Focus indicators visible

✅ No content flashes more than 3x/sec

✅ Page works at 200% zoom

Page Structure Template

STRUCTURE

Developer Portfolio — Full Page Template

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- [meta, SEO, OG tags — see HTML section] -->
  <link rel="stylesheet" href="styles.css">
</head>
<body>

  <!-- Skip nav -->
  <a href="#main" class="skip-link">Skip to main content</a>

  <header role="banner">
    <nav aria-label="Primary navigation">
      <a href="/" aria-label="Home">YourName</a>
      <ul>
        <li><a href="#about">About</a></li>
        <li><a href="#projects">Projects</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
      <button aria-label="Toggle menu" aria-expanded="false">☰</button>
    </nav>
  </header>

  <main id="main">

    <section id="hero" aria-labelledby="hero-heading">
      <h1 id="hero-heading">Hi, I'm Your Name</h1>
      <p>Full-stack developer building [thing]</p>
      <a href="#projects" class="btn btn-primary">View Work</a>
    </section>

    <section id="about" aria-labelledby="about-heading">
      <h2 id="about-heading">About</h2>
      <p>Your bio...</p>
      <ul aria-label="Skills">
        <li>JavaScript</li>
      </ul>
    </section>

    <section id="projects" aria-labelledby="projects-heading">
      <h2 id="projects-heading">Projects</h2>
      <div class="project-grid">
        <article class="project-card">
          <figure>
            <img src="project.webp" alt="Project screenshot" loading="lazy">
          </figure>
          <h3>Project Name</h3>
          <p>Description...</p>
          <a href="#">View →</a>
        </article>
      </div>
    </section>

    <section id="contact" aria-labelledby="contact-heading">
      <h2 id="contact-heading">Contact</h2>
      <form method="post" action="">
        <!-- inputs -->
      </form>
    </section>

  </main>

  <footer>
    <p><small>© 2025 Your Name</small></p>
    <nav aria-label="Social links">
      <a href="https://github.com/you" rel="noopener" target="_blank">GitHub</a>
    </nav>
  </footer>

  <script src="main.js" defer></script>
</body>
</html>

Ecosystem & Tooling

TOOLS

Build & Dev Tools

ToolUse
ViteBuild tool (fastest)
ParcelZero-config bundler
esbuildJS bundler/minifier
PostCSSCSS transforms
AutoprefixerVendor prefixes auto
PrettierCode formatter
ESLintJS linter
StylelintCSS linter

CSS Libraries & Frameworks

ToolStyle
Tailwind CSSUtility-first
Open PropsCSS variables lib
PicoCSSClassless semantic
Sass / SCSSCSS preprocessor
CSS ModulesScoped CSS
StitchesCSS-in-JS

JS Utilities

LibraryPurpose
GSAPAnimation (best-in-class)
Motion OneLightweight animation
LenisSmooth scroll
Alpine.jsLightweight reactivity
ZodSchema validation
date-fnsDate manipulation
SwiperTouch sliders

Fonts & Icons

ResourceType
Google FontsFree webfonts
FontsourceSelf-host npm fonts
Variable Fontsfontvariations.com
LucideClean icon set
HeroiconsTailwind icons
PhosphorFlexible icon set
Tabler Icons1800+ free SVGs

Deployment

PlatformBest for
VercelStatic + serverless
NetlifyStatic + forms
Cloudflare PagesFastest CDN
GitHub PagesFree static hosting
Config: Add _headers file to Netlify/CF for caching + security headers.

Dev Checklist Before Ship

✅ Validate HTML (validator.w3.org)

✅ Run Lighthouse (Chrome DevTools)

✅ Test keyboard navigation

✅ Test in Firefox + Safari + Chrome

✅ Check mobile (375px, 390px, 414px)

✅ Add 404 page

✅ sitemap.xml + robots.txt

✅ OG image (1200×630px)

✅ favicon.ico + apple-touch-icon

✅ Test with screen reader

File structure tip: Keep your project as index.html / styles.css / main.js at root, with /assets/ for images and fonts. This makes it dead-simple to duplicate for new projects.