Headings: Semantics, Fluidity, and Styling — Oh My! | CSS-Tricks
These articles are AI-generated summaries. Please check the original sources for full details.
Headings: Semantics, Fluidity, and Styling — Oh My!
This article addresses best practices for structuring and styling HTML headings, focusing on semantic correctness, responsive typography, and emerging CSS features. It emphasizes accessibility, usability, and cross-browser compatibility in modern web development.
Semantic Structure of Headings
Proper placement of <h1> and other heading elements is critical for accessibility and semantic HTML. The <header> element should not contain the main page heading (<h1>) if it’s part of the <main> content. Key guidelines include:
-
Avoid placing
<h1>in the<header>unless it’s the site-wide title (not the page-specific heading). This prevents confusion for screen readers and users navigating via skip links. -
Nesting
<header>inside<main>loses the semantic role of<header>(which maps torole="banner"), reducing clarity for assistive technologies. -
Correct structure places
<h1>directly within<main>, separate from<header>:<header> <!-- Site-wide header content --> </header> <main> <h1>Page heading</h1> <!-- Main content --> </main>Impact: Ensures predictable navigation for screen readers and maintains semantic landmarks.
Fluid Typography with clamp()
Responsive typography requires balancing scalability and accessibility. The clamp() function allows font sizes to scale between a minimum and maximum value based on viewport width. However, improper use can break accessibility when users zoom.
-
Basic
clamp()usage:.article-heading { font-size: clamp(18px, 4vw, 36px); }- Min:
18px(smallest font size). - Ideal:
4vw(viewport width-based scaling). - Max:
36px(largest font size).
- Min:
-
Accessibility issue: If the “ideal” value uses
vw, zooming disrupts the scaling. To fix this, useremfor the ideal value, calculated based on character count per line:.article-heading { --heading-smallest: 2.5rem; --heading-largest: 5rem; --m: calc((var(--heading-largest) - var(--heading-smallest)) / (30 - 20)); font-size: clamp(var(--heading-smallest), var(--m) * 100vw, var(--heading-largest)); }Note: This works in Chrome and Safari but not Firefox due to unit division in
calc().
Emerging CSS Features: :heading Pseudo-Class
A new experimental CSS feature in Firefox Nightly allows targeting headings more efficiently:
-
:headingpseudo-class selects all heading elements (<h1>to<h6>)::heading { color: #333; } -
:heading(2, 3)targets only<h2>and<h3>::heading(2, 3) { font-weight: bold; }Advantages:
- Cleaner syntax than
h1, h2, h3, h4, h5, h6. - Automatically ignores non-heading elements with ARIA roles or attributes.
Limitation: Currently only available in Firefox Nightly (not widely supported).
- Cleaner syntax than
Working Example
Semantic Structure
<header>
<nav>Site Navigation</nav>
</header>
<main>
<h1>Welcome to Our Blog</h1>
<article>
<h2>Responsive Typography Tips</h2>
<p>...</p>
</article>
</main>
Fluid Typography
.article-heading {
--heading-smallest: 1.5rem;
--heading-largest: 3rem;
--m: calc((var(--heading-largest) - var(--heading-smallest)) / (40 - 20));
font-size: clamp(var(--heading-smallest), var(--m) * 100vw, var(--heading-largest));
}
Recommendations
- Semantic Structure:
- Always place
<h1>inside<main>, not in<header>. - Use
<header>only for introductory content, not for page headings.
- Always place
- Fluid Typography:
- Prefer
removervwfor the middle value inclamp()to ensure zoom accessibility. - Test across browsers, as unit-based calculations may fail in Firefox.
- Prefer
- New Features:
- Use
:headingfor cleaner CSS when targeting multiple headings. - Monitor browser support for
:headingand use fallbacks where necessary.
- Use
Reference: Headings: Semantics, Fluidity, and Styling — Oh My! | CSS-Tricks
Continue reading
Next article
Reverse-Engineering a Dockerfile from an Existing Docker Image
Related Content
CSS Evolution: New Features and Future Directions
CSS introduces new features like 'IF' functions, anchor positioning, and scroll-driven animations, revolutionizing web development with improved performance and accessibility.
Interop 2026: Major CSS Features Gain Cross-Browser Consistency
Interop 2026 initiative ensures consistent cross-browser support for advanced CSS features like Anchor Positioning, Container Style Queries, and Scroll-Driven Animations.
Building Scrollytelling Experiences with CSS Scroll-Snap Events and Scroll-Driven Animation
Lee Meyer demonstrates how to utilize emergent Chromium-based scroll-snap events and scroll-state queries to create complex, interactive scrollytelling experiences.