cheatsheets
things i keep forgetting. saved here so i stop opening 47 tabs.
use freely. judge silently.
the skeleton
memorize it. burn it into your brain. tattoo it somewhere.
<!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="..." />
<title>Naca's Portfolio</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<script src="script.js"></script>
</body>
</html> input types
yes, there are way more than just type="text"
<input type="text" />
<input type="email" />
<input type="password" />
<input type="number" min="0" max="100" step="1" />
<input type="date" />
<input type="time" />
<input type="file" accept=".jpg,.png" multiple />
<input type="range" min="0" max="10" />
<input type="color" />
<input type="checkbox" />
<input type="radio" name="group" value="a" />
<input type="hidden" name="token" value="secret" />
<input type="search" />
<input type="tel" pattern="[0-9]{3}-[0-9]{4}" />
<input type="url" /> try it
forms (everyone hates them)
but they pay the bills, so here we are
<form action="/submit" method="POST">
<label for="name">Name</label>
<input type="text" id="name" name="name" placeholder="..." required />
<label for="email">Email</label>
<input type="email" id="email" name="email" autocomplete="email" />
<label for="msg">Message</label>
<textarea id="msg" name="msg" rows="4" maxlength="500"></textarea>
<label for="role">Role</label>
<select id="role" name="role">
<option value="">-- pick one --</option>
<option value="dev">Developer</option>
<option value="design">Designer</option>
</select>
<input type="checkbox" id="agree" name="agree" required />
<label for="agree">I agree to whatever this is</label>
<button type="submit">Send it</button>
<button type="reset">Never mind</button>
</form> try it
semantic html
divs are for layout. these are for meaning. use them and seo improves for free.
<!-- use these instead of divs. screen readers and seo notice -->
<body>
<header>site-wide top: logo, nav, search</header>
<nav>
<a href="/">home</a>
<a href="/about">about</a>
</nav>
<main>
<!-- one per page. the primary content -->
<article>
<!-- self-contained. blog post, card, comment -->
</article>
<section>
<!-- thematic grouping. usually has a heading -->
</section>
<aside>
<!-- tangentially related. sidebar, callout, ad -->
</aside>
</main>
<footer>site-wide bottom: links, copyright</footer>
</body> head elements
the stuff you google every time. og tags, favicon, theme color, canonical, preconnect.
<head>
<!-- basics, already in the skeleton -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="page description here" />
<title>Page Title</title>
<!-- favicon -->
<link rel="icon" href="/favicon.ico" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<!-- open graph. controls how links look when shared -->
<meta property="og:title" content="Page Title" />
<meta property="og:description" content="page description" />
<meta property="og:image" content="https://yoursite.com/og.png" />
<meta property="og:url" content="https://yoursite.com/page" />
<meta property="og:type" content="website" />
<!-- twitter/x card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Page Title" />
<meta name="twitter:image" content="https://yoursite.com/og.png" />
<!-- theme color. browser chrome on mobile -->
<meta name="theme-color" content="#111111" />
<!-- preconnect. start connection early for external origins -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.yoursite.com" />
<!-- canonical. the "real" url for this page -->
<link rel="canonical" href="https://yoursite.com/page" />
</head> tags you always forget exist
details, dialog, figure, mark, progress, template. all real, all useful, all underused.
<!-- toggle open/close without a single line of JS -->
<details>
<summary>click to expand</summary>
<p>surprise, hidden content</p>
</details>
<!-- native modal dialog -->
<dialog id="modal">
<p>hello from the void</p>
<button onclick="this.closest('dialog').close()">close</button>
</dialog>
<button onclick="document.getElementById('modal').showModal()">
open modal
</button>
<!-- image with caption -->
<figure>
<img src="cat.jpg" alt="a cat" />
<figcaption>she broke the build again</figcaption>
</figure>
<!-- inline highlight -->
<p>the word <mark>important</mark> is now yellow</p>
<!-- abbreviation with tooltip on hover -->
<abbr title="Cascading Style Sheets">CSS</abbr>
<!-- native progress bar -->
<progress value="70" max="100"></progress>
<!-- template: invisible to browser, cloned by js -->
<template id="card-tpl">
<div class="card">
<h3 class="card-title"></h3>
<p class="card-body"></p>
</div>
</template>
const tpl = document.getElementById('card-tpl');
const clone = tpl.content.cloneNode(true);
clone.querySelector('.card-title').textContent = 'hello';
document.body.appendChild(clone); try it
click to expand
surprise, hidden content. zero javascript involved.
the word important is highlighted, and hovering CSS shows a tooltip.
data attributes
custom data that lives in the html and travels to js. surprisingly elegant.
<!-- set in html -->
<div data-user-id="42" data-role="admin" data-is-active="true">
...
</div>
<!-- read in js -->
const el = document.querySelector('[data-role="admin"]');
el.dataset.userId; // "42" ← always a string
el.dataset.role; // "admin"
el.dataset.isActive; // "true" ← camelCase from kebab-case
// select by data attribute
document.querySelector('[data-user-id="42"]');
<!-- write in js -->
el.dataset.status = "verified";
el.dataset.userId = "99";
<!-- style in css -->
[data-role="admin"] { border: 1px solid gold; }
[data-is-active="true"] { opacity: 1; } try it