HTML Style Guide
Table of Contents
- HTML Style Rules
- HTML Formatting Rules
- Modern HTML Features
- Accessibility Guidelines
- SEO Optimization
- Performance
- Semantic HTML
HTML Style Rules
Document Type
Use HTML5.
Always declare the document type as the first line in your document.
<!DOCTYPE html>
Protocol
Use HTTPS for embedded resources where possible.
Always use HTTPS for scripts unless each file is available via HTTPS.
// Wrong
<script src="http://api.pelagornis.com/..."></script>
// RIGHT
<script src="https://api.pelagornis.com/..."></script>
Close All HTML Elements
In HTML, you do not have to close all elements.
we strongly recommend closing all HTML elements.
// Wrong
<section>
<p>Hello, Pelagornis.</p>
<p>Pelagornis StyleGuide.</p>
</section>
// Right
<section>
<p>Hello, Pelagornis.</p>
<p>Pelagornis StyleGuide.</p>
</section>
Spaces and Equal Signs
Do not prefer spaces around HTML equals.
Without spaces, it’s easier to read, and you can better group an entity.
// Wrong
<a href="/signin">Sign In</a>
// Right
<a href="/signin">Sign In</a>
Semantics
Use the appropriate HTML.
The purposeful use of HTML can have a good impact on accessibility, reusability, and code efficiency.
// Wrong
<div onclick="navigateToSemantics();">Semantics</div>
// Right
<a href="/semantics">Semantics</a>
Entity References
Do not use entity references.
In HTML, entity references are unnecessary except for characters with special meanings (e.g., <
and &
) and control characters or “invisible” characters (e.g., indistinguishable spaces).
// Wrong The symbol for classification is “§”. // Right The
symbol for classification is "§".
type
Attributes
Omit type
attributes for style sheets and scripts.
Do not use type attributes for style sheets (unless not using CSS) and scripts (unless not using JavaScript).
// Wrong
<link rel="stylesheet" href="/styles.css" type="text/css" />
// Right
<link rel="stylesheet" href="/styles.css" />
HTML Formatting Rules
Indentation
Indent by 2 spaces at a time.
Don’t use tabs or mix tabs and spaces for indentation.
<ul>
<li>Home</li>
<li>Opensource</li>
</ul>
Capitalization
Use only lowercase.
// Wrong
<a href="/">Home</a>
// Right
<a href="/">Home</a>
Trailing Whitespace
Remove trailing white spaces.
// Wrong
<p>Hello, World_</p>
// Right
<p>Hello, World</p>
General Formatting
Use a new line for every block, list, or table element, and indent every such child element.
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
HTML Quotation Marks
we recommend quoting attribute values.
// Wrong
<a class="sign-in-button">Sign In</a>
// Right
<a class="sign-in-button">Sign In</a>
Modern HTML Features
HTML5 Semantic Elements
Use semantic HTML5 elements for better structure and accessibility.
<!-- Document structure -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Page Title</title>
</head>
<body>
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header>
<h1>Article Title</h1>
<time datetime="2024-01-15">January 15, 2024</time>
</header>
<section>
<h2>Section Title</h2>
<p>Article content...</p>
</section>
</article>
<aside>
<h3>Related Links</h3>
<ul>
<li><a href="/related1">Related Article 1</a></li>
<li><a href="/related2">Related Article 2</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2024 Company Name. All rights reserved.</p>
</footer>
</body>
</html>
Form Elements and Validation
Use modern form elements with proper validation.
<form novalidate>
<fieldset>
<legend>User Information</legend>
<div class="form-group">
<label for="email">Email Address</label>
<input
type="email"
id="email"
name="email"
required
autocomplete="email"
aria-describedby="email-error"
/>
<div id="email-error" class="error-message" role="alert"></div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
id="password"
name="password"
required
minlength="8"
autocomplete="new-password"
aria-describedby="password-help"
/>
<div id="password-help" class="help-text">
Password must be at least 8 characters long.
</div>
</div>
<div class="form-group">
<label for="age">Age</label>
<input
type="number"
id="age"
name="age"
min="13"
max="120"
aria-describedby="age-help"
/>
<div id="age-help" class="help-text">
You must be at least 13 years old.
</div>
</div>
<div class="form-group">
<label for="country">Country</label>
<select id="country" name="country" required>
<option value="">Select a country</option>
<option value="us">United States</option>
<option value="ca">Canada</option>
<option value="uk">United Kingdom</option>
</select>
</div>
<div class="form-group">
<fieldset>
<legend>Newsletter Subscription</legend>
<input type="radio" id="newsletter-yes" name="newsletter" value="yes" />
<label for="newsletter-yes">Yes, subscribe me</label>
<input type="radio" id="newsletter-no" name="newsletter" value="no" />
<label for="newsletter-no">No, thanks</label>
</fieldset>
</div>
<div class="form-group">
<input type="checkbox" id="terms" name="terms" required />
<label for="terms">
I agree to the <a href="/terms" target="_blank">Terms of Service</a>
</label>
</div>
<button type="submit">Create Account</button>
</fieldset>
</form>
Media Elements
Use modern media elements with proper attributes.
<!-- Responsive images -->
<picture>
<source media="(min-width: 800px)" srcset="large-image.jpg" />
<source media="(min-width: 400px)" srcset="medium-image.jpg" />
<img src="small-image.jpg" alt="Descriptive alt text" loading="lazy" />
</picture>
<!-- Video with multiple sources -->
<video controls preload="metadata" poster="video-poster.jpg">
<source src="video.mp4" type="video/mp4" />
<source src="video.webm" type="video/webm" />
<track kind="captions" src="captions.vtt" srclang="en" label="English" />
<p>Your browser doesn't support HTML5 video.</p>
</video>
<!-- Audio with multiple sources -->
<audio controls preload="metadata">
<source src="audio.mp3" type="audio/mpeg" />
<source src="audio.ogg" type="audio/ogg" />
<p>Your browser doesn't support HTML5 audio.</p>
</audio>
Accessibility Guidelines
ARIA Labels and Roles
Use ARIA attributes to improve accessibility.
<!-- Navigation with ARIA -->
<nav role="navigation" aria-label="Main 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>
<!-- Button with ARIA -->
<button
type="button"
aria-expanded="false"
aria-controls="menu"
aria-label="Toggle navigation menu"
>
<span class="hamburger-icon" aria-hidden="true">☰</span>
Menu
</button>
<!-- Modal dialog -->
<div
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
<h2 id="modal-title">Confirm Action</h2>
<p id="modal-description">Are you sure you want to delete this item?</p>
<button type="button" aria-label="Close dialog">×</button>
</div>
<!-- Form with ARIA -->
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
id="username"
name="username"
required
aria-describedby="username-error username-help"
aria-invalid="false"
/>
<div id="username-help" class="help-text">
Username must be 3-20 characters long.
</div>
<div id="username-error" class="error-message" role="alert"></div>
</div>
Focus Management
Implement proper focus management for keyboard navigation.
<!-- Skip links -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<!-- Focusable elements -->
<button type="button" tabindex="0">Focusable Button</button>
<input type="text" tabindex="0" placeholder="Focusable Input" />
<a href="/link" tabindex="0">Focusable Link</a>
<!-- Non-focusable elements -->
<div tabindex="-1">Non-focusable div</div>
<span tabindex="-1">Non-focusable span</span>
Screen Reader Support
Provide proper support for screen readers.
<!-- Hidden text for screen readers -->
<button type="button">
<span class="icon" aria-hidden="true">🔍</span>
<span class="sr-only">Search</span>
</button>
<!-- Live regions for dynamic content -->
<div aria-live="polite" aria-atomic="true" id="status-messages"></div>
<!-- Descriptive text -->
<img
src="chart.jpg"
alt="Sales increased by 25% from Q1 to Q2, reaching $2.5M in revenue"
/>
<!-- Complex images with long descriptions -->
<img
src="infographic.jpg"
alt="Detailed infographic showing market trends"
longdesc="infographic-description.html"
/>
SEO Optimization
Meta Tags
Use comprehensive meta tags for SEO.
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Primary meta tags -->
<title>Page Title - Company Name</title>
<meta name="title" content="Page Title - Company Name" />
<meta
name="description"
content="Brief description of the page content (150-160 characters)"
/>
<meta name="keywords" content="keyword1, keyword2, keyword3" />
<meta name="author" content="Author Name" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://example.com/page/" />
<meta property="og:title" content="Page Title - Company Name" />
<meta
property="og:description"
content="Brief description of the page content"
/>
<meta property="og:image" content="https://example.com/image.jpg" />
<meta property="og:site_name" content="Company Name" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://example.com/page/" />
<meta property="twitter:title" content="Page Title - Company Name" />
<meta
property="twitter:description"
content="Brief description of the page content"
/>
<meta property="twitter:image" content="https://example.com/image.jpg" />
<!-- Additional SEO -->
<meta name="robots" content="index, follow" />
<meta name="googlebot" content="index, follow" />
<link rel="canonical" href="https://example.com/page/" />
<link rel="alternate" hreflang="en" href="https://example.com/page/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/page/" />
</head>
Structured Data
Implement structured data for better search results.
<!-- JSON-LD structured data -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Company Name",
"url": "https://example.com",
"logo": "https://example.com/logo.png",
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+1-555-123-4567",
"contactType": "customer service"
},
"sameAs": [
"https://facebook.com/company",
"https://twitter.com/company",
"https://linkedin.com/company/company"
]
}
</script>
<!-- Microdata -->
<article itemscope itemtype="https://schema.org/Article">
<h1 itemprop="headline">Article Title</h1>
<div itemprop="author" itemscope itemtype="https://schema.org/Person">
<span itemprop="name">Author Name</span>
</div>
<time itemprop="datePublished" datetime="2024-01-15">January 15, 2024</time>
<div itemprop="articleBody">
<p>Article content...</p>
</div>
</article>
Performance
Resource Loading
Optimize resource loading for better performance.
<!-- Preload critical resources -->
<link
rel="preload"
href="/fonts/main-font.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<link rel="preload" href="/css/critical.css" as="style" />
<link rel="preload" href="/js/critical.js" as="script" />
<!-- Prefetch resources for next page -->
<link rel="prefetch" href="/next-page.html" />
<link rel="prefetch" href="/images/hero-image.jpg" />
<!-- DNS prefetch for external domains -->
<link rel="dns-prefetch" href="//fonts.googleapis.com" />
<link rel="dns-prefetch" href="//api.example.com" />
<!-- Lazy loading for images -->
<img src="image.jpg" alt="Description" loading="lazy" decoding="async" />
<!-- Defer non-critical scripts -->
<script src="/js/analytics.js" defer></script>
<script src="/js/chat-widget.js" defer></script>
<!-- Async for independent scripts -->
<script src="/js/third-party-widget.js" async></script>
Critical CSS
Inline critical CSS for faster rendering.
<head>
<style>
/* Critical CSS for above-the-fold content */
body {
margin: 0;
font-family: Arial, sans-serif;
}
.header {
background: #333;
color: white;
padding: 1rem;
}
.hero {
background: #f0f0f0;
padding: 2rem;
text-align: center;
}
</style>
<!-- Load non-critical CSS asynchronously -->
<link
rel="preload"
href="/css/main.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
/>
<noscript><link rel="stylesheet" href="/css/main.css" /></noscript>
</head>
Semantic HTML
Content Structure
Use semantic elements to structure content properly.
<!-- Article structure -->
<article>
<header>
<h1>Article Title</h1>
<div class="article-meta">
<address class="author">
By <a href="/author/john-doe">John Doe</a>
</address>
<time datetime="2024-01-15T10:30:00Z">January 15, 2024 at 10:30 AM</time>
</div>
</header>
<div class="article-content">
<p>Article introduction...</p>
<section>
<h2>Section Title</h2>
<p>Section content...</p>
<figure>
<img src="image.jpg" alt="Descriptive alt text" />
<figcaption>Image caption explaining the image</figcaption>
</figure>
</section>
<section>
<h2>Another Section</h2>
<p>More content...</p>
<blockquote cite="https://example.com/source">
<p>This is a quote from an external source.</p>
<footer>
<cite>Source Name</cite>
</footer>
</blockquote>
</section>
</div>
<footer>
<div class="article-tags">
<span>Tags:</span>
<ul>
<li><a href="/tag/web-development">Web Development</a></li>
<li><a href="/tag/html">HTML</a></li>
</ul>
</div>
</footer>
</article>
Navigation Structure
Create accessible navigation structures.
<!-- Breadcrumb navigation -->
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/category">Category</a></li>
<li aria-current="page">Current Page</li>
</ol>
</nav>
<!-- Main navigation -->
<nav role="navigation" aria-label="Main navigation">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li>
<a href="/products" aria-expanded="false" aria-haspopup="true">
Products
</a>
<ul>
<li><a href="/products/software">Software</a></li>
<li><a href="/products/hardware">Hardware</a></li>
</ul>
</li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
<!-- Pagination -->
<nav aria-label="Pagination">
<ul>
<li><a href="/page/1" aria-label="Previous page">«</a></li>
<li><a href="/page/1">1</a></li>
<li><a href="/page/2" aria-current="page">2</a></li>
<li><a href="/page/3">3</a></li>
<li><a href="/page/3" aria-label="Next page">»</a></li>
</ul>
</nav>