HTML for Joomla
Open any Joomla page, ignore the colours and the moving parts for a moment, and look at what is left: a heading, some paragraphs, a list, a menu, a form. That skeleton is HTML, the language that says what each piece of content actually is. Joomla is written in PHP on the server, CSS decides how the page looks, and JavaScript makes it react, but underneath all of that sits HTML. It is the structure every browser, search engine, and screen reader reads first.
This article explains HTML from a Joomla point of view. It covers the basics for site owners and editors, the way Joomla assembles a page's HTML for administrators, and the developer tools (the template skeleton, jdoc:include tags, template overrides, HTMLHelper, and Joomla Forms) for those who build templates and extensions.
HTML is the content and the structure; CSS is the look; JavaScript is the behaviour.
The goal is simple: help you understand how Joomla produces HTML well enough to write clean content, change the markup in a place that survives updates, and keep your pages light, accessible, and easy for search engines to read.
1. The Basics
1.1 What is HTML?
HTML stands for HyperText Markup Language. It is the language that describes the structure and meaning of a web page: this is a heading, this is a paragraph, this is a link, this is a list, this is an image. The browser reads the HTML and builds the page from it, then CSS styles it and JavaScript adds behaviour. HTML always comes first, because the other two have nothing to work on until the structure exists.
HTML is not a programming language. It has no logic, no loops, and no calculations. It is a markup language: you wrap your content in tags that say what each part is. The browser does the rest.
1.2 Elements, Tags, and Attributes
The building block of HTML is the element. An element is usually an opening tag, some content, and a closing tag. For example, a paragraph looks like this:
<p>Welcome to my Joomla site.</p>
Many elements also take attributes, which are extra settings written inside the opening tag. A link uses the href attribute to say where it points, and an image uses src and alt:
<a href="/about-us">About us</a>
<img src="/images/logo.png" alt="Company logo">
A handful of attributes appear everywhere, so they are worth knowing by name:
| Attribute | What it is for |
|---|---|
class |
A label CSS and JavaScript target. Joomla and Bootstrap rely on it heavily. |
id |
A unique name for one element on the page. |
href / src |
The address of a link, or the source of an image or script. |
alt |
The text alternative for an image. |
aria-* |
Extra accessibility information (section 14). |
That is the whole idea. Content goes between tags, settings go in attributes, and elements nest inside each other to form the page.
1.3 Semantic HTML
The single most important habit in modern HTML is to choose the element that matches the meaning of the content, not the element that happens to look right. This is called semantic HTML. A heading should be a heading tag (<h1> to <h6>), a list should be a list (<ul> or <ol>), and the main navigation should sit in a <nav>.
Semantic HTML says what content is, not how it should look. The look is the job of CSS.
This matters because the meaning is what search engines index and what screen readers announce. A heading made of bold text inside a paragraph looks like a heading but means nothing; a real <h2> tells every machine that reads the page that a new section starts here.
1.4 Where Joomla Uses HTML
You do not have to write a line of HTML to benefit from it. Every Joomla page is HTML from top to bottom, and Joomla generates most of it for you:
- The template builds the page shell: the
<html>,<head>, and<body>. - Components output the main content, such as an article or a contact form.
- Modules output the smaller blocks: menus, login boxes, the search field.
- The editor turns the text you type into clean HTML when you save an article.
- Joomla Forms render every back-end and front-end form field as HTML inputs.
So most of the HTML on a Joomla site is produced by Joomla. Your job, when you want to change it, is to change it in the right place so it loads cleanly and survives the next update.
Back to top2. A Short History: From Table Layouts to Semantic HTML5
2.1 The XHTML and Table-Layout Era
Older websites, and older Joomla templates, were built very differently. Layouts were made with HTML <table> elements, nesting tables inside tables to position columns. Spacing came from invisible spacer images. The markup said almost nothing about meaning; it was all about pushing pixels into place. Joomla 1.x and 2.5 templates were full of this approach, and it made sites slow, hard to maintain, and unfriendly to screen readers.
2.2 HTML5 and Joomla
HTML5, the current version of HTML, changed the picture. It added elements that describe meaning, such as <header>, <nav>, <main>, <article>, <section>, <aside>, and <footer>. Layout moved out of HTML tables and into CSS (Flexbox and Grid). From Joomla 4 onward, the default template, Cassiopeia, outputs clean, semantic HTML5 and uses CSS for layout. Joomla 5 and 6 continue this: tables are used only for tabular data, and the page structure is built from meaningful elements.
2.3 Why This Matters to You
The practical result is that a modern Joomla site already produces good HTML. You rarely need to fight the markup. When you do write HTML, whether in an article, a custom module, or a template override, the goal is to match that modern, semantic style: use the right element for the job, keep the structure clean, and let CSS handle the appearance. Do not paste in old table-based layouts or copy markup from a tool that wraps everything in <div> tags with no meaning.
3. How Joomla Builds the HTML of a Page
3.1 PHP Renders, the Browser Receives
When a visitor opens a Joomla page, the server runs PHP, gathers the content from the database, and assembles one finished HTML document. The browser receives that HTML, draws the page, then applies the CSS and runs the JavaScript. By the time you can read a page, the HTML is already complete and static; nothing on the server changes until the next request.
This is the opposite of how JavaScript works (which runs in the browser after the HTML arrives). Knowing where the HTML is built, on the server, in PHP, tells you where to look when the markup is wrong: in the template, the component, or an override, not in the browser.
3.2 The Document Object
Joomla represents the page it is building as a document object. For a normal web page this is an HTML document, and it holds the page title, the metadata, the links to stylesheets and scripts, and the body content. Your code reaches it through the application:
use Joomla\CMS\Factory;
$doc = Factory::getApplication()->getDocument();
$doc->setTitle('My page title');
The document is what turns all the separate pieces, the template, the component, and the modules, into one HTML string that is sent to the browser.
3.3 The Page Head
The <head> of an HTML page is not visible, but it carries vital information: the page title, the character set, the viewport setting for mobile, the meta description, and the links to CSS and JavaScript. Joomla builds the head for you from the document object, so you set values in PHP rather than typing tags by hand:
$doc->setDescription('A short summary for search engines.');
$doc->setMetaData('viewport', 'width=device-width, initial-scale=1');
Because Joomla writes the head, you get a consistent, valid head on every page, and extensions can add to it safely without overwriting each other.
3.4 HTML Is One of Several Document Types
HTML is the normal output, but it is not the only one Joomla can produce. The same content can be delivered in different formats by changing the document type, which you usually request with the format parameter in the URL:
| Type | What it outputs |
|---|---|
html |
A full HTML page. The default. |
json |
Data with no markup, used by the Web Services API and Ajax. |
feed |
An RSS or Atom feed (XML). |
raw |
The raw body with no template around it. |
xml |
An XML document. |
This is worth knowing because it shows that HTML is a presentation layer, not the data itself. When Joomla serves the headless Web Services API, it produces JSON and no HTML at all. The content is the same; only the document type changes.
Back to top4. How the Browser Reads HTML: the DOM
Joomla's job ends when it sends the HTML. The browser's job begins there, and it does not keep your HTML as text. It turns it into a live tree it can style, change, and redraw. Understanding that tree explains why clean HTML matters and why the page you inspect is not always the page Joomla sent.
4.1 From HTML to the DOM Tree
The browser parses your HTML into the DOM (Document Object Model), a tree of nodes where every element, attribute, and piece of text is an object. The nesting of your tags becomes the shape of the tree:
HTML source → HTML parser → DOM tree
CSS goes through the same process into a parallel tree called the CSSOM. JavaScript can read and change the DOM at any time after it is built, which is how a menu opens or a new row appears without a page reload.
4.2 DOM Plus CSSOM Equals the Rendered Page
The browser combines the DOM and the CSSOM into a render tree, works out where everything goes (layout), draws it (paint), and layers it on the screen (composite):
DOM + CSSOM → render tree → layout → paint → composite
Every element in your HTML becomes a node the browser must hold in memory, style, and lay out. A small, shallow DOM is quick to build and cheap to update; a huge, deeply nested one is slow at every step (section 15).
4.3 View Source Versus Inspect Element
Two browser tools show you HTML, and they are not the same thing:
- View Source shows the original HTML exactly as Joomla sent it, before any JavaScript ran.
- Inspect Element shows the live DOM right now, including everything JavaScript has added or changed since.
The difference is crucial when you debug. If a menu, slider, or module looks wrong, comparing the two tells you whether the problem is in the HTML Joomla produced (fix it in a template or override) or in the JavaScript that changed it afterwards.
Back to top5. The Template Skeleton and jdoc:include
5.1 index.php Holds the Page Shell
Every Joomla template has an index.php file that defines the HTML skeleton of the page: the doctype, the <html> element with its language, the <head>, and the <body> with its layout regions. This file is plain HTML with a few special placeholders that Joomla fills in. Cassiopeia's lives in templates/cassiopeia/index.php, and its top looks much like this:
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
<jdoc:include type="metas" />
<jdoc:include type="styles" />
<jdoc:include type="scripts" />
</head>
<body>
...
</body>
</html>
The lang attribute is set from the site language, which matters for accessibility and SEO. You normally never edit a core template's index.php; if you need to change the shell, you use a child template (section 8).
5.2 The jdoc:include Tags
The <jdoc:include> tags are the heart of a Joomla template. Each one tells Joomla to drop a particular piece of generated HTML into that spot. They are not real HTML; Joomla replaces them while it builds the page. The main types are:
| jdoc:include type | What it inserts |
|---|---|
metas, styles, scripts |
The head: meta tags, stylesheet links, and script tags. |
head |
All of the above at once (the older, combined form). |
component |
The main content of the page from the active component. |
modules |
Every module published to a named position. |
message |
Joomla's system messages (the alert bar). |
Splitting the head into metas, styles, and scripts (instead of one head) lets the template control their order, which is why modern Cassiopeia uses the three separate tags.
5.3 Module Positions and Chrome
The modules tag names a position and a style. The position is a label (such as sidebar-right) that you also pick when you publish a module, and the style decides the HTML wrapper, called the module chrome, that goes around each module:
<jdoc:include type="modules" name="sidebar-right" style="card" />
So the template defines where modules can appear and how they are wrapped, while the administrator decides which modules go in each position. Joomla matches the two and writes the final HTML. Choosing a lighter chrome (or none) avoids extra wrapper markup you do not need (section 15).
6. Semantic Structure: Landmarks and Headings
6.1 The HTML5 Landmark Elements
HTML5 gives a page a small set of structural elements that describe its major regions. Used well, they turn a flat wall of <div> tags into a page a screen reader can navigate and a search engine can understand:
| Element | Meaning |
|---|---|
<header> |
The top area: logo, site title, sometimes the main menu. |
<nav> |
A block of navigation links. |
<main> |
The main content, unique to the page. One per page. |
<article> |
A self-contained piece, such as a blog post. |
<section> |
A thematic grouping within the content. |
<aside> |
Related but separate content, such as a sidebar. |
<footer> |
The bottom area: copyright, secondary links. |
6.2 One Main, One H1, Ordered Headings
Two structural rules carry most of the weight. First, a page should have exactly one <main> and one <h1>, the page's true title. Second, headings should go in order without skipping levels: an <h2> starts a major section, an <h3> a subsection inside it, and so on. Do not jump from <h1> to <h4> just because the smaller text looks nicer; choose the right level and style it with CSS.
This is exactly how the article you are reading is built: one title, then numbered <h2> sections, each with <h3> subsections. The structure is the meaning.
6.3 Cassiopeia's Semantic Output
Cassiopeia already produces this structure. It wraps the page in landmark elements, puts the component output inside a <main>, and adds a "Skip to main content" link at the top so keyboard users can jump past the menu. When you write content or build an override, your job is to keep that structure intact: put the article title in the heading Joomla provides, and use real headings and lists inside the body rather than styled paragraphs.
7. Where the HTML Comes From: Components, Modules, Layouts
To change the HTML of a Joomla page, you first have to know which part of Joomla produced it. The page is assembled from several sources, and each has its own files.
7.1 Component Output (the Main Content)
The component is what answers the URL: com_content shows articles and categories, com_contact shows the contact form, and so on. Its HTML is generated by view template files (also called layouts), which are PHP files that mix HTML with small loops over the data. For an article, the relevant file is:
components/com_content/tmpl/article/default.php
This file decides the markup around a single article: where the title goes, how the author and date appear, and how the body is wrapped. Content plugins can also change the HTML at this stage, replacing tags in the article text before it is shown (this is how features such as the read-more break or media embeds work). It is the HTML you most often want to adjust, and you do that with an override (section 8), never by editing this file.
7.2 Module Output and Chrome
Each module also has its own layout files that produce its HTML. A menu module builds a <ul> of links; a custom module outputs whatever HTML you put in it. On top of the module's own HTML sits the chrome, the wrapper the template adds (the style attribute from section 5.3), which gives every module in a position a consistent frame such as a card with a heading.
7.3 Layouts: Reusable HTML Snippets
Joomla also has a layouts system for small, reusable pieces of HTML that many places share, such as a pagination bar, a set of icons, or a form field. These live under layouts/ and are rendered from PHP with LayoutHelper:
use Joomla\CMS\Layout\LayoutHelper;
echo LayoutHelper::render('joomla.content.icons', $displayData);
The point for you is that a single bit of repeated markup is usually a shared layout, so you can override it once and fix it everywhere, instead of editing the same HTML in many files.
7.4 The Classes in Joomla's HTML
Look at Joomla's output and you will see many class attributes, most of them from Bootstrap 5, which Joomla bundles. When you change the markup, it helps to know what a class is doing before you remove it:
- Visual classes only style the element, such as
text-centerormt-3. Safe to change. - Structural classes are part of a layout system, such as
rowandcol-md-8. Remove one and the grid breaks. - Behaviour classes are hooks JavaScript looks for, such as a Bootstrap modal trigger. Remove one and the script stops working.
Some attributes do double duty for accessibility too, such as role="alert" on a message box, which tells assistive technology the purpose of the element. Keep those when you restyle.
8. Template Overrides: Changing Joomla's HTML
This is the most important Joomla-specific idea in the whole article. When the HTML a component or module produces is not what you want, you do not edit the extension. You make a template override: a copy of the layout file placed inside your template, where Joomla uses it instead of the original. Your copy survives updates, because the update replaces the core file, not your override.
8.1 What an Override Is
An override is a layout file in a special folder inside your template. Joomla looks there first; if it finds a matching file, it uses yours, otherwise it falls back to the extension's own. Nothing in the extension changes, so an update cannot wipe your work (though you should re-check overrides after a big update, in case the original markup changed).
8.2 How to Create One
You do not have to copy files by hand. In the back end, go to System → Site Templates → Cassiopeia Details and Files → Create Overrides, pick the component or module, and Joomla copies the layout into the right place for you. The result is a file you can edit:
Original layout:
components/com_content/tmpl/article/default.php
Your override (Joomla uses this instead):
templates/cassiopeia/html/com_content/article/default.php
Open the override and change the HTML: add a wrapper, add a class for your CSS, move the date below the title, or remove a piece you do not want. The content still comes from Joomla; you control only the markup around it.
8.3 A Common Example: Semantic Article Images
A frequent reason to override is to improve the markup around an image. By default an intro image is a plain <img>; in your override you can wrap it in a <figure> with a caption, which is clearer and easier to style (section 9.4):
<figure class="article-image">
<img src="/images/example.jpg" alt="Example image">
<figcaption>Example image caption</figcaption>
</figure>
8.4 Override Module Chrome and Layouts
The same mechanism works for module chrome and for shared layouts. Module styles live under html/layouts/chromes/ in the template, and shared layouts mirror their original path under html/layouts/. So you can change how every module in a position is wrapped, or how pagination looks site-wide, by overriding one file. Do this in a child template for serious work, so even a change to the parent template leaves your overrides untouched.
9. Modern HTML Elements Worth Knowing
HTML keeps gaining elements that do, on their own, jobs that used to need JavaScript or a framework. They work in every current browser, so you can use them in articles (where the text filter allows), in a Custom module, or in a template override. Reaching for the right native element keeps your pages lighter and more accessible.
9.1 details and summary for FAQs and Toggles
The <details> element makes an open-and-close panel with no JavaScript at all. The <summary> is the part that is always visible and clickable. It is perfect for an FAQ list or a "read more" toggle:
<details>
<summary>How do I update Joomla safely?</summary>
<p>Take a backup first, then run the update from the System dashboard.</p>
</details>
9.2 dialog for Simple Modals
The <dialog> element is a built-in pop-up. It handles the overlay, focus, and the Escape key for you, which once needed a library:
<dialog id="contact-dialog">
<p>Contact us for more information.</p>
<button>Close</button>
</dialog>
For a back-end component, Joomla's bundled Bootstrap modal is still the consistent choice; for a small front-end pop-up, native <dialog> is often enough.
9.3 picture for Responsive and Modern Images
The <picture> element lets the browser pick the best image: a modern format such as WebP when it is supported, with a normal fallback. This cuts image weight without any script:
<picture>
<source srcset="/images/photo.webp" type="image/webp">
<img src="/images/photo.jpg" alt="Our office">
</picture>
Add loading="lazy" to images below the fold so the browser only fetches them when they are about to appear, which speeds up the first view of the page.
9.4 figure, figcaption, and template
Two more elements round this out. <figure> with <figcaption> ties an image to its caption as one semantic unit (the override example in section 8.3). And <template> holds a chunk of markup that does nothing until JavaScript clones it, which is the clean way to repeat a card or a row that a script will fill in later.
10. Writing HTML in Articles: The Editor and Code View
Most people who use Joomla write HTML without realising it: every time you format an article, the editor produces HTML behind the scenes. Knowing how that works helps you keep your content clean.
10.1 TinyMCE and the WYSIWYG Editor
Joomla's default editor is TinyMCE, a "what you see is what you get" (WYSIWYG) editor. When you make text bold, add a list, or insert a link, TinyMCE writes the matching HTML (<strong>, <ul>, <a>) into the article body, which Joomla then stores in the database. You write content; the editor writes the HTML.
TinyMCE is configured as a plugin, so an administrator can decide which buttons editors see and which HTML they are allowed to produce. A tidy editor configuration is the easiest way to keep article HTML consistent across many authors.
10.2 The Code View (Editing Raw HTML)
Sometimes you need to see or edit the HTML directly: to fix a stray tag, paste an embed, or add a class. TinyMCE has a code view (the </> button) that shows the raw HTML of the article. For full control, you can switch the editor to CodeMirror or None in your user settings or globally, which lets you type HTML by hand with no WYSIWYG layer in the way.
When you paste from a word processor, paste as plain text or use the editor's paste-cleaning, because Office documents bring in a mass of meaningless markup and inline styles that bloat the page and fight your CSS.
10.3 The Custom HTML Module
When you want a block of your own HTML somewhere on the site that is not part of an article, use a Custom module (mod_custom). It gives you the same editor and stores whatever HTML you write, then you publish it to a position. It is the right tool for a promo box, a footer note, or a small piece of embedded content, and it keeps that HTML out of your articles where it does not belong.
11. Text Filters: What HTML Joomla Lets You Save
Joomla does not blindly save every tag you type. It runs article and module HTML through a text filter first, to stop a user from saving dangerous markup such as a <script> that could attack other visitors. This is a security feature, and it is the reason a script or an <iframe> you paste sometimes disappears when you save.
11.1 Why Joomla Filters HTML
If any author could save a <script> tag, a single compromised or careless account could inject code that runs in every visitor's browser (a cross-site scripting attack). The text filter removes such tags for users who are not trusted to use them, so the stored HTML stays safe.
11.2 The Filter Settings
You control the filter in System → Global Configuration → Text Filters. The settings apply per user group, so you can trust your administrators while restricting public or less-experienced authors. The main modes are:
| Mode | What it does |
|---|---|
| Default Black List | Strips known-dangerous tags (such as script) and allows the rest. |
| Custom Black List | Your own list of tags and attributes to remove. |
| White List | Allows only the tags you list, removes everything else. |
| No Filtering | Saves any HTML. Use only for fully trusted groups. |
| Prohibited | Allows no HTML tags at all for that group. |
11.3 Choosing the Right Filter Per Group
By default, the Super Users group is set to No Filtering and everyone else to the Default Black List, which is a sensible starting point. If editors need an extra tag (an <iframe> for a map, say), do not switch a whole group to No Filtering; instead add that one tag to a White List or remove it from the Black List for that group only. Keep the lowest level of trust that still lets people do their work.
12. Generating HTML From PHP: HTMLHelper
When you build an extension or an override, you often need to output a common piece of HTML: an image tag, a formatted date, a link, a list of options. Joomla provides HTMLHelper (the HTMLHelper::_() function) so you produce that markup consistently instead of writing tags by hand each time.
12.1 What HTMLHelper Does
HTMLHelper is a registry of small functions that each return a tested piece of HTML. You call one by name and pass it your data; it returns the markup, correctly escaped and formatted. This keeps output consistent across the whole site and saves you from re-inventing the same tag everywhere.
use Joomla\CMS\HTML\HTMLHelper;
echo HTMLHelper::_('image', 'logo.png', 'Company logo');
echo HTMLHelper::_('link', $url, 'Read more');
echo HTMLHelper::_('date', $article->created, 'F j, Y');
12.2 Common Helpers
| Helper | What it returns |
|---|---|
HTMLHelper::_('image', ...) |
An <img> tag, resolving the image path for you. |
HTMLHelper::_('link', ...) |
An <a> tag with the right attributes. |
HTMLHelper::_('date', ...) |
A date formatted in the site's time zone and language. |
HTMLHelper::_('bootstrap.renderModal', ...) |
A Bootstrap modal dialog. |
HTMLHelper::_('list.genericordering', ...) |
A select list of ordering options. |
12.3 Escaping: Never Output Raw Data
Whenever you print a value into HTML by hand, escape it first, so a stray < or a quote in the data cannot break the page or inject a tag. In a view template, Joomla gives you $this->escape(), which runs the value through htmlspecialchars:
<h2><?php echo $this->escape($article->title); ?></h2>
The rule is simple: data from the database or the user is text, not HTML, until you escape it. Helpers like HTMLHelper handle this for you; when you write tags by hand, escaping is your job.
Back to top13. Forms and HTML in Joomla
Forms are HTML too, and they are where bad markup hurts users most. Joomla has its own Form system that turns a simple definition into accessible HTML inputs, so you rarely write a form's HTML by hand.
13.1 Joomla Forms Render HTML
A Joomla form is described in an XML file as a list of fields. Joomla reads it and renders the matching HTML: the input, its label, and any help text, all wired together correctly. Almost every form you see in the back end, and many in the front end, is built this way:
<field
name="email"
type="email"
label="COM_EXAMPLE_EMAIL_LABEL"
required="true"
/>
From that one line Joomla produces an <input type="email">, a matching <label>, the required attribute, and the validation hooks, all consistent with the rest of the site.
13.2 Field Types and Their Markup
Each field type maps to a specific piece of HTML. A handful cover most needs:
| Field type | HTML it produces |
|---|---|
text, email, url |
An <input> of the matching type. |
textarea |
A multi-line <textarea>. |
list |
A <select> with <option> children. |
radio, checkboxes |
A group of radio buttons or checkboxes with labels. |
editor |
A full WYSIWYG editor (TinyMCE). |
13.3 Labels and Accessible Forms
The big win of the Form system is accessibility. It links each label to its input with the right for and id attributes, so a screen reader announces the label when the user reaches the field, and clicking the label focuses the input. If you ever write a form by hand, copy this: every input needs a real <label> tied to it, not just text sitting next to it.
14. Accessibility and Semantic HTML
HTML decides whether a site works for people who use a screen reader, navigate by keyboard, or rely on browser zoom. Good, semantic HTML is most of accessibility; the rest is small additions on top. These checks also overlap with the WCAG standards many sites must meet.
14.1 Landmarks and Skip Links
The landmark elements from section 6 (<header>, <nav>, <main>, <footer>) let a screen-reader user jump straight to a region. A skip link at the very top, which Cassiopeia includes, lets a keyboard user skip the menu and go to the content. Keep both intact when you build a template or an override.
14.2 Headings and Reading Order
Screen-reader users often move through a page by its headings, so a correct heading order (section 6.2) is a navigation tool, not just a visual style. Make sure the HTML order matches the reading order too: do not use CSS to move a block visually while it stays in a different place in the HTML, because the screen reader follows the HTML.
14.3 Images, Labels, and Alt Text
Every meaningful image needs an alt attribute that describes it, so people who cannot see it still get the information. A decorative image that adds nothing should have an empty alt="" so the screen reader skips it. Joomla's media field and the editor both let you set alt text; use it. Forms need real labels, as in section 13.3.
14.4 Use Buttons and Links Correctly
A link (<a>) goes somewhere; a button (<button>) does something. Both are keyboard accessible by default. A common mistake is to make a <div> clickable with JavaScript, which a keyboard user cannot reach:
<!-- Avoid: not keyboard accessible, no role. -->
<div onclick="submitForm()">Send</div>
<!-- Prefer: works with keyboard and announces its role. -->
<button type="submit">Send</button>
14.5 ARIA: Use It Sparingly
ARIA attributes (such as role and aria-label) add accessibility information when plain HTML cannot. The first rule of ARIA, though, is not to use it when a real HTML element will do: a <button> is better than a <div role="button">. Reach for ARIA only to fill a genuine gap, such as an off-canvas menu or a live region that updates, and test it, because wrong ARIA is worse than none.
15. Performance: Keep the HTML Light
HTML performance is not only about file size. As section 4 showed, every element becomes a node the browser must build, style, lay out, and update. A heavy page can be slow even with small images, because the DOM itself is too big.
15.1 DOM Size Matters
A small, shallow DOM is fast: quick to parse, cheap to lay out, and light for JavaScript to search and change. A large, deeply nested DOM slows every one of those steps, and tools such as Lighthouse warn when a page has too many elements or nests them too deeply. Clean HTML is a performance feature, not just a tidiness one.
15.2 Where Joomla Bloat Comes From
Most oversized Joomla pages grow for a handful of familiar reasons:
- Too many modules published on one page, each adding its own wrapper.
- Heavy module chrome or extra nested wrappers where a lighter style would do.
- Page-builder content that wraps every line in several
<div>tags. - A second, hidden mobile menu duplicating the desktop one.
- Large tables, repeated inline SVG icons, and heavy third-party embeds.
15.3 Trim the Markup
The fixes follow the causes. Unpublish modules a page does not need, choose a lighter chrome (section 5.3) or none, and simplify the markup in your overrides. Add loading="lazy" to below-the-fold images (section 9.3) so they load only when needed. When you weigh a page builder, remember that the convenience often costs you a much larger DOM. Good Joomla performance work includes reviewing the generated HTML, not only compressing images and enabling cache.
16. Validating and Debugging HTML
Most HTML problems are easy to find once you look at the actual markup the browser received, not the source you think you wrote. A few tools do almost all of this work.
16.1 The Browser's Developer Tools
Press F12, or right-click an element and choose Inspect. The browser shows the live DOM tree, the element you clicked, and how everything nests. As section 4.3 explained, this is the DOM after JavaScript has run; use View Source alongside it to see the raw HTML Joomla sent. The other panels help too: the Network tab shows which assets loaded, the Accessibility panel shows roles and labels, and Lighthouse reviews performance and accessibility in one report.
16.2 HTML Validation
A validator checks your HTML against the standard and reports errors such as unclosed tags, duplicate IDs, or elements nested in the wrong place. The official W3C validator at validator.w3.org can check a live URL. Valid HTML is more predictable across browsers and easier for search engines and assistive technology to read.
16.3 Common Invalid-Markup Traps
- Unclosed tags: a missing
</div>shifts the whole layout. The inspector shows where the nesting goes wrong. - Duplicate IDs: an
idmust be unique on a page; two of the same break CSS and JavaScript that target it. This is easy to cause in an override. - Block inside inline: putting a
<div>inside an<a>or a<p>can produce surprising results. - Pasted markup: content pasted from Word or another site often carries broken or meaningless tags; clean it on paste.
17. SEO, Metadata, and Structured Data
Search engines read HTML, so the quality of your markup directly affects how well a page can rank. Most of SEO at the HTML level is simply good, semantic structure.
17.1 Semantic HTML Helps Ranking
- One clear
<h1>per page and an ordered heading structure tell a search engine what the page is about and how it is organised. - Descriptive link text (
<a>with real words, not "click here") helps both users and crawlers. - Meaningful
alttext lets images appear in image search and describes them when they cannot load. - A responsive, valid, light layout is mobile-friendly and fast, both of which are ranking factors.
17.2 Meta Tags and Open Graph
Joomla writes the basic meta tags for you: the title, the meta description, the viewport, and the character set. You set the title and description per article or menu item, in the Publishing and Metadata tabs, and Joomla puts them in the head. For social sharing, Open Graph tags (og:title, og:image) control how a link looks on social media; the core does not add these by default, so a plugin, template, or an entry added with $doc->setMetaData() supplies them.
17.3 Structured Data (Schema.org)
Structured data is extra, machine-readable information you add to a page to describe what it is (an article, a product, an event, a recipe), usually as a block of JSON-LD in the head. Search engines use it for rich results such as star ratings and FAQ panels:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Focus on HTML in Joomla"
}
</script>
Joomla does not output schema.org data by default; you add it with a plugin or template, or by injecting a JSON-LD script through the document. Make sure it matches the visible content: do not add misleading schema, which search engines can penalise.
Back to top18. Common Mistakes and Pitfalls
18.1 Editing Core Files Instead of Using an Override
Symptom: your HTML change to an article layout or module disappears after a Joomla update.
Fix: never edit files in components/, modules/, or a core template. Make a template override (section 8), which survives updates.
18.2 Non-semantic, Div-only Markup
Symptom: a layout works visually but is hard for search engines and screen readers to understand.
Fix: use the element that matches the meaning, a heading for a heading, a list for a list, a <nav> for navigation, and style it with CSS rather than wrapping everything in <div> tags.
18.3 Skipping Heading Levels
Symptom: headings jump from <h1> to <h4> to get a certain size, and the document outline is broken.
Fix: choose the correct heading level for the structure and set the size in CSS. One <h1>, then ordered <h2> and <h3>.
18.4 Pasting Messy HTML From Word
Symptom: an article carries strange spacing and inline styles and ignores your stylesheet.
Fix: paste as plain text or use the editor's paste-cleaning, then format with the editor's buttons. Keep design in CSS, not in pasted inline styles.
18.5 A Bloated DOM From Too Much Markup
Symptom: the page feels slow to render even though the images are small.
Fix: reduce the number of published modules, choose lighter chrome, and simplify page-builder or override markup so the DOM stays small (section 15).
18.6 Clickable Divs Instead of Buttons or Links
Symptom: a control works with the mouse but a keyboard user cannot reach or trigger it.
Fix: use a real <button> for actions and an <a> for navigation, which are keyboard accessible by default (section 14.4).
18.7 Missing Alt Text and Labels
Symptom: images have no alt and form fields have no real labels, so the site fails accessibility checks.
Fix: add meaningful alt text to content images (empty alt for decorative ones), and rely on Joomla Forms, which label fields correctly.
19. Best Practices
If you remember only a few things from this article, remember these:
- Write semantic HTML: choose the element by meaning, and leave the look to CSS.
- Keep one
<h1>and one<main>per page, and order your headings without skipping levels. - Change Joomla's markup with a template override (in a child template for serious work), never by editing core files.
- Let Joomla build the page: set the title and metadata through the document, and use
<jdoc:include>regions in the template. - Use HTMLHelper for common markup and always escape data you print by hand.
- Build forms with the Joomla Form system so labels and inputs are accessible by default.
- Reach for modern native elements (
details,dialog,picture,figure) before adding JavaScript. - Keep the DOM light: fewer modules, lighter chrome, simpler markup, lazy-loaded images.
- Set Text Filters per user group to the lowest trust that still lets people work.
- Add meaningful
alttext, keep the skip link and landmarks, and use ARIA only to fill real gaps. - Help SEO with clean structure, good titles and descriptions, and accurate structured data.
- Debug with View Source and Inspect, and validate your HTML when something looks wrong.
20. Quick Reference
WHAT IT IS HTML is the content and structure; CSS the look, JS the behaviour
SEMANTIC Pick the element by meaning (h2, ul, nav), style it with CSS
BUILT BY PHP on the server; the browser receives finished HTML
DOM Browser parses HTML into the DOM tree; JS can change it after
SOURCE vs DOM View Source = what Joomla sent; Inspect = live DOM after JS
DOCUMENT $doc = Factory::getApplication()->getDocument();
SET TITLE $doc->setTitle('...'); $doc->setDescription('...')
TEMPLATE SHELL templates/cassiopeia/index.php (doctype, head, body)
JDOC TAGS <jdoc:include type="metas|styles|scripts|component|modules|message" />
MODULE POS <jdoc:include type="modules" name="sidebar-right" style="card" />
LANDMARKS header, nav, main (one), article, section, aside, footer
HEADINGS One h1 per page; order h2 -> h3, no skipped levels
COMPONENT HTML components/com_content/tmpl/article/default.php
OVERRIDE templates/cassiopeia/html/com_content/article/default.php
MAKE OVERRIDE System → Site Templates → Cassiopeia → Create Overrides
MODERN EL <details>/<summary>, <dialog>, <picture>, <figure>, <template>
RESP IMAGES <picture> + WebP source; add loading="lazy" below the fold
EDITOR TinyMCE writes the HTML; code view (</>) shows raw HTML
CUSTOM HTML mod_custom for a free block of HTML in a position
TEXT FILTERS Global Configuration → Text Filters, per user group
FROM PHP HTMLHelper::_('image'|'link'|'date', ...)
ESCAPE <?php echo $this->escape($value); ?> always for raw data
FORMS XML <field type="..."> renders accessible input + label
DOC TYPES html (default), json, feed, raw, xml via &format=
PERFORMANCE Smaller, shallower DOM parses and paints faster
ACCESSIBILITY alt text, real labels, skip link, button vs link, ARIA last
SEO one h1, good titles/descriptions, Open Graph, JSON-LD
DEBUG F12 / Inspect for live DOM; validator.w3.org to validate
NO CORE HACKS Override, child template, plugin, or extension - never core
Back to top21. Summary
HTML is the foundation of every Joomla page. PHP builds it on the server, CSS styles it, and JavaScript adds behaviour, but the HTML structure is what every browser, search engine, and screen reader reads first. Joomla 6 produces clean, semantic HTML5 and gives you safe ways to shape it:
- Semantic structure: landmark elements, one
<h1>, and ordered headings carry the meaning that machines and assistive technology rely on. - The template skeleton:
index.phpand<jdoc:include>tags assemble the head, the component, the modules, and the messages into one page that the browser turns into the DOM. - Template overrides: the correct way to change Joomla's markup, kept in your template so updates never wipe it.
- Clean content tools: the editor, the Custom module, modern native elements, and per-group Text Filters keep article HTML consistent and safe.
- Light, accessible, and findable: a small DOM, helpers and forms that produce correct markup, real alt text and labels, and good metadata keep the site fast and easy to read.
Most HTML problems on a Joomla site are not hard. They are markup edited in a core file and lost on update, a layout built from meaningless <div> tags, headings chosen for their size, messy HTML pasted from a word processor, or a DOM so large the page drags. Each one is quick to fix once you know where Joomla expects custom markup to live and how it builds a page.
If your site outputs messy markup, fails an accessibility check, loses your layout changes after every update, or feels heavier than it should, the cause and the cure usually sit in how the HTML is structured and where it is changed. That is exactly the kind of Joomla template and front-end work I help with, so a site stays well-structured, accessible, fast, and easy to maintain for years.
Back to top

Peter is a Joomla specialist and a Linux admin for fast, secure and scalable websites.
Frequently Asked Questions
HTML is the foundation of every Joomla page. It defines the structure and meaning of your content, including headings, paragraphs, lists, images, tables, forms, and navigation. Joomla generates HTML on the server using PHP, after which CSS controls the design and JavaScript adds interactivity. Clean HTML improves SEO, accessibility, and page performance.
Joomla creates HTML by combining content, modules, menus, components, and a template. PHP retrieves data from the database, the template assembles the page using jdoc:include tags, and the final HTML is sent to the browser. Search engines and screen readers only see this generated HTML, not the underlying PHP code.
Each technology has a specific role:
- HTML provides the structure and content.
- CSS controls the visual appearance.
- JavaScript adds interactive behaviour.
Keeping these responsibilities separate makes Joomla websites easier to maintain, faster to load, and more accessible.
Template overrides let you customise the HTML output of Joomla components and modules without modifying the Joomla core. Because overrides survive Joomla updates, they are the recommended way to change markup, improve accessibility, optimise SEO, or adapt the design of your website.
Semantic HTML uses elements such as headings, lists, navigation, articles, and forms to describe the purpose of content. Search engines understand page structure more accurately, while screen readers can navigate content more effectively. Well-structured HTML also helps AI search engines and large language models interpret your pages.
Joomla includes several tools for generating clean, maintainable HTML:
- Template files define the page structure.
jdoc:includeinserts components, modules, and metadata.- Template overrides customise output safely.
HTMLHelpercreates common HTML elements consistently.- Joomla Forms generate secure, accessible forms with minimal code.
Together, these tools help developers create fast, standards-compliant, SEO-friendly Joomla websites that remain easy to maintain.


