Cheatsheet HTML
Linguagem de marcação para páginas web
HTML
Basic Structure
Complete HTML5 Document
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>My Page</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>Minimum required structure. <!DOCTYPE html> declares HTML5. lang="en" sets the language. <meta charset> guarantees correct accents. <meta viewport> makes the page responsive.
Body — Visible Content
<body>
<header>Top</header>
<main>
<h1>Main content</h1>
<p>Text visible to the user.</p>
</main>
<footer>Footer</footer>
</body>The <body> contains all visible content. Everything the user sees is here. Use semantic tags like <header>, <main> and <footer> to organize.
data-* Attributes
<li data-id="42" data-name="Anna"
data-active="true">
Item custom
</li>
<!-- JavaScript: -->
<!-- el.dataset.id → "42" -->
<!-- el.dataset.name → "Anna" -->data-* attributes store custom data in HTML. Access them via element.dataset.name in JavaScript. Useful for passing information without external APIs.
DOCTYPE
<!DOCTYPE html>
It must always be the first line of the file. It tells the browser the document is HTML5. Without it, the browser enters quirks mode (old compatibility mode).
Comments
<!-- Comment simple --> <!-- Comment multi-line --> <!-- [if IE]> Only no Internet Explorer <![endif] -->
Comments are ignored by the browser. Useful for documenting the code. Do not use them to "hide" content — it is visible in View Source. The format is <!-- text -->.
Global Attributes
<div id="app" class="box" style="color:red"
title="Tooltip" hidden tabindex="0"
contenteditable="true" draggable="true"
data-info="extra" lang="en" dir="ltr">
Editable e draggable
</div>Global attributes work on any tag. hidden hides, title shows a tooltip, tabindex sets tab order, contenteditable makes it editable, draggable allows dragging.
html Element and lang
<html lang="en"> <html lang="pt-BR"> <html lang="en">
The lang attribute sets the page language. Essential for SEO, screen readers and automatic translation. Use ISO 639-1 codes (pt, en, es).
Div and Span
<div class="container"> <p>Generic block (block-level)</p> </div> <span class="highlight">Inline generic</span>
<div> is a block container (takes the whole line). <span> is inline (only takes the content). Both have no meaning — use them with CSS and JavaScript.
HTML Entities
< = < > = > & = & " = " = space © = © ® = ® → = → ♥ = ♥ 😀 = 😀
Entities represent special characters. < and > for < and >. is a non-breaking space. Use numeric codes (😀) for emojis.
Head — Metadata
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta name="description" content="Page summary">
<title>Tab Title</title>
<link rel="stylesheet" href="style.css">
</head>The <head> contains invisible metadata. The <title> appears in the tab and on Google. The <link> imports CSS. Metadata does not appear on the page.
id and class Attributes
<div id="header" class="box highlight">
<p id="intro" class="text big">
Content
</p>
</div>id is unique on the page (1 element). class can repeat and an element can have several classes. Use id for anchors and JS; class for reusable CSS styles.
Text and Formatting
Headings h1 to h6
<h1>Main title (1 per page)</h1> <h2>Section subtitle</h2> <h3>Sub-section</h3> <h4>Detail</h4> <h5>Sub-detail</h5> <h6>Smallest title</h6>
Six hierarchical levels. Use only one <h1> per page. Do not skip levels (e.g. h2 → h4). The hierarchy is important for SEO and accessibility.
Superscript and Subscript
<p>E = mc<sup>2</sup></p> <p>H<sub>2</sub>O</p> <p>10<sup>3</sup> = 1000</p> <p>CO<sub>2</sub> is carbon dioxide</p>
<sup> raises the text (exponents, notes). <sub> lowers it (chemical formulas). Essential for mathematical and scientific notation.
Text Direction and Unicode
<p dir="rtl">Text from right to left</p> <p dir="ltr">Text normal (left→right)</p> <bdo dir="rtl">Text inverted</bdo> <!-- Direct Unicode: --> <p>© 2024 — Coffee ☕ → 🚀</p>
dir="rtl" reverses the text direction (Arabic, Hebrew). <bdo> forces the direction. For Unicode characters (emojis, symbols), just use UTF-8 in as <meta charset>.
Paragraph and Breaks
<p>First paragraph de text.</p> <p>Second paragraph.<br> Com break de line forced.</p> <hr> <p>New theme after line horizontal.</p>
<p> creates paragraphs with automatic spacing. <br> forces a line break without a new paragraph. <hr> inserts a horizontal thematic separation.
Code and Preformatted
<p>Use <code>console.log()</code> to debug.</p>
<pre><code>
function hello() {
return "Hello";
}
</code></pre>
<kbd>Ctrl</kbd> + <kbd>C</kbd> = copy
<samp>Program output</samp><code> formats inline code. <pre> preserves spaces and breaks. <kbd> represents keys. <samp> shows program output. Combine <pre><code> for blocks.
WBR and Hyphenation
<p> http://site.com/very/<wbr>long/<wbr>path </p> <p lang="de"> Straßen­bahn­haltestelle </p> <p style="hyphens: auto" lang="en"> Parallelepiped is uma word long </p>
<wbr> suggests a break point in long URLs. ­ is a soft hyphen (only appears if it breaks). hyphens: auto in CSS separates syllables automatically.
Bold, Italic and Emphasis
<strong>Important (bold semantic)</strong> <em>Emphasis (italic semantic)</em> <b>Bold visual (without semantics)</b> <i>Italic visual (technical term)</i>
<strong> indicates importance (bold). <em> indicates emphasis (italic). <b> and <i> are only visual. Prefer <strong>/<em> for accessibility.
Quotations
<blockquote cite="https://example.com"> <p>Long block quote.</p> </blockquote> <p>As said: <q>short inline quote</q>.</p> <cite>Title of the work</cite>
<blockquote> for long block quotations. <q> for short inline quotations (adds automatic quotes). <cite> references the work title. The cite attribute stores the source URL.
Modified Text
<del>Text removed</del> <ins>Inserted text</ins> <mark>Highlighted text</mark> <s>Incorrect text</s> <u>Underline (careful with links!)</u> <small>Text small</small>
<del> shows strikethrough text (removed). <ins> underlines (inserted). <mark> highlights with a yellow background. <small> reduces the size. Avoid <u> — it is confused with links.
Abbreviations and Definitions
<abbr title="HyperText Markup Language"> HTML </abbr> <dfn>HTML</dfn> is a markup language used for web pages. <address> Written by <a href="mailto:a@b.com">Anna</a> </address>
<abbr> shows the meaning in a tooltip. <dfn> marks the definition of a term. <address> contains the author's contact information. All of them improve semantics.
Lists
Unordered List
<ul> <li>HTML</li> <li>CSS</li> <li>JavaScript</li> </ul>
<ul> creates a list with bullets. Each item uses <li>. Ideal for items with no specific order. The bullet style changes with list-style-type in CSS.
Nested Lists
<ul>
<li>Frontend
<ul>
<li>HTML</li>
<li>CSS
<ul>
<li>Flexbox</li>
<li>Grid</li>
</ul>
</li>
</ul>
</li>
<li>Backend</li>
</ul>Sublists go inside the parent <li>. You can mix <ul> and <ol>. The visual indentation comes from CSS (margin-left per level).
Ordered List
<ol> <li>Open the file</li> <li>Edit the content</li> <li>Save</li> </ol> <ol start="5" reversed> <li>Fifth</li> <li>Second</li> </ol>
<ol> creates a numbered list. start="5" starts at 5. reversed reverses the count. Use it for sequential steps or rankings.
List with CSS (No Bullets)
<ul style="list-style: none; padding: 0;">
<li>→ Item with arrow</li>
<li>✓ Item with check</li>
<li>★ Item with star</li>
</ul>
<!-- Or with external CSS: -->
<!-- ul { list-style: none; } -->
<!-- li::before { content: "→ "; } -->list-style: none removes the bullets. Use ::before with content for custom bullets. Common pattern in navigation menus.
Numbering Type
<ol type="1"> <!-- 1, 2, 3 --> <ol type="A"> <!-- A, B, C --> <ol type="a"> <!-- a, b, c --> <ol type="I"> <!-- I, II, III --> <ol type="i"> <!-- i, ii, iii --> <li value="10">Salta to 10</li>
The type attribute sets the format: 1 (numbers), A/a (letters), I/i (Roman). value on an <li> resets the numbering from there.
Definition List
<dl> <dt>HTML</dt> <dd>Markup language</dd> <dt>CSS</dt> <dd>Style sheet</dd> <dt>JavaScript</dt> <dd>Programming language</dd> </dl>
<dl> creates a definition list. <dt> is the term. <dd> is the description. Ideal for glossaries, FAQs and key-value pairs.
Links and Navigation
Basic Link
<a href="https://example.com">Visit site</a> <a href="/about">Page interna</a> <a href="./file.pdf">File local</a>
The <a> creates hyperlinks. href sets the destination. Use absolute URLs (https://) for external sites and relative ones (/page) for internal pages.
File Download
<a href="report.pdf" download> Download PDF </a> <a href="data.csv" download="sales-2024.csv"> Download with custom name </a>
The download attribute forces the download instead of opening the file. You can specify an alternative name. It only works for URLs from the same domain (same-origin).
Open in New Tab
<a href="https://external.com" target="_blank" rel="noopener noreferrer"> Open in new tab </a>
target="_blank" opens in a new tab. Always add rel="noopener" for security (prevents access to window.opener). noreferrer also hides the referer.
Link the Button
<!-- Link com appearance de button --> <a href="/record" class="btn btn-primary" role="button"> Register </a> <!-- Button real (without navigation) --> <button type="button" class="btn"> Click here </button>
Use <a> for navigation and <button> for actions (JS). role="button" tells screen readers the link acts the a button. Do not use <div onclick> — it is not accessible.
Anchors (Internal Links)
<a href="#contacts">Go to contacts</a> <!-- Further down the page: --> <section id="contacts"> <h2>Contacts</h2> </section> <!-- Link from another page: --> <a href="/page.html#section">Section</a>
Links with #id jump to the element with that id. Works on the same page or another one (page.html#id). Use scroll-behavior: smooth in CSS to animate.
Rel noopener and nofollow
<a href="https://external.com" rel="noopener">Safe</a> <a href="https://spam.com" rel="nofollow">Sem endorsement SEO</a> <a href="https://patrocinado.com" rel="sponsored">Patrocinado</a> <a href="https://example.com" rel="noopener nofollow">Both</a>
rel="noopener" protects against attacks. nofollow tells Google not to follow the link (SEO). sponsored marks paid links. Combine values separated by spaces.
Email and Phone
<a href="mailto:ana@example.com"> Send email </a> <a href="mailto:a@b.com?subject=Hello&cc=x@y.com"> Email com assunto </a> <a href="tel:+351912345678"> Connect now </a>
mailto: opens the email client. It accepts ?subject=, &cc=, &body=. tel: opens the dialer on mobile. Use international format with +.
Breadcrumb
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li aria-current="page">Detail</li>
</ol>
</nav>Breadcrumbs show the location in the hierarchy. Use <nav> with aria-label. aria-current="page" marks the current page. Improves SEO and navigation.
Tables
Basic Table
<table>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</table><table> creates the table. <tr> is a row. <td> is a data cell. Tables are for tabular data — not for layout.
Table Footer
<table>
<thead>
<tr><th>Product</th><th>Price</th></tr>
</thead>
<tbody>
<tr><td>Item A</td><td>10€</td></tr>
<tr><td>Item B</td><td>20€</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>30€</td></tr>
</tfoot>
</table><tfoot> contains summary rows. The browser may repeat it in long printed tables. The order in HTML can be thead → tfoot → tbody (it renders at the end).
Header and Body
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>Anna</td>
<td>30</td>
</tr>
</tbody>
</table><thead> groups the header. <th> is a header cell (bold and centered). <tbody> contains the data. Improves accessibility and allows styling sections.
Grouping Columns (colgroup)
<table>
<colgroup>
<col style="background: #f0f0f0">
<col span="2" style="background: #e0e0e0">
</colgroup>
<tr>
<td>Col 1</td>
<td>Col 2</td>
<td>Col 3</td>
</tr>
</table><colgroup> and <col> style entire columns. span="2" applies to 2 columns. Useful for per-column zebra striping or highlighting specific columns.
Caption
<table>
<caption>Sales per quarter (2024)</caption>
<thead>
<tr>
<th>Quarter</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr><td>Q1</td><td>10k</td></tr>
</tbody>
</table><caption> gives the table a descriptive title. It must be the first child of <table>. Essential for accessibility — screen readers announce the caption.
Responsive Table
<div style="overflow-x: auto;">
<table>
<tr>
<td>Wide data...</td>
<td>That do not fit...</td>
<td>On mobile screen</td>
</tr>
</table>
</div>Wrap the table in a <div> with overflow-x: auto. On small screens, a horizontal scroll appears. Alternative: transform it into cards with CSS Grid on mobile.
Colspan and Rowspan
<table>
<tr>
<td colspan="2">Spans 2 columns</td>
</tr>
<tr>
<td rowspan="2">Spans 2 rows</td>
<td>Normal</td>
</tr>
<tr>
<td>Normal</td>
</tr>
</table>colspan="2" makes the cell span 2 columns. rowspan="2" spans 2 rows. Useful for grouped headers and summary cells.
Header Scope
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
</tr>
<tr>
<th scope="row">Anna</th>
<td>30</td>
</tr>
</table>scope="col" indicates that the <th> is the column header. scope="row" for the row. Essential for screen readers to associate data with the correct header.
Forms
Basic Form
<form action="/send" method="POST"> <label for="name">Name:</label> <input type="text" id="name" name="name"> <button type="submit">Send</button> </form>
action sets the data destination. method is GET (URL) or POST (body). name is required for the field to be submitted. <label> with for links to the input.
Checkbox and Radio
<label>
<input type="checkbox" name="aceito"
value="yes" checked>
I accept the terms
</label>
<label>
<input type="radio" name="color"
value="blue">
Blue
</label>
<label>
<input type="radio" name="color"
value="green" checked>
Green
</label>checkbox allows multiple selection. radio only allows one choice (same name). checked pre-marks. Wrap with <label> to click on the text too.
File Input and Multiple
<form enctype="multipart/form-data">
<input type="file" name="photo"
accept="image/*">
<input type="file" name="docs"
multiple
accept=".pdf,.doc,.docx">
</form>type="file" allows upload. accept filters file types. multiple allows several. The <form> needs enctype="multipart/form-data" for uploads.
Input Types
<input type="text"> <!-- text --> <input type="email"> <!-- email --> <input type="password"> <!-- password --> <input type="number"> <!-- number --> <input type="date"> <!-- date --> <input type="time"> <!-- time --> <input type="color"> <!-- color --> <input type="range"> <!-- slider --> <input type="file"> <!-- file --> <input type="url"> <!-- URL --> <input type="tel"> <!-- phone --> <input type="search"> <!-- search -->
The type defines the behavior and the keyboard on mobile. email validates the format, number shows a spinner, date opens a calendar. Use the correct type for better UX.
Native Validation
<input type="email" required>
<input type="text" minlength="3"
maxlength="50">
<input type="number" min="1" max="100"
step="0.5">
<input type="text"
pattern="[0-9]{9}"
title="9 digits">required makes it mandatory. minlength/maxlength limit the size. min/max limit values. pattern validates with regex. title shows a hint on error.
Autofocus, Placeholder and Readonly
<input type="text" autofocus
placeholder="Search...">
<input type="text" readonly
value="Not editable">
<input type="text" disabled
value="Desativado">
<input type="hidden" name="token"
value="abc123">autofocus focuses on load (1 per page). placeholder shows a hint. readonly prevents editing but submits. disabled prevents and does not submit. hidden is invisible.
Textarea
<label for="msg">Message:</label>
<textarea id="msg" name="message"
rows="5" cols="40"
placeholder="Write here..."
maxlength="500"></textarea><textarea> allows multi-line text. rows sets the initial height. maxlength limits characters. The initial content goes between the tags (do not use value).
Fieldset and Legend
<form>
<fieldset>
<legend>Personal Data</legend>
<label>Name: <input name="name"></label>
<label>Email: <input type="email"
name="email"></label>
</fieldset>
<fieldset disabled>
<legend>Blocked</legend>
<input type="text" value="Not editable">
</fieldset>
</form><fieldset> groups related fields. <legend> gives the group a title. disabled on the fieldset disables all fields inside. Improves organization and accessibility.
Select and Datalist
<select name="country">
<option value="">Choose...</option>
<option value="pt" selected>Portugal</option>
<option value="br">Brasil</option>
<optgroup label="Europe">
<option value="es">Spain</option>
</optgroup>
</select>
<input list="languages">
<datalist id="languages">
<option value="HTML">
<option value="CSS">
</datalist><select> creates a dropdown. <optgroup> groups options. selected pre-selects. <datalist> gives suggestions in a text input (native autocomplete).
Buttons
<button type="submit">Send</button> <button type="button" onclick="save()"> Save </button> <button type="reset">Clear</button> <button disabled>Unavailable</button>
type="submit" submits the form. type="button" does not submit (use with JS). type="reset" clears fields. disabled deactivates. Prefer <button> over <input type="submit">.
Semantic HTML
Header and Footer
<header> <h1>My Site</h1> <nav>...</nav> </header> <main>Content</main> <footer> <p>© 2024 My Site</p> </footer>
<header> is the top (logo, nav, title). <footer> is the bottom (copyright, links). Several can exist per page (inside <article>, <section>). They replace <div class="header">.
Aside — Side Content
<main>
<article>Main content</article>
<aside>
<h3>Related</h3>
<ul>
<li><a href="/post1">Post 1</a></li>
<li><a href="/post2">Post 2</a></li>
</ul>
</aside>
</main><aside> contains complementary content (sidebar, tips, advertising). It should be related to the main content. Do not use it for unrelated content.
Dialog (Native Modal)
<dialog id="modal">
<h2>Modal Title</h2>
<p>Dialog box content.</p>
<button onclick="this.closest('dialog')
.close()">Close</button>
</dialog>
<button onclick="document
.querySelector('#modal')
.showModal()">Open</button><dialog> creates native modals without JS. .showModal() opens with an overlay. .close() closes it. It supports ::backdrop in CSS to style the background. No external dependencies.
Nav — Navigation
<nav aria-label="Main">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav><nav> marks main navigation areas. Use aria-label if there are multiple <nav>. Not all links need to be in a <nav> — only the main ones.
Details and Summary
<details> <summary>Click to expand</summary> <p>Hidden content that appears when clicking the summary.</p> </details> <details open> <summary>Already open</summary> <p>Visible by default.</p> </details>
<details> creates a native accordion without JavaScript. <summary> is the clickable title. open shows it expanded by default. Ideal for FAQs and optional content.
Template and Slot
<template id="card-template">
<div class="card">
<h3 class="title"></h3>
<p class="text"></p>
</div>
</template>
<script>
const tpl = document
.querySelector('#card-template');
const clone = tpl.content.cloneNode(true);
clone.querySelector('.title')
.textContent = 'New';
document.body.appendChild(clone);
</script><template> stores inert HTML (does not render). Clone with .content.cloneNode(true) in JS. Ideal for dynamic lists and Web Components. The content only exists when cloned.
Main — Main Content
<body>
<header>...</header>
<nav>...</nav>
<main>
<h1>Title of the page</h1>
<p>Unique content of this page.</p>
</main>
<footer>...</footer>
</body><main> contains the unique content of the page. Only one can exist per page. Do not include header, nav or footer inside. It helps screen readers jump straight to the content.
Time and Date
<time datetime="2024-01-15">15 January</time> <time datetime="2024-01-15T14:30"> 15 Jan, 14:30 </time> <time datetime="PT2H30M">2h 30min</time>
<time> marks dates/times in a machine-readable way. The datetime attribute uses ISO format. It improves SEO and lets browsers add it to the calendar.
Article and Section
<article> <h2>Post: How to use HTML</h2> <time datetime="2024-01-15">15 Jan</time> <p>Independent content...</p> </article> <section> <h2>Comments</h2> <p>Thematic section of the page.</p> </section>
<article> is independent content (post, news, comment). <section> groups thematic content. Rule: if it makes sense on its own, use <article>.
Progress and Meter
<progress value="70" max="100">
70%
</progress>
<meter value="0.7" min="0" max="1"
low="0.3" high="0.8"
optimum="1">
70% complete
</meter><progress> shows the progress of a task. <meter> shows a value within a range (like a gauge). low/high/optimum define color zones.
Metadata and SEO
Title and Description
<head>
<title>My Site - Web Services</title>
<meta name="description"
content="We create modern and
responsive. Free quote.">
</head>The <title> appears in the tab and in Google results (max ~60 chars). The meta description is the summary in the results (max ~160 chars). Essential for SEO.
Favicon and Icons
<link rel="icon" href="/favicon.ico"
sizes="32x32">
<link rel="icon" href="/icon.svg"
type="image/svg+xml">
<link rel="apple-touch-icon"
href="/apple-icon.png">
<link rel="manifest"
href="/site.webmanifest">rel="icon" sets the tab favicon. apple-touch-icon for iOS (180x180px). manifest links to the PWA. Use SVG for a scalable favicon.
JSON-LD (Schema.org)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "My Company",
"url": "https://site.com",
"logo": "https://site.com/logo.png"
}
</script>JSON-LD is structured data for Google. It goes in a <script type="application/ld+json">. It enables rich snippets (stars, prices, FAQs) in search results.
Open Graph (Social Networks)
<meta property="og:title"
content="Title do Post">
<meta property="og:description"
content="Summary atractivo">
<meta property="og:image"
content="https://site.com/img.jpg">
<meta property="og:url"
content="https://site.com/post">
<meta property="og:type"
content="article">Open Graph controls the preview when sharing on Facebook, LinkedIn, WhatsApp. og:image should be 1200x630px. Without this, networks try to guess the content.
Linking CSS and JavaScript
<!-- CSS in the head -->
<link rel="stylesheet" href="style.css">
<!-- JS with defer (recommended) -->
<script src="app.js" defer></script>
<!-- JS with async -->
<script src="analytics.js" async></script>
<!-- ES6 module -->
<script type="module"
src="module.js"></script>CSS goes in the <head> with <link>. For JS use defer (runs after parsing, keeps order) or async (runs on load, no order). type="module" enables ES modules.
Twitter Card
<meta name="twitter:card"
content="summary_large_image">
<meta name="twitter:title"
content="Title do Post">
<meta name="twitter:description"
content="Summary do post">
<meta name="twitter:image"
content="https://site.com/img.jpg">Twitter Card controls the preview on X/Twitter. summary_large_image shows a large image. summary shows a small one. It complements Open Graph.
Preload and Prefetch
<!-- Preload: critical resource -->
<link rel="preload" href="fonte.woff2"
the="font" crossorigin>
<!-- Preconnect: early DNS -->
<link rel="preconnect"
href="https://fonts.googleapis.com">
<!-- Prefetch: next page -->
<link rel="prefetch" href="/proxima">
<!-- DNS prefetch -->
<link rel="dns-prefetch"
href="//cdn.example.com">preload loads critical resources ahead of time. preconnect anticipates DNS+TCP. prefetch loads next page resources when idle. They improve Core Web Vitals.
Canonical and Robots
<link rel="canonical"
href="https://site.com/page">
<meta name="robots"
content="index, follow">
<meta name="robots"
content="noindex, nofollow">canonical indicates the preferred URL (avoids duplicate content). robots controls indexing: index/noindex (appear on Google), follow/nofollow (follow links).
Essential Meta Tags
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width,
initial-scale=1.0">
<meta name="author" content="Anna">
<meta name="theme-color"
content="#E34F26">
<meta http-equiv="X-UA-Compatible"
content="IE=edge">charset and viewport are mandatory. theme-color sets the bar color on mobile. author identifies the author. X-UA-Compatible for IE compatibility.
Accessibility
Alt on Images
<img src="chart.png"
alt="Sales subiram 20% em 2024">
<!-- Decorative: empty alt -->
<img src="line.png" alt=""
role="presentation">alt describes the image for screen readers. Be specific and descriptive. For decorative images, use alt="" (empty) — the reader ignores it. Never omit the attribute.
Labels in Forms
<!-- Method 1: for/id -->
<label for="email">Email:</label>
<input id="email" type="email">
<!-- Method 2: wrapping -->
<label>
Name:
<input type="text" name="name">
</label>
<!-- No visible label -->
<input type="search"
aria-label="Search">Every input needs a label. for/id links explicitly. Wrapping the input in the <label> also works. Without a visible label, use aria-label. Never use only placeholder.
ARIA Labels
<button aria-label="Close menu">
✕
</button>
<nav aria-label="Navigation main">
...
</nav>
<input aria-label="Search no site"
type="search">aria-label gives an accessible name to elements without visible text. Use it on icon buttons, inputs without a visible label and navigations. Do not use it if suitable visible text already exists.
Skip Links and Landmarks
<a href="#content" class="skip-link"> Skip to content </a> <header>...</header> <nav>...</nav> <main id="content"> <h1>Main content</h1> </main>
Skip links let you skip the navigation (keyboard). Hide them with CSS but keep them accessible. <main>, <nav>, <header> are landmarks that readers use to navigate.
ARIA States and Properties
<button aria-expanded="false"
aria-controls="menu">
Menu
</button>
<div id="menu" hidden>
...
</div>
<div aria-live="polite">
Dynamic update
</div>
<span aria-hidden="true">★</span>aria-expanded indicates the open/closed state. aria-controls links to the controlled element. aria-live announces dynamic changes. aria-hidden hides decorative ones.
Contrast and Focus
<!-- Do not remove the outline! -->
<style>
a:focus-visible {
outline: 3px solid #E34F26;
outline-offset: 2px;
}
/* Minimum ratio: 4.5:1 */
.text {
color: #333; /* good contrast */
}
</style>Never use outline: none without an alternative. :focus-visible shows focus only for keyboard. Minimum contrast: 4.5:1 for normal text, 3:1 for large text. Test with contrast tools.
ARIA Roles
<div role="alert">
Error: field required!
</div>
<div role="tablist">
<button role="tab"
aria-selected="true">Tab 1</button>
<button role="tab">Tab 2</button>
</div>
<div role="tabpanel">Content</div>role defines the element's role. alert announces errors. tablist/tab/tabpanel create accessible tabs. Prefer semantic tags — use role only when necessary.
Accessible Tables
<table>
<caption>Sales 2024</caption>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">January</th>
<td>10.000€</td>
</tr>
</tbody>
</table>Use <caption> for the title. <th> with scope associates headers with cells. Never use tables for layout. Screen readers navigate by <th> and scope.
Tips and Modern
Loading JavaScript (defer/async)
<!-- Recommended: defer --> <script src="app.js" defer></script> <!-- Async: no guaranteed order --> <script src="analytics.js" async></script> <!-- Inline at the end of body --> <body> ... <script src="app.js"></script> </body>
defer loads in parallel and runs after parsing (keeps order). async runs the soon the it loads (no order). Without an attribute, it blocks parsing. Prefer defer for your own scripts.
Meta Refresh and Redirect
<!-- Redirect after 0s -->
<meta http-equiv="refresh"
content="0; url=https://new.com">
<!-- Refresh every 30s -->
<meta http-equiv="refresh"
content="30">http-equiv="refresh" redirects or reloads the page. content="0; url=..." redirects immediately. Prefer HTTP redirects (301/302) on the server for SEO.
Contenteditable
<div contenteditable="true">
Click to edit this text!
</div>
<p contenteditable="plaintext-only">
Only simple text
</p>
<!-- JS: get content -->
<script>
const el = document
.querySelector('[contenteditable]');
el.addEventListener('input', () => {
console.log(el.innerHTML);
});
</script>contenteditable="true" makes any element editable. plaintext-only prevents formatting. The input event detects changes. The basis of rich-text editors.
Web Components (Basic)
<template id="tpl">
<style>
.card { border: 1px solid #ccc; }
</style>
<div class="card">
<slot></slot>
</div>
</template>
<script>
class MyCard
extends HTMLElement {
connectedCallback() {
const tpl = document
.querySelector('#tpl');
this.attachShadow({ mode: 'open' })
.append(
tpl.content.cloneNode(true));
}
}
customElements
.define('my-card', MyCard);
</script>
<my-card>Content</my-card>Web Components create custom elements. customElements.define() registers them. Shadow DOM isolates styles. <slot> receives content. <template> stores the HTML.
Output and Result
<form oninput="result.value =
parseInt(a.value) + parseInt(b.value)">
<input type="number" id="a" value="5"> +
<input type="number" id="b" value="3"> =
<output name="result"
for="a b">8</output>
</form><output> shows the result of a calculation. for links to the related inputs. oninput recalculates in real time. Semantic for form results.
Useful Global Attributes
<div hidden>Hidden</div>
<div inert>
<button>Not clickable</button>
</div>
<p spellcheck="true">Editable</p>
<div translate="no">
Do not translate: code
</div>
<input inputmode="numeric"
pattern="[0-9]*">hidden hides (without CSS). inert disables interaction and focus. spellcheck enables spell checking. translate="no" prevents translation. inputmode sets the mobile keyboard.
Details the FAQ
<h2>Frequently Asked Questions</h2> <details> <summary>What is HTML?</summary> <p>Markup language for structuring web pages.</p> </details> <details> <summary>Is it a programming language?</summary> <p>No, it is markup.</p> </details>
<details>/<summary> create FAQs without JavaScript. Each question is a <summary>, the answer goes inside the <details>. Native, accessible and dependency-free.
Validate HTML (W3C)
<!-- Validation tools: --> https://validator.w3.org <!-- VS Code: --> <!-- Extension: HTMLHint --> <!-- Common errors: --> <!-- ✗ <div><p>Text</div></p> --> <!-- ✓ <div><p>Text</p></div> --> <!-- ✗ <img src="x.jpg"> --> <!-- ✓ <img src="x.jpg" alt="..."> -->
Validate at validator.w3.org. Common errors: badly closed tags, <img> without alt, <div> inside <p>, duplicate IDs. Valid HTML improves SEO and accessibility.
Images and Media
Basic Image
<img src="photo.jpg"
alt="Dog running in the park"
width="400"
height="300"><img> is self-closing (no closing tag). alt is required for accessibility and SEO. Set width/height to avoid layout shifts.
Lazy Loading
<img src="photo.jpg" alt="..." loading="lazy">
<img src="hero.jpg" alt="..." loading="eager">
<!-- iframe also supports: -->
<iframe src="map.html"
loading="lazy"></iframe>loading="lazy" only loads the image when it is about to appear in the viewport. loading="eager" loads immediately (default). Ideal for images below the fold.
Responsive Image (srcset)
<img src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, 800px"
alt="Landscape">srcset offers multiple resolutions. sizes tells the browser the display size. The browser picks the best image. Reduces data on small screens.
Figure with Caption
<figure>
<img src="chart.png"
alt="Sales 2024">
<figcaption>
Fig. 1 — Sales per quarter
</figcaption>
</figure><figure> groups visual content with its caption. <figcaption> is the description. It can contain images, charts, code or quotations.
Picture — Art Direction
<picture>
<source media="(max-width: 600px)"
srcset="mobile.jpg">
<source media="(max-width: 1024px)"
srcset="tablet.jpg">
<img src="desktop.jpg" alt="Product">
</picture><picture> serves different images depending on the screen (art direction). The <source> sets conditions with average. The <img> is the required fallback.
Inline SVG
<svg width="100" height="100"
viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40"
fill="#E34F26"/>
<text x="50" y="55"
text-anchor="middle"
fill="white">HTML</text>
</svg>Inline <svg> allows scalable vector graphics. viewBox sets the coordinate system. Advantage: stylable with CSS and animatable with JS. No quality loss.
Modern Formats (WebP/AVIF)
<picture> <source srcset="photo.avif" type="image/avif"> <source srcset="photo.webp" type="image/webp"> <img src="photo.jpg" alt="Photo"> </picture>
AVIF and WebP are lighter than JPEG/PNG. Use <picture> with type for fallback. The browser uses the first supported format. Reduces size by 30-50%.
Image Map
<img src="map.png" alt="Map"
usemap="#menu">
<map name="menu">
<area shape="rect"
coords="0,0,100,50"
href="/pagina1" alt="Page 1">
<area shape="circle"
coords="200,75,50"
href="/pagina2" alt="Page 2">
</map><map> defines clickable areas on an image. usemap links the image to the map. shape can be rect, circle or poly. Rarely used today — prefer SVG.
Multimedia and Embed
HTML5 Video
<video controls width="640"
poster="cover.jpg">
<source src="video.mp4"
type="video/mp4">
<source src="video.webm"
type="video/webm">
<track src="subtitles.vtt"
kind="subtitles"
srclang="en" label="PT">
Your browser does not support video.
</video><video> plays native video. controls shows the buttons. poster is the cover image. <source> offers formats. <track> adds subtitles (.vtt).
Embed and Object
<!-- PDF -->
<embed src="doc.pdf"
type="application/pdf"
width="100%" height="500">
<!-- Fallback with object -->
<object data="doc.pdf"
type="application/pdf"
width="100%" height="500">
<p>PDF not supported.
<a href="doc.pdf">Download</a>
</p>
</object><embed> embeds external content (PDF, SVG). <object> allows a fallback (content between the tags). Prefer <iframe> for pages and <img> for SVG.
HTML5 Audio
<audio controls>
<source src="musica.mp3"
type="audio/mpeg">
<source src="musica.ogg"
type="audio/ogg">
Your browser does not support audio.
</audio>
<!-- Autoplay with mute -->
<audio autoplay muted loop>
<source src="background.mp3">
</audio><audio> plays native audio. controls shows the player. autoplay only works with muted (browser policy). loop repeats. The inner text is a fallback.
Picture-in-Picture
<video id="video" controls
src="video.mp4"></video>
<button onclick="togglePiP()">
Picture-in-Picture
</button>
<script>
async function togglePiP() {
const v = document
.querySelector('#video');
if (document.pictureInPictureElement) {
await document
.exitPictureInPicture();
} else {
await v.requestPictureInPicture();
}
}
</script>requestPictureInPicture() activates PiP mode (floating video). exitPictureInPicture() deactivates it. The user can keep watching the video while browsing another page.
Iframe
<iframe src="https://maps.google.com/..."
width="600" height="400"
title="Map da location"
loading="lazy"
sandbox="allow-scripts"
allowfullscreen>
</iframe><iframe> embeds another page. title is mandatory for accessibility. loading="lazy" defers loading. sandbox restricts permissions. allowfullscreen allows full screen.
Canvas (Basic)
<canvas id="canvas"
width="400" height="200">
Canvas not supported.
</canvas>
<script>
const ctx = document
.querySelector('#canvas')
.getContext('2d');
ctx.fillStyle = '#E34F26';
ctx.fillRect(10, 10, 150, 100);
ctx.font = '20px Arial';
ctx.fillText('HTML5', 50, 70);
</script><canvas> creates a drawing area via JavaScript. getContext("2d") gives access to the drawing API. Use it for graphics, games and image manipulation. It requires JS to render.
YouTube and Vimeo Embed
<!-- YouTube -->
<iframe
src="https://www.youtube.com/embed/ID"
title="Title do video"
allow="accelerometer; autoplay;
clipboard-write; encrypted-media;
gyroscope; picture-in-picture"
allowfullscreen
loading="lazy">
</iframe>Use YouTube's /embed/ID URL. allow sets permissions. title describes the video. loading="lazy" improves performance. Add aspect-ratio: 16/9 in CSS for responsive.