Home › Web Development › HTML
WEB DEVELOPMENT / HTML
Learn how HTML structures modern websites — from document basics and semantic elements to forms, media, accessibility, SEO and practical HTML5 development.
This is a working reference as much as a tutorial: every concept comes with a short, valid example you can copy and adapt.
THE BASICS
HTML stands for HyperText Markup Language. It’s the language used to give web content structure and meaning — marking up which part of a document is a heading, which is a paragraph, which is a link, an image, a list, a table, a form, a navigation region or a self-contained article.
HTML is a markup language, not a programming language. It has no variables, loops or logic. What it does is describe content: this text is the main heading, this group of links is the navigation, this image illustrates that figure.
When a browser receives an HTML file it parses the markup and builds an internal representation of the document, which it then uses to render the page and to expose the content to assistive technologies such as screen readers. That second part is why the choice of element matters: the meaning you encode in HTML is what software has to work with.
Modern HTML is maintained as a living standard by the WHATWG, with documentation on MDN Web Docs. It evolves continuously rather than in numbered versions, which is why there’s no “HTML 6” on the way.
THE FOUNDATION
Defines what the content is: headings, paragraphs, links, images, forms and regions. It carries the meaning that browsers, search engines and assistive technologies interpret.
Controls how that content looks: colour, typography, spacing, layout and responsive behaviour. Learn more in our CSS guide.
Adds interaction and application logic: responding to events, updating the page, fetching data. Covered in our JavaScript guide.
The division is a useful mental model, not a wall. In practice the three work together constantly — CSS selectors target HTML elements and classes, JavaScript reads and modifies the document HTML produced, and some behaviour that once needed scripting is now available in HTML and CSS directly. See the wider picture in our web development guides.
HOW IT WORKS
The journey from file to page is roughly this: the browser requests the HTML file, parses the markup, builds a document tree known as the DOM (Document Object Model), fetches and applies CSS, runs any JavaScript, and renders the result.
The DOM is a live, structured representation of the document that scripts can read and modify. It starts from your HTML but doesn’t stay identical to it: JavaScript can add, remove or change elements after load, and browsers correct certain markup errors while parsing. Viewing the source shows what was sent; inspecting the DOM in developer tools shows what currently exists.
This is a simplified model. Real rendering involves more stages than shown here, but the sequence is enough to reason about why markup, styles and scripts affect what appears on screen.
DOCUMENT STRUCTURE
Nearly every HTML page starts the same way. <!DOCTYPE html> is a declaration, not an element or a tag — it tells the browser to use standards mode rather than a legacy compatibility mode. It doesn’t “enable HTML5”; it simply signals modern parsing.
<html> is the root element and carries the lang attribute. <head> holds metadata and resource references that aren’t rendered as page content. <title> names the document. <body> contains everything the visitor actually sees.
The charset declaration should come early in the head, and the viewport meta is what makes responsive CSS behave as intended on phones.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Example Page</title> </head> <body> <h1>Hello world</h1> </body> </html>
<!-- Element: opening tag, content, closing tag --> <p class="intro">Hello world</p> <!-- Void elements have no closing tag --> <img src="photo.jpg" alt="A laptop on a desk"> <br> <input type="email" id="email"> <!-- Attributes configure the element --> <a href="/about/" class="button">About us</a>
SYNTAX
An element usually consists of an opening tag, content and a closing tag: <p>Hello</p>. A tag is just the markup delimiter — <p> on its own is a tag, while <p>Hello</p> is an element. People use the words interchangeably in conversation; technically they’re different things.
Not every element has a closing tag. Void elements such as <img>, <br>, <hr>, <input>, <meta> and <link> have no content, so they have no closing tag.
Attributes appear in the opening tag and configure the element: href on a link, src and alt on an image, type on an input. Some are global attributes that work on almost any element — id, class, title, lang, hidden, tabindex, data-* and the aria-* family. Others belong to specific elements only; href means nothing on a paragraph.
METADATA
The <head> holds information about the document rather than content for the page: the title, metadata, stylesheet and script references, and occasionally a <base> element.
<title> appears in the browser tab and bookmarks, is announced by screen readers when a page loads, and is commonly used by search engines when generating a result title. Make it describe the page specifically.
The meta description is metadata that search engines may use when generating a snippet — they often rewrite it based on the query, and it isn’t a ranking guarantee. See our website SEO guides.
The viewport meta tells mobile browsers to use the device width rather than a wide virtual viewport, which is what allows responsive CSS to work as intended — more in responsive design. The lang attribute on <html> declares the document’s actual language, helping screen readers pronounce content correctly and assisting translation tools. Set it to whatever the content really is.
Comments use <!-- ... -->. They’re useful for organising markup, but they’re visible in the page source — never put anything sensitive in one.
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HTML Guide: Elements, Tags and Best Practices</title> <meta name="description" content="Learn HTML elements, semantic markup, forms, accessibility and best practices."> <link rel="stylesheet" href="styles.css"> <!-- Comments are visible in the page source --> </head>
SEMANTIC MARKUP
Semantic HTML means choosing elements according to what the content is, rather than how you want it to look. <div class="header"> and <header> can look identical on screen; only one of them tells software anything.
The benefits are practical: assistive technologies can offer navigation by landmark and heading, the markup is easier for other developers to read, content structure is clearer to search engines, and CSS and JavaScript have meaningful hooks to work with. It’s a foundation, not a guarantee — semantic elements alone don’t make a page accessible or improve rankings, but their absence makes both harder.
Introductory or navigational content for a page or a section within it.
A block of major navigation links. Not every group of links needs one.
The primary content of the document. One per page, and not inside header, nav, aside or footer.
A thematic grouping of content, normally with a heading.
Self-contained content that would make sense on its own — a post, a comment, a product card.
Content tangentially related to the surrounding content, such as a sidebar or pull quote.
Footer content for its nearest sectioning ancestor, not necessarily the whole page.
<div> is a generic block-level container and <span> a generic inline one. Both are useful when no more appropriate element exists — typically for grouping purely for styling or scripting purposes.
The anti-pattern is reaching for them first. If the content is a navigation region, an article, a button or a list, the specific element communicates more and behaves better.
TEXT
Headings run from <h1> to <h6> and express document structure. Choose the level that reflects the content hierarchy, then style it with CSS — picking <h4> because it looked the right size breaks navigation for screen-reader users who move between headings. Use one <h1> that states what the page is about.
Paragraphs use <p>. Don’t create spacing with strings of <br> elements; that’s a job for CSS margins.
Text-level semantics convey meaning inside a paragraph. <strong> marks strong importance and <em> stress emphasis — both differ from purely visual bold and italic. <mark> highlights relevance, <small> indicates side comments, <abbr> expands abbreviations, <time> supplies a machine-readable date, and <sub> and <sup> handle subscript and superscript.
For technical text: <code> for code fragments, <pre> for preformatted blocks, <kbd> for keyboard input, <samp> for program output and <var> for variables. For quotations, <blockquote> handles longer passages, <q> inline quotes and <cite> the title of a referenced work.
<h1>Page title</h1> <h2>Section heading</h2> <p>A paragraph of text with <strong>strong importance</strong> and <em>emphasis</em>.</p> <p>Press <kbd>Ctrl</kbd> + <kbd>S</kbd> to save.</p> <p>Use the <code>alt</code> attribute on images.</p> <p>Published <time datetime="2024-03-08">8 March</time>.</p> <blockquote cite="https://example.com/source/"> <p>A quoted passage.</p> <footer><cite>Source title</cite></footer> </blockquote>
<!-- Relative: within the same site --> <a href="/web-development/css/">Learn CSS</a> <!-- Absolute: full URL --> <a href="https://example.com/guide/">External guide</a> <!-- Fragment: jump within the page --> <a href="#html-structure">Document structure</a> <!-- Email --> <a href="mailto:hello@example.com">Email us</a>
LINKS
The anchor element <a> with an href attribute is what makes the web a web. The text between the tags is the accessible name of the link, so it should describe the destination on its own — screen-reader users often list all links out of context, where “click here” repeated eight times is useless.
Relative URLs such as /web-development/css/ point within the same site and keep working if the domain changes. Absolute URLs include the full address and are needed for external links, feeds and some metadata. Fragment links using #id jump to an element on the page. mailto: and tel: links open the relevant application.
A link navigates; it shouldn’t be used to trigger an action on the current page. That’s what a button is for — covered below.
IMAGES
<img> takes a src and an alt. Setting width and height lets the browser reserve space so the page doesn’t shift as images load, and loading="lazy" defers off-screen images — though not the main hero image, which you want as early as possible.
Alt text depends on the image’s role. An informative image gets a description of what it conveys. A functional image inside a link or button is described by its action. A decorative image takes an empty alt="" so assistive technology skips it — omitting the attribute entirely is not the same thing. Complex diagrams usually need a fuller description nearby. Never keyword-stuff alt text; see website accessibility.
srcset and sizes let the browser choose an appropriately sized file for the viewport and screen density. <picture> goes further, allowing different crops for art direction or modern formats with a fallback — the inner <img> is required and carries the alt text. <figure> with <figcaption> associates a visible caption with an image, diagram or code sample.
<!-- Informative image -->
<img src="editor.jpg" alt="Laptop displaying an HTML editor"
width="800" height="600" loading="lazy">
<!-- Decorative image: empty alt -->
<img src="divider.svg" alt="">
<!-- Responsive image -->
<img src="small.jpg"
srcset="small.jpg 480w, large.jpg 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="Example responsive image">
<!-- Art direction and formats -->
<picture>
<source media="(max-width: 600px)" srcset="mobile.jpg">
<img src="desktop.jpg" alt="Example image">
</picture>
<figure>
<img src="diagram.png" alt="HTML document structure">
<figcaption>Illustrative HTML document structure.</figcaption>
</figure><ul>
<li>HTML</li>
<li>CSS</li>
</ul>
<ol>
<li>Plan the content</li>
<li>Write the markup</li>
</ol>
<dl>
<dt>HTML</dt>
<dd>Structure and meaning</dd>
</dl>
<table>
<caption>Frontend technologies</caption>
<thead>
<tr>
<th scope="col">Technology</th>
<th scope="col">Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">HTML</th>
<td>Structure</td>
</tr>
</tbody>
</table>LISTS & TABLES
Lists come in three kinds. <ul> for items whose order doesn’t matter, <ol> where sequence is meaningful, and <dl> with <dt> and <dd> for term-and-description pairs such as glossaries or metadata. Navigation menus are usually marked up as lists, which lets assistive technology announce how many items there are.
Tables are for tabular data — information with a genuine row-and-column relationship — not for page layout. That was a workaround from before CSS layout existed and it produces a confusing reading order for screen readers.
Accessible tables use <th> for header cells with a scope of col or row, which ties data cells to their headers so a screen reader can announce “Technology: HTML” rather than a bare value. A <caption> gives the table a title. <thead>, <tbody> and <tfoot> group rows. Complex tables with merged cells need more careful markup, and on narrow screens a table should scroll inside its own container rather than pushing the page sideways.
FORMS
Forms are where HTML’s semantics matter most, because getting them wrong locks people out of the one thing the page exists for.
Every control needs a <label> whose for attribute matches the input’s id. That association is what lets a screen reader announce the field, and it makes the label clickable, which enlarges the target. Placeholder text is not a label — it disappears as soon as someone types and often has poor contrast. <fieldset> with <legend> groups related controls such as radio buttons. More in website accessibility.
<form action="/contact/" method="post">
<label for="name">Full name</label>
<input id="name" name="name" type="text" required autocomplete="name">
<label for="email">Email address</label>
<input id="email" name="email" type="email" required
autocomplete="email">
<label for="message">Message</label>
<textarea id="message" name="message" rows="4"></textarea>
<fieldset>
<legend>Preferred contact</legend>
<input id="byEmail" name="contact" type="radio" value="email">
<label for="byEmail">Email</label>
<input id="byPhone" name="contact" type="radio" value="phone">
<label for="byPhone">Phone</label>
</fieldset>
<button type="submit">Send message</button>
</form>Choosing the right type gives you appropriate mobile keyboards, built-in format checking and better autofill behaviour for free.
<input type="text">
Single-line text
<input type="email">
Email with basic format checking
<input type="password">
Masked input
<input type="number">
Numeric values with optional min and max
<input type="tel">
Telephone numbers; triggers a numeric keypad
<input type="url">
Web addresses
<input type="search">
Search fields
<input type="date">
Date picker
<input type="time">
Time values
<input type="checkbox">
Zero or more options
<input type="radio">
One option from a group
<input type="file">
File upload
Validation attributes — required, min, max, minlength, maxlength, pattern and the type itself — let the browser catch obvious mistakes before submission. This improves the experience but is not a security measure: anyone can bypass client-side checks, so always validate on the server as well.
CONTROLS
Use a button when something happens on the current page, and a link when the location changes. The distinction isn’t pedantry: each comes with different keyboard behaviour and is announced differently by assistive technology, so the wrong choice breaks expectations.
Inside a form, <button> defaults to type="submit", which is why an unlabelled button can submit unexpectedly. Set type="button" for anything that shouldn’t submit.
<!-- Action on this page --> <button type="button">Open menu</button> <!-- Submits the form --> <button type="submit">Send message</button> <!-- Navigation --> <a href="/contact/">Contact</a>
<audio controls>
<source src="episode.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<video controls poster="preview.jpg" width="800" height="450">
<source src="demo.mp4" type="video/mp4">
<track kind="captions" src="captions.vtt" srclang="en"
label="English" default>
</video>
<iframe src="/embed/map/" title="Office location map"
loading="lazy"></iframe>MEDIA
<audio> and <video> embed media natively. The controls attribute exposes the browser’s own player, which is keyboard accessible by default. Multiple <source> elements let the browser pick a format it supports, and any content between the tags acts as a fallback message.
<track> adds timed text such as captions from a WebVTT file — essential for people who are deaf or hard of hearing, and useful for anyone watching without sound. Video also takes a poster image. Avoid autoplay with sound, and consider the bandwidth cost on mobile.
<iframe> embeds another document — a map, a video player, a third-party widget. Always give it a title, since screen-reader users otherwise encounter an unlabelled frame. Iframes carry security and performance implications, so only embed sources you trust, use loading="lazy" where appropriate, and size them responsively with CSS rather than fixed dimensions.
INTEGRATION
<link rel="stylesheet"> in the head attaches a stylesheet. Keeping presentation in CSS rather than inline style attributes makes markup readable and styles reusable — see our CSS guide.
<script> loads JavaScript. The defer attribute lets the browser continue parsing HTML and run the script once the document is parsed, in order — a sensible default for scripts that need the DOM. It isn’t right in every case: async suits independent scripts, and some code genuinely needs to run immediately. More in our JavaScript guide.
data-* attributes store custom data on an element for scripts to read, such as an identifier on a button. They’re for your own application data — they carry no meaning for browsers or assistive technology, so they never replace semantic elements or ARIA attributes.
<!-- In the head --> <link rel="stylesheet" href="styles.css"> <!-- Script that can wait for parsing to finish --> <script src="script.js" defer></script> <!-- Custom data for scripts --> <button type="button" data-product-id="123">View product</button>
<!-- Preferred: native element --> <button type="button" aria-expanded="false">Menu</button> <!-- Needs rebuilding keyboard behaviour by hand --> <div role="button" tabindex="0">Menu</div> <!-- Naming an icon-only control --> <button type="button" aria-label="Close dialog">×</button> <!-- Hiding decorative content from assistive tech --> <span aria-hidden="true">★</span>
ACCESSIBILITY
ARIA (Accessible Rich Internet Applications) supplies roles, states and properties for components HTML has no native element for. Useful attributes include aria-label and aria-labelledby for naming, aria-describedby for supplementary description, aria-expanded for disclosure state and aria-hidden for decorative content.
The first rule of ARIA is to prefer native HTML. A <button> arrives with focusability, keyboard activation and the correct role; a <div role="button"> has only the role — ARIA changes how something is announced, never how it behaves. Incorrect ARIA is often worse than none, because it promises capabilities that don’t exist.
Good HTML accessibility comes down to fundamentals: declare the language, write a meaningful title, keep headings logical, label every form control, use buttons and links correctly, write descriptive link text and alt text, mark up tables properly, and make sure everything works by keyboard. That’s a strong foundation — full accessibility still needs testing, covered in our website accessibility guide.
HTML IN CONTEXT
A descriptive <title>, logical headings, semantic structure, descriptive link text, useful alt text, crawlable internal links and clean metadata all help search engines interpret a page. Structured data can add machine-readable context. HTML supports understanding — it doesn't guarantee rankings, which depend on content quality, relevance, technical health and competition. See website SEO.
HTML supplies the content structure; CSS handles the responsive layout. The HTML side contributes the viewport meta tag, responsive images with srcset and sizes, and a source order that still makes sense when everything stacks into one column. See responsive design.
Markup affects loading: image dimensions prevent layout shift, loading="lazy" defers off-screen media, script loading attributes control blocking, and deeply nested markup enlarges the DOM. HTML alone doesn't determine speed — images, scripts, fonts and hosting matter more. See website speed.
STRUCTURE
HTML is hierarchical. Elements nest inside one another, forming parent, child and sibling relationships — a <section> containing an <h2> and a <p> makes those two children of the section and siblings of each other. That hierarchy becomes the document tree, and CSS selectors and JavaScript traversal both depend on it.
Nesting has rules. Elements must close in the reverse order they opened, and certain elements may only contain certain others — a <ul> expects <li> children, and interactive elements shouldn’t be nested inside each other. Browsers silently correct some mistakes, which is why validation is worth running.
On block and inline: elements like <div>, <p>, <section> and headings default to block-level display, while <span>, <a>, <strong> and <em> default to inline. Treat these as defaults, not fixed properties — CSS display can change them, and modern layout with flexbox and grid makes the old binary far less central than it once was.
<details>
<summary>What is HTML?</summary>
<p>HTML structures web content.</p>
</details>
<dialog id="confirm">
<p>Save your changes?</p>
<button type="button">Save</button>
</dialog>
<svg width="24" height="24" viewBox="0 0 24 24"
role="img" aria-label="Star rating">
<title>Star</title>
<path d="M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7z"></path>
</svg>INTERACTIVE ELEMENTS
<details> and <summary> create a native disclosure widget — expandable content with keyboard support and state announcement built in, no JavaScript required. Useful for FAQs and optional detail, though it isn’t a full accordion component.
<dialog> represents a dialog or modal, with browser-provided focus handling and an Escape-to-close behaviour when opened as a modal. It removes a lot of custom work, but it still needs testing — focus management and screen-reader behaviour vary, and native support doesn’t remove the need to check.
<template> holds inert markup that isn’t rendered until scripts clone it — the basis of most client-side templating. <canvas> provides a scriptable drawing surface; because its contents are pixels rather than elements, anything meaningful drawn there needs an accessible alternative. SVG can be embedded inline, scales cleanly at any size and can be styled with CSS — give meaningful graphics an accessible name and hide decorative ones.
ENTITIES & SECURITY
Some characters are part of HTML syntax, so writing them as literal text needs an entity: < for <, > for >, & for &, " for a quotation mark. produces a space that won’t break across lines. Entities also cover characters awkward to type directly.
Escaping is the same idea applied for safety. When user-supplied content is inserted into a page without escaping these characters, a browser may interpret it as markup rather than text — the basis of cross-site scripting (XSS). Escaping output and sanitising untrusted HTML are handled by your server-side language or framework; this page only flags the concept.
Other basics: never put credentials, API keys or private data in HTML or comments, since source is always viewable; be selective about which sources you embed in iframes; load resources over HTTPS; and treat anything a user can submit as untrusted until proven otherwise.
<!-- Showing markup as text --> <p>Use <p> for paragraphs.</p> <!-- Common entities --> & <!-- & --> < <!-- < --> > <!-- > --> " <!-- " --> <!-- non-breaking space -->
QUALITY
Running markup through a validator catches invalid nesting, missing required attributes, duplicate IDs and structural mistakes that browsers might silently paper over. The W3C provides an official validation service, and browser developer tools reveal how markup was actually parsed. Validation checks syntax and structure only — it says nothing about whether your alt text is meaningful, your headings sensible or your page accessible.
Choose elements by meaning, not appearance.
Nest logically and close elements correctly.
Make the destination clear from the link text alone.
Associate every control with a visible label.
Describe informative images; empty alt for decorative ones.
Levels reflect structure, styling comes from CSS.
Avoid inline styles; keep presentation in CSS.
Use defer or async appropriately for the script.
Check the markup, then test the real page.
PITFALLS
Generic containers where semantic elements would carry meaning.
Produces a confusing reading order and fragile markup.
Controls that assistive technology cannot identify.
The hint vanishes the moment typing starts.
“Click here” repeated across a page tells nobody anything.
Either no alternative at all, or keywords instead of a description.
Levels chosen for size, breaking navigation by heading.
Elements closed out of order or placed where they aren't allowed.
Layout work that belongs in CSS.
Unmaintainable, hard to override and bloats the markup.
Anything in the source can be read by anyone.
Duplicating semantics native elements already provide.
IDs must be unique; duplicates break labels and scripts.
Handlers on non-interactive elements with no keyboard path.
Missing viewport meta or fixed widths that overflow.
Structural errors found by users instead of the developer.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML Example</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>Learn HTML</h1>
<nav aria-label="Primary">
<ul>
<li><a href="/web-development/html/">HTML</a></li>
<li><a href="/web-development/css/">CSS</a></li>
</ul>
</nav>
</header>
<main>
<section>
<h2>HTML basics</h2>
<p>HTML structures content for the web.</p>
<a href="/web-development/css/">Learn CSS next</a>
</section>
</main>
<footer>
<p>Example page</p>
</footer>
<script src="script.js" defer></script>
</body>
</html>PUTTING IT TOGETHER
This example brings the pieces together: a declared doctype and language, character encoding and viewport in the head, a semantic structure of header, navigation, main and footer, a single <h1>, navigation marked up as a list, descriptive link text, and a deferred script at the end of the body.
It’s deliberately small. Real pages add more content, but the skeleton rarely changes — which is why learning it well pays off on every project.
REFERENCE
A categorised quick reference rather than an exhaustive list. Many of these — the sectioning elements, <figure>, the media elements, <details> and <dialog> — are part of modern HTML’s semantic and interactive vocabulary, added to the language at different points as it evolved. For the authoritative definition of any element, use the WHATWG HTML Living Standard or MDN Web Docs rather than a summary like this one.
<html><head><body><title><meta><link><base><header><nav><main><section><article><aside><footer><h1>–<h6><p><strong><em><mark><small><abbr><time><a><img><audio><video><picture><source><track><figure><figcaption><ul><ol><li><dl><dt><dd><table><caption><thead><tbody><tfoot><tr><th><td><form><label><input><textarea><select><option><button><fieldset><legend><details><summary><dialog><template><code><pre><kbd><samp><var><canvas><svg><iframe><div><span>IMPROVEMENTS
Simplified examples — real implementations depend on context. Each change swaps a generic construct for one that carries meaning.
CHECKLISTS
Three review passes over the same markup. These are practical working lists — the accessibility one is not a complete WCAG conformance test, and SEO involves many factors beyond HTML.
ACCESSIBILITY [ ] Document language is declared [ ] Page has a meaningful title [ ] Heading structure is logical [ ] Semantic elements used appropriately [ ] Links have descriptive text [ ] Images have appropriate alternatives [ ] Forms have associated labels [ ] Buttons use the right element [ ] Tables use proper headers [ ] Keyboard interaction is possible [ ] Focus remains visible [ ] Dynamic components have accessible states [ ] ARIA used only where needed [ ] Important content isn't hidden from assistive tech [ ] Multimedia has appropriate alternatives SEO [ ] Meaningful, descriptive title [ ] Logical heading structure [ ] Descriptive URLs [ ] Crawlable links in markup [ ] Useful text content [ ] Descriptive image alt text [ ] Appropriate metadata [ ] Semantic structure [ ] Relevant internal links [ ] Mobile-friendly structure [ ] Performance-conscious media [ ] Structured data where appropriate MARKUP QUALITY [ ] Valid document structure [ ] Correct nesting [ ] Closing tags where required [ ] Correct attributes for each element [ ] Unique IDs [ ] Appropriate element choices [ ] No unnecessary markup [ ] Forms correctly associated [ ] Media has alternatives [ ] Tested across relevant browsers
INTERVIEW PREP
Concise, technically accurate answers to the HTML questions that come up most often in interviews and assessments.
WORKFLOW
Know what the page needs to say.
Decide the sections and their hierarchy.
Doctype, lang, charset, viewport, title.
Header, nav, main, sections, footer.
Headings, text, lists and tables.
Descriptive links, images with alt text.
Labels, input types, validation.
Link stylesheets; keep styling out of markup.
Load scripts with the right strategy.
Run the markup through a validator.
Keyboard, headings, labels, contrast.
Check the full range of widths.
Images, scripts, DOM size.
Keep markup current as content changes.
LEARNING PATH
A workable order for learning HTML, roughly from structure outward. Accessibility and SEO appear midway rather than at the end deliberately — they’re easier to build in than to retrofit.
Reading about markup only goes so far. These practice projects are suggestions to build yourself, not downloadable templates — the useful part is hitting the problems that only appear with real content.
Beginner — headings, paragraphs, an image with alt text and a few links.
Intermediate — semantic sections, navigation, responsive images.
Intermediate — labelled inputs, appropriate types, validation attributes.
Advanced — deep heading hierarchy, skip link, tables, code samples.
Advanced — articles, figures, time elements, related content.
Advanced — hero, sections, form and clear content hierarchy.
WORDPRESS & ELEMENTOR
WordPress produces HTML at every level: themes and templates define the surrounding markup, the block editor and Elementor generate the content markup, and widgets, menus and forms each output their own structure. You don’t hand-code every page — but understanding what’s produced is what lets you debug layout problems, target elements with CSS, hook into them with JavaScript, fix heading hierarchies and improve accessibility.
In Elementor specifically, most widgets let you choose the HTML tag — which heading level a title uses, whether a container renders as a <section> or a <div>. Those choices are your semantic structure. The HTML widget handles genuine gaps: an embed, a snippet, a custom element. What it shouldn’t do is hold an entire page; that throws away the responsive controls and structure Elementor provides.
The most useful habit is inspecting the generated markup in browser developer tools. It shows exactly what visitors, search engines and assistive technologies receive — which is often not what the editor preview suggests. Related: WordPress guides.
Build layout with real Elementor containers rather than custom HTML blocks.
Choose the level for structure, adjust size separately.
Use the HTML widget only where a specific need isn't covered.
Check any hand-written HTML for nesting and attribute errors.
Check labels, focus visibility and keyboard access on widgets.
Confirm custom markup behaves at every breakpoint.
<!-- HTML: structure -->
<button type="button" id="menuButton" aria-expanded="false">
Open menu
</button>
<!-- CSS: presentation -->
<style>
#menuButton { padding: 10px 18px; border-radius: 8px; }
</style>
<!-- JavaScript: behaviour -->
<script>
const btn = document.getElementById("menuButton");
btn.addEventListener("click", () => {
const open = btn.getAttribute("aria-expanded") === "true";
btn.setAttribute("aria-expanded", String(!open));
});
</script>THE FRONTEND FOUNDATION
One small component shows the division clearly. The HTML declares what the control is — a button, with a state attribute. The CSS decides how it looks. The JavaScript updates the state when someone interacts with it.
Notice that the accessibility information lives in the HTML and is maintained by the JavaScript. That pattern — semantic markup as the foundation, styling layered on, behaviour keeping state accurate — is what most frontend work comes down to, whatever framework sits on top.
HTML is also where frontend development connects to everything else: React and similar libraries ultimately render HTML, PHP and Laravel generate it server-side, and website APIs supply the data that populates it.
NEXT TOPICS
Learn how CSS styles HTML content and controls layout, typography, colour and responsive presentation.
Learn how JavaScript adds behaviour and dynamic interaction to HTML pages.
Explore server-side development and dynamic web applications.
Learn component-based frontend development built around JavaScript.
Explore PHP-based web application development.
Understand how websites and applications exchange data with external services.
Learn how semantic HTML and accessible structures support inclusive experiences.
Learn the design fundamentals that shape the pages your markup describes.
FAQ
Short answers to the questions people ask most about HTML.
Learn how HTML structures modern websites and build a stronger foundation for responsive, accessible, search-friendly and maintainable web experiences.