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

checkbox
radio

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

submit empty or with a broken email. the browser complains, not my code.

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.

a real <dialog>, esc closes it

the word important is highlighted, and hovering CSS shows a tooltip.

hello from the void

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

the div in question
data-role
data-is-active
homeprojectscheatsheets