Core Features and Capabilities

Category: html

An overview of core features and capabilities in HTML.

Basic Structure of an HTML Document

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Document Title</title>
</head>
<body>
  <h1>Hello World</h1>
</body>
</html>

Key Elements:

  • <!DOCTYPE html> – Declares standards‑mode HTML5
  • <html> – Root element (always include lang attribute)
  • <head> – Metadata, links, scripts
  • <body> – Visible content

HTML Elements & Tags

Elements: An element consists of an opening tag, optional content, and a closing tag:

<p>This is a paragraph.</p>

Void (Self‑Closing) Elements: Void elements do not have closing tags. These elements can be written without the / at the end in modern HTML5.

<img src="image.jpg" alt="Description" />
<input type="text" />
<br />
<hr />
<meta />
<link />
<area />
<base />
<col />
<embed />
<source />
<track />
<wbr />

Attributes

Attributes provide additional meaning or behavior for elements.

Common Global Attributes:

Identification & Styling:

  • id – Unique identifier
  • class – Space-separated class names
  • style – Inline styles (avoid for maintainability)

Accessibility:

  • role – ARIA role
  • aria-* – ARIA attributes
  • tabindex – Tab order control (1, 0, positive integers)
  • title – Advisory tooltip text

Interaction:

  • contenteditable – Editable content ("true", "false", "plaintext-only"). It enables inline editing and its practical use case is user-generated content.
  • draggable – Drag and drop ("true", "false")
  • hidden – Hides element (use instead of CSS display: none for semantic hiding)
    • hidden="until-found" allows “Find in Page” to search inside hidden content (like accordions) and expand them automatically. MDN
  • inert – Disables interactions and removes from accessibility tree (modern, powerful attribute)

Internationalization:

  • lang – Language code (e.g., "en", "es", "fr")
  • dir – Text direction ("ltr", "rtl", "auto")
  • translate – Translation hint ("yes", "no"). Hints to translation tools (e.g., set to no for brand names).

Data & Behavior:

  • data-* – Custom data attributes
  • spellcheck – Spell checking ("true", "false")
  • autocapitalize – Auto-capitalization ("off", "none", "on", "sentences", "words", "characters") MDN

Interactive Attributes:

These attributes are part of custom web components and check browser support before using.

  • popover – Declares popover element ("auto", "manual")
  • popovertarget – Associates button with popover (by ID)
  • popovertargetaction – Popover action ("toggle", "show", "hide")
<a href="https://example.com" target="_blank" rel="noopener">Visit</a>
<div data-user-id="42" data-role="admin"></div>
<button popovertarget="menu-popover">Open Menu</button>
<div id="menu-popover" popover>Menu content</div>
<div inert>This section is completely disabled</div>

Metadata Elements

The <head> contains critical metadata for browsers, search engines, and social platforms.

<head>
  <!-- Character encoding (must be first) -->
  <meta charset="UTF-8" />

  <!-- Viewport for responsive design -->
  <meta name="viewport" content="width=device-width, initial-scale=1" />

  <!-- Page title (crucial for SEO) -->
  <title>Page Title - Site Name</title>

  <!-- Description for search engines -->
  <meta name="description" content="Page description for SEO" />

  <!-- Author -->
  <meta name="author" content="Author Name" />

  <!-- Keywords (largely deprecated for SEO) -->
  <meta name="keywords" content="html, tutorial, web" />

  <!-- Robots directives -->
  <meta name="robots" content="index, follow" />

  <!-- Theme color for browser UI -->
  <meta name="theme-color" content="#4285f4" />

  <!-- Open Graph for social sharing -->
  <meta property="og:title" content="Page Title" />
  <meta property="og:description" content="Description" />
  <meta property="og:image" content="https://example.com/image.jpg" />
  <meta property="og:url" content="https://example.com/page" />
  <meta property="og:type" content="website" />

  <!-- Twitter Card -->
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:title" content="Page Title" />
  <meta name="twitter:description" content="Description" />
  <meta name="twitter:image" content="https://example.com/image.jpg" />

  <!-- Favicon -->
  <link rel="icon" type="image/png" href="/favicon.png" />
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" />

  <!-- Canonical URL -->
  <link rel="canonical" href="https://example.com/page" />

  <!-- Preconnect for performance -->
  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link rel="dns-prefetch" href="https://api.example.com" />

  <!-- Stylesheet -->
  <link rel="stylesheet" href="styles.css" />

  <!-- Module preload -->
  <link rel="modulepreload" href="app.js" />
</head>

Less Common but Important Meta Tags

<!-- Referrer policy -->
<meta name="referrer" content="strict-origin-when-cross-origin" />

<!-- Color scheme preference -->
<meta name="color-scheme" content="light dark" />

<!-- Disable automatic detection -->
<meta name="format-detection" content="telephone=no" />

<!-- App manifest for PWAs -->
<link rel="manifest" href="/manifest.json" />

Semantic HTML (Core Concept)

Semantic HTML communicates meaning, not appearance. Using correct landmarks allows screen readers to navigate efficiently and improves SEO.

<!-- Non-semantic -->
<div class="header">Header</div>

<!-- Semantic -->
<header>Header</header>

Document Structure Elements

ElementDescription
<header>Introductory content, logos, navigation.
<nav>Major block of navigation links.
<main>The dominant content of the <body>. (Use only once per page).
<article>Self-contained composition (blog post, news item) distributable independently.
<section>Thematic grouping of content, usually with a heading.
<aside>Content tangentially related (sidebar, callouts, ads).
<footer>Copyright, contact info, sitemap.
<search>(New) Represents a section used to filter or search content. MDN
<hgroup>(Restored) Groups a heading with a subtitle/tagline. MDN
<!DOCTYPE html>
<html lang="en">
<body>
  <header>
    <nav>
      <!-- Site navigation -->
    </nav>
  </header>

  <main>
    <article>
      <header>
        <h1>Article Title</h1>
        <p>Published on <time datetime="2025-01-15">January 15, 2025</time></p>
      </header>

      <section>
        <h2>Section Heading</h2>
        <p>Content...</p>
      </section>

      <aside>
        <!-- Related content -->
      </aside>

      <footer>
        <!-- Article footer -->
      </footer>
    </article>
  </main>

  <aside>
    <!-- Sidebar -->
  </aside>

  <footer>
    <!-- Site footer -->
  </footer>
</body>
</html>

Benefits:

  • Accessibility – Screen readers navigate by landmarks
  • SEO – Search engines understand content structure
  • Maintainability – Clear document hierarchy
  • Default styling – Browsers provide sensible defaults

Modern & Underused Semantic Elements

Interactive Disclosure Widgets

<!-- Native accordion/disclosure -->
<details>
  <summary>Click to expand</summary>
  <p>Hidden content revealed on interaction.</p>
</details>

<!-- Open by default -->
<details open>
  <summary>Already expanded</summary>
  <p>This content is visible initially.</p>
</details>

Native Modal Dialog

<dialog id="modal">
  <form method="dialog">
    <h2>Dialog Title</h2>
    <p>Dialog content</p>
    <button>Close</button>
  </form>
</dialog>

<script>
  const dialog = document.getElementById('modal');
  // dialog.showModal(); // Modal with backdrop
  // dialog.show(); // Non-modal
  // dialog.close(); // Close dialog
</script>

Media with Caption

<figure>
  <img src="chart.png" alt="Sales data visualization" />
  <figcaption>
    Figure 1: Sales increased 45% in Q4 2024
  </figcaption>
</figure>

<!-- Also works with code, quotes, etc. -->
<figure>
  <pre><code>const x = 42;</code></pre>
  <figcaption>Listing 1: Variable declaration</figcaption>
</figure>

Date and Time

<!-- Machine-readable dates -->
<time datetime="2025-01-15">January 15, 2025</time>
<time datetime="2025-01-15T14:30:00Z">2:30 PM UTC</time>
<time datetime="PT2H30M">2 hours 30 minutes</time>

<!-- With publication date -->
<article>
  <h1>Article Title</h1>
  <p>Published <time datetime="2025-01-15" pubdate>Jan 15</time></p>
</article>

Data with Machine-Readable Value

The <data> element is useful for associating human-readable content with machine-readable values. This could be used more widely for things like product prices or geographic data.

<!-- Associate human-readable with machine-readable -->
<data value="42">Forty-two</data>
<data value="USD">US Dollars</data>
<data value="398">Product SKU 398</data>

Measurements and Progress

<meter> and <progress> are important for displaying measurements and task completion.

<!-- Scalar measurement within a range -->
<meter value="0.7" min="0" max="1" low="0.3" high="0.8" optimum="0.9">
  70%
</meter>

<!-- Task completion -->
<progress value="70" max="100">70%</progress>

<!-- Indeterminate progress -->
<progress>Loading...</progress>

Bidirectional Text Isolation

<!-- Isolate text with different direction -->
<p>User <bdi>إيان</bdi> has 50 points.</p>
<!-- Prevents RTL text from affecting surrounding LTR layout -->

Ruby Annotations (East Asian Typography)

<!-- Pronunciation guide for CJK characters -->
<ruby>
  漢 <rp>(</rp><rt>Kan</rt><rp>)</rp>
  字 <rp>(</rp><rt>ji</rt><rp>)</rp>
</ruby>

Word Break Opportunity

<!-- Suggest line break locations in long words/URLs -->
<p>
  https://example.com/<wbr>very-long-path/<wbr>document.html
</p>

Text Content Elements

TagMeaningUse Case
<strong>Strong importanceWarnings, serious notes. (Bold by default)
<em>Stress emphasisChanging the meaning of a sentence. (Italic by default)
<b>Stylistic offsetKeywords, product names. No importance implied.
<i>Alternate voiceTechnical terms, thoughts, taxonomic names.
<mark>RelevanceHighlighting text relevant to a user’s search.
<time>Machine-readable time<time datetime="2023-10-12">Oct 12</time>
<abbr>Abbreviation<abbr title="HyperText Markup Language">HTML</abbr>
<!-- Headings -->
<h1>Main Heading</h1>
<h2>Subheading</h2>
<h3>Sub-subheading</h3>
<!-- ... h4, h5, h6 -->

<!-- Paragraphs and inline elements -->
<p>Paragraph text with <span>inline container</span></p>

<!-- Emphasis and importance -->
<em>Emphasis (usually italic)</em>
<strong>Strong importance (usually bold)</strong>
<mark>Highlighted/marked text</mark>
<small>Fine print or side comments</small>
<s>Strikethrough (no longer accurate)</s>
<u>Underline (avoid, use CSS)</u>

<!-- Code and technical -->
<code>inline code</code>
<pre>Preformatted text block</pre>
<kbd>Keyboard input</kbd>
<samp>Sample output</samp>
<var>Variables</var>

<!-- Quotations -->
<q>Short inline quote</q>
<blockquote cite="https://source.com">
  <p>Long quotation block</p>
</blockquote>
<cite>Citation of creative work</cite>

<!-- Definitions -->
<dfn>Term being defined</dfn>
<abbr title="HyperText Markup Language">HTML</abbr>

<!-- Edits -->
<ins datetime="2025-01-15">Inserted text</ins>
<del datetime="2025-01-14">Deleted text</del>

<!-- Subscript and superscript -->
H<sub>2</sub>O
E = mc<sup>2</sup>

Headings Best Practices

  • Use logical order (h1h6)
  • Don’t skip levels (e.g., h1h3)
  • Usually one <h1> per page (debated, but common)
  • Use for structure, not styling
  • Ensure meaningful hierarchy for screen readers

Lists

<!-- Unordered list -->
<ul>
  <li>First item</li>
  <li>Second item
    <ul>
      <li>Nested item</li>
    </ul>
  </li>
</ul>

<!-- Ordered list -->
<ol>
  <li>First step</li>
  <li>Second step</li>
</ol>

<!-- Ordered with specific numbering -->
<ol start="5" type="A">
  <li>Fifth item, labeled "E"</li>
  <li>Sixth item, labeled "F"</li>
</ol>

<!-- Reversed ordering -->
<ol reversed>
  <li>Third</li>
  <li>Second</li>
  <li>First</li>
</ol>

<!-- Description list -->
<dl>
  <dt>HTML</dt>
  <dd>Markup language for web content</dd>

  <dt>CSS</dt>
  <dd>Stylesheet language for presentation</dd>

  <dt>JavaScript</dt>
  <dd>Programming language for interactivity</dd>
  <dd>Also known as ECMAScript</dd>
</dl>

<!-- Basic link -->
<a href="/about">About</a>

<!-- External link (security best practice) -->
<a href="https://external.com" target="_blank" rel="noopener noreferrer">
  External Site
</a>

<!-- Download link -->
<a href="/document.pdf" download="filename.pdf">Download PDF</a>

<!-- Email link -->
<a href="mailto:email@example.com?subject=Hello&body=Message">Email Us</a>

<!-- Telephone link -->
<a href="tel:+1234567890">Call Us</a>

<!-- Fragment (anchor) link -->
<a href="#section-2">Jump to Section 2</a>

<!-- Ping attribute for analytics -->
<a href="/product" ping="/analytics">Product</a>

<!-- Link to alternate representation -->
<a href="/feed" type="application/rss+xml">RSS Feed</a>

Link Relationship Attributes

<!-- Common rel values -->
<a href="/next" rel="next">Next Page</a>
<a href="/prev" rel="prev">Previous Page</a>
<a href="https://author.com" rel="author">Author's Site</a>
<a href="/license" rel="license">License</a>
<a href="https://example.com" rel="nofollow">Nofollow Link</a>
<a href="https://example.com" rel="sponsored">Sponsored</a>
<a href="https://example.com" rel="ugc">User Generated Content</a>

Navigation Best Practices

<nav aria-label="Primary navigation">
  <ul>
    <li><a href="/" aria-current="page">Home</a></li>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

<!-- Secondary navigation -->
<nav aria-label="Footer navigation">
  <ul>
    <li><a href="/privacy">Privacy</a></li>
    <li><a href="/terms">Terms</a></li>
  </ul>
</nav>

Images & Responsive Images

Basic Image:

<img
  src="image.jpg"
  alt="Descriptive text for accessibility"
  width="800"
  height="600"
  loading="lazy"
  decoding="async"
  fetchpriority="high"
/>

Responsive Images with srcset

The sizes attribute is mandatory when using srcset for width descriptors.

<!-- Pixel density descriptors -->
<img
  src="image.jpg"
  srcset="image.jpg 1x, image@2x.jpg 2x, image@3x.jpg 3x"
  alt="Description"
/>

<!-- Width descriptors with sizes -->
<img
  src="image-800.jpg"
  srcset="
    image-400.jpg 400w,
    image-800.jpg 800w,
    image-1200.jpg 1200w,
    image-1600.jpg 1600w
  "
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
  alt="Description"
/>

Picture Element (Art Direction):

<picture>
  <!-- Different images for different conditions -->
  <source
    media="(max-width: 600px)"
    srcset="mobile.jpg"
  />
  <source
    media="(max-width: 1200px)"
    srcset="tablet.jpg"
  />
  <source
    srcset="desktop.jpg"
  />
  <img src="fallback.jpg" alt="Description" />
</picture>

<!-- Modern image formats with fallback -->
<picture>
  <source type="image/avif" srcset="image.avif" />
  <source type="image/webp" srcset="image.webp" />
  <img src="image.jpg" alt="Description" />
</picture>

Image Attributes:

  • loading="lazy" – Lazy load images (native browser feature)
  • loading="eager" – Load immediately (default)
  • decoding="async" – Decode off main thread
  • decoding="sync" – Decode synchronously
  • fetchpriority="high" – Prioritize loading (for LCP images)
  • fetchpriority="low" – Deprioritize loading

Audio & Video

Video Element

<video
  controls
  width="640"
  height="360"
  poster="thumbnail.jpg"
  preload="metadata"
  playsinline
>
  <source src="video.mp4" type="video/mp4" />
  <source src="video.webm" type="video/webm" />
  <track
    kind="subtitles"
    src="subtitles-en.vtt"
    srclang="en"
    label="English"
    default
  />
  <track
    kind="captions"
    src="captions-en.vtt"
    srclang="en"
    label="English"
  />
  <track
    kind="descriptions"
    src="descriptions-en.vtt"
    srclang="en"
    label="English"
  />
  <p>Your browser doesn't support video. <a href="video.mp4">Download</a></p>
</video>

Audio Element

<audio controls preload="none">
  <source src="audio.mp3" type="audio/mpeg" />
  <source src="audio.ogg" type="audio/ogg" />
  <p>Your browser doesn't support audio.</p>
</audio>

Media Attributes:

  • controls – Show playback controls
  • autoplay – Auto-play (avoid, accessibility concern)
  • loop – Repeat playback
  • muted – Start muted
  • preload"none", "metadata", "auto"
  • playsinline – Play inline on iOS (not fullscreen)
  • poster – Thumbnail image (video only)

Track Element (Captions/Subtitles):

  • kind"subtitles", "captions", "descriptions", "chapters", "metadata"
  • srclang – Language code
  • label – User-visible label
  • default – Default track

Tables

<table>
  <caption>Q4 2024 Sales Data</caption>
  <thead>
    <tr>
      <th scope="col">Product</th>
      <th scope="col">Units Sold</th>
      <th scope="col">Revenue</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Widget A</th>
      <td>1,234</td>
      <td>$12,340</td>
    </tr>
    <tr>
      <th scope="row">Widget B</th>
      <td>5,678</td>
      <td>$56,780</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th scope="row">Total</th>
      <td>6,912</td>
      <td>$69,120</td>
    </tr>
  </tfoot>
</table>

Complex Tables

<table>
  <caption>Complex data with row and column groups</caption>
  <colgroup>
    <col />
    <col span="2" class="highlight" />
  </colgroup>
  <thead>
    <tr>
      <th rowspan="2" scope="col">Name</th>
      <th colspan="2" scope="colgroup">Scores</th>
    </tr>
    <tr>
      <th scope="col">Math</th>
      <th scope="col">Science</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Alice</th>
      <td>95</td>
      <td>88</td>
    </tr>
  </tbody>
</table>

Table Best Practices

  • Always use <caption> for accessibility
  • Use <th> with scope attribute ("row", "col", "rowgroup", "colgroup")
  • Use <thead>, <tbody>, <tfoot> for structure
  • Avoid tables for layout (use CSS Grid/Flexbox)
  • Consider responsive strategies (overflow-x, stacked layouts)

Forms & Input Elements

Basic Form Structure

<form action="/submit" method="post" novalidate>
  <fieldset>
    <legend>Personal Information</legend>

    <label for="name">Full Name</label>
    <input
      type="text"
      id="name"
      name="name"
      required
      autocomplete="name"
      aria-describedby="name-hint"
    />
    <span id="name-hint">Enter your legal name</span>

    <label for="email">Email</label>
    <input
      type="email"
      id="email"
      name="email"
      required
      autocomplete="email"
    />
  </fieldset>

  <button type="submit">Submit</button>
  <button type="reset">Reset</button>
</form>

Modern Input Types

<!-- Text variations -->
<input type="text" />
<input type="email" />
<input type="password" />
<input type="search" />
<input type="tel" />
<input type="url" />

<!-- Numbers -->
<input type="number" min="0" max="100" step="5" />
<input type="range" min="0" max="100" value="50" />

<!-- Dates and times -->
<input type="date" />
<input type="time" />
<input type="datetime-local" />
<input type="month" />
<input type="week" />

<!-- Selection -->
<input type="checkbox" />
<input type="radio" name="group" />
<input type="color" />
<input type="file" accept="image/*,.pdf" multiple />

<!-- Buttons -->
<input type="submit" value="Submit" />
<input type="button" value="Click" />
<input type="reset" value="Reset" />

Input Attributes

Validation

<input
  type="text"
  required
  minlength="3"
  maxlength="50"
  pattern="[A-Za-z]{3,}"
  title="Only letters, minimum 3 characters"
/>

<input type="number" min="0" max="100" step="0.01" />

Autocomplete

<!-- Common autocomplete values -->
<input type="text" autocomplete="name" />
<input type="email" autocomplete="email" />
<input type="tel" autocomplete="tel" />
<input type="text" autocomplete="street-address" />
<input type="text" autocomplete="postal-code" />
<input type="text" autocomplete="country" />
<input type="text" autocomplete="cc-number" />
<input type="text" autocomplete="cc-exp" />

<!-- Disable autocomplete -->
<input type="text" autocomplete="off" />

Mobile Optimization

<!-- Input mode (soft keyboard type) -->
<input type="text" inputmode="numeric" />
<!-- Options: text, decimal, numeric, tel, search, email, url -->

<!-- Enter key hint -->
<input type="text" enterkeyhint="search" />
<!-- Options: enter, done, go, next, previous, search, send -->

<!-- Auto-capitalization -->
<input type="text" autocapitalize="words" />
<!-- Options: off, none, on, sentences, words, characters -->

Other Important Attributes

<input
  type="text"
  placeholder="Enter text..."
  readonly
  disabled
  autofocus
  spellcheck="true"
  aria-label="Search"
  aria-required="true"
  aria-invalid="false"
/>

Datalist (Autocomplete Suggestions)

<label for="browser">Choose a browser:</label>
<input list="browsers" id="browser" name="browser" />
<datalist id="browsers">
  <option value="Chrome" />
  <option value="Firefox" />
  <option value="Safari" />
  <option value="Edge" />
</datalist>

Select Element

<label for="country">Country</label>
<select id="country" name="country" required>
  <option value="">-- Select --</option>
  <option value="us">United States</option>
  <option value="ca">Canada</option>
  <option value="uk">United Kingdom</option>
  <optgroup label="Europe">
    <option value="fr">France</option>
    <option value="de">Germany</option>
  </optgroup>
</select>

<!-- Multiple selection -->
<select multiple size="4">
  <option>Option 1</option>
  <option>Option 2</option>
</select>

Textarea

<label for="message">Message</label>
<textarea
  id="message"
  name="message"
  rows="5"
  cols="40"
  minlength="10"
  maxlength="500"
  placeholder="Enter your message..."
  required
></textarea>

Output Element <output>

<!-- Display calculation results -->
<form oninput="result.value=parseInt(a.value)+parseInt(b.value)">
  <input type="number" id="a" value="0" /> +
  <input type="number" id="b" value="0" /> =
  <output name="result" for="a b">0</output>
</form>

Fieldset and Legend

<fieldset>
  <legend>Shipping Address</legend>
  <label for="street">Street</label>
  <input type="text" id="street" name="street" />
  <!-- More fields -->
</fieldset>

<!-- Disabled fieldset -->
<fieldset disabled>
  <legend>Optional Information</legend>
  <!-- All inputs inside are disabled -->
</fieldset>

Form Attributes

<form
  action="/submit"
  method="post"
  enctype="multipart/form-data"
  novalidate
  autocomplete="on"
  target="_blank"
  rel="noopener"
>
  <!-- Form content -->
</form>
  • method"get" or "post"
  • enctype"application/x-www-form-urlencoded" (default), "multipart/form-data" (files), "text/plain"
  • novalidate – Disable HTML5 validation
  • autocomplete"on" or "off"