HTML Guides for fragment
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
In a URL, the # character has a special role: it acts as the delimiter that separates the main URL from the fragment identifier. The fragment typically points to a specific section or element within the target document, often corresponding to an element’s id attribute. Because # serves this reserved purpose, it cannot appear more than once in its raw form within a URL. When the validator encounters something like ##pricing or section#one#two, it flags the extra # characters as illegal.
This issue usually arises from one of these common scenarios:
- Typos — accidentally typing ## instead of #.
- String concatenation bugs — building URLs programmatically where a # is included both in the base URL and prepended to the fragment value.
- Copy-paste errors — duplicating the # when copying URLs from browser address bars or other sources.
- Literal # intended in fragment — if you genuinely need a # symbol within the fragment text, it must be percent-encoded as %23.
This matters because browsers may handle malformed URLs inconsistently. Some browsers silently strip the extra #, while others may fail to navigate to the intended fragment. Malformed URLs also cause problems for assistive technologies, web crawlers, and any tooling that parses links. Keeping your URLs well-formed ensures predictable behavior across all user agents and complies with the URL Standard and HTML specification.
Examples
Incorrect: duplicate # in the URL
The double ## makes the fragment identifier invalid:
<a href="https://example.com/faqs##pricing">Pricing</a>
Correct: single # delimiter
Remove the extra # so that pricing is the fragment:
<a href="https://example.com/faqs#pricing">Pricing</a>
Incorrect: extra # inside the fragment
Here, the fragment portion overview#details contains a raw #, which is not allowed:
<a href="/docs#overview#details">Details</a>
Correct: percent-encode the literal #
If you truly need a # as part of the fragment text, encode it as %23:
<a href="/docs#overview%23details">Details</a>
In most cases though, this pattern suggests the URL structure should be rethought. A cleaner approach is to link directly to the intended fragment:
<a href="/docs#details">Details</a>
Incorrect: programmatic concatenation error
A common bug in templates or JavaScript is prepending # when the variable already includes it:
<!-- If defined as defined as fragment = "#pricing", this produces a double ## -->
<a href="https://example.com/faqs#pricing">Pricing</a>
Correct: ensure only one # is present
Make sure either the base URL or the fragment variable includes the #, but not both:
<a href="https://example.com/faqs#pricing">Pricing</a>
Fragment-only links
Fragment-only links (links to sections within the same page) follow the same rule — only one #:
<!-- Incorrect -->
<a href="##contact">Contact Us</a>
<!-- Correct -->
<a href="#contact">Contact Us</a>
A data: URI embeds resource content directly in a URL rather than pointing to an external file. It follows the format data:[<mediatype>][;base64],<data>. RFC 2397, which governs this scheme, explicitly states that fragment identifiers (the # character followed by a fragment name) are not valid in data: URIs.
This issue most commonly arises when developers try to reference a specific element inside an embedded SVG — for example, a particular <symbol> or element with an id — by appending a fragment like #icon-name to a data: URI. While fragments work in standard URLs (e.g., icons.svg#home), the data: URI scheme simply doesn’t support them.
Why It Matters
- Standards compliance: Browsers may handle invalid data: URIs inconsistently. Some may silently ignore the fragment, while others may fail to render the image entirely.
- Portability: Code that relies on non-standard behavior in one browser may break in another or in a future update.
- Accessibility and tooling: Validators, linters, and assistive technologies expect well-formed URIs. An invalid URI can cause unexpected issues down the chain.
How to Fix It
You have several options depending on your use case:
- Remove the fragment from the data: URI. If the embedded content is a complete, self-contained image, it doesn’t need a fragment reference.
- Inline the SVG directly into the HTML document. This lets you reference internal id values with standard fragment syntax using <use> elements.
- Use an external file instead of a data: URI. Standard URLs like icons.svg#home fully support fragment identifiers.
- Encode the full, standalone SVG into the data: URI so that it contains only the content you need, eliminating the need for a fragment reference.
Examples
❌ Incorrect: Fragment in a data: URI
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Csymbol id='icon'%3E%3Ccircle cx='10' cy='10' r='10'/%3E%3C/symbol%3E%3C/svg%3E#icon"
alt="Icon">
The #icon fragment at the end of the data: URI violates RFC 2397 and triggers the validation error.
✅ Correct: Self-contained SVG in a data: URI (no fragment)
Embed only the content you need directly, without wrapping it in a <symbol> or referencing a fragment:
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='10'/%3E%3C/svg%3E"
alt="Icon">
✅ Correct: External SVG file with a fragment
Move the SVG to a separate file and reference the specific symbol using a standard URL fragment:
<img src="icons.svg#icon" alt="Icon">
✅ Correct: Inline SVG with <use> referencing an internal id
If you need to reference individual symbols from a sprite, inline the SVG and use fragment references within the same document:
<svg xmlns="http://www.w3.org/2000/svg" hidden>
<symbol id="icon-home" viewBox="0 0 20 20">
<path d="M10 2 L2 10 L4 10 L4 18 L16 18 L16 10 L18 10 Z"/>
</symbol>
</svg>
<svg width="20" height="20" aria-hidden="true">
<use href="#icon-home"></use>
</svg>
This approach gives you full control over individual icons without needing data: URIs at all, and it’s the most flexible option for icon systems.
URLs follow a strict syntax defined by RFC 3986 and the URL Living Standard. Only a specific set of characters are allowed to appear unencoded in a URL. Curly braces ({ and }) are among the characters that fall outside this permitted set. When the W3C validator encounters a raw { or } in an href value, it reports the error: Bad value for attribute “href” on element “a”: Illegal character in fragment.
This issue commonly arises in a few scenarios:
- Server-side or client-side template placeholders left unresolved in the rendered HTML (e.g., {id}, {{slug}}).
- URLs copied from API documentation that use curly braces to indicate variable segments (e.g., /users/{userId}/posts).
- Malformed or auto-generated URLs where curly braces were included by mistake.
Why This Matters
Standards compliance: The HTML specification requires that href values conform to valid URL syntax. Curly braces violate this requirement, producing invalid HTML.
Browser inconsistency: While most modern browsers will attempt to handle URLs with illegal characters by silently encoding them, this behavior is not guaranteed across all browsers or versions. Relying on browser error correction can lead to unpredictable results.
Accessibility and interoperability: Assistive technologies, web crawlers, and other tools that parse HTML may not handle illegal URL characters gracefully. Invalid URLs can break link extraction, bookmarking, and sharing functionality.
Debugging difficulty: If curly braces appear in your rendered HTML, it often signals that a template variable was not properly resolved, which may point to a deeper bug in your application logic.
How to Fix It
The fix depends on why the curly braces are there:
-
If the curly braces are literal characters that should be part of the URL, replace them with their percent-encoded equivalents: { becomes %7B and } becomes %7D.
-
If the curly braces are template placeholders (e.g., {userId}), ensure your server-side or client-side code resolves them to actual values before the HTML is sent to the browser. The rendered HTML should never contain unresolved template variables.
-
If the curly braces were included by mistake, simply remove them.
Examples
Incorrect: Raw curly braces in href
<a href="https://example.com/api/users/{userId}/profile">View Profile</a>
This triggers the validation error because { and } are illegal URL characters.
Correct: Percent-encoded curly braces
If the curly braces are meant to be literal parts of the URL:
<a href="https://example.com/api/users/%7BuserId%7D/profile">View Profile</a>
Correct: Resolved template variable
If the curly braces were template placeholders, ensure your templating engine resolves them before rendering. The final HTML should look like:
<a href="https://example.com/api/users/42/profile">View Profile</a>
Incorrect: Curly braces in a fragment identifier
<a href="https://example.com/docs#section-{name}">Jump to Section</a>
Correct: Percent-encoded fragment
<a href="https://example.com/docs#section-%7Bname%7D">Jump to Section</a>
Incorrect: Curly braces in query parameters
<a href="https://example.com/search?filter={active}">Active Items</a>
Correct: Percent-encoded query parameter
<a href="https://example.com/search?filter=%7Bactive%7D">Active Items</a>
Using JavaScript for dynamic URLs
If you need to build URLs dynamically with values that might contain special characters, use encodeURIComponent() in JavaScript rather than inserting raw values into href attributes:
<a id="dynamic-link" href="https://example.com">Dynamic Link</a>
<script>
var value = "{some-value}";
var link = document.getElementById("dynamic-link");
link.href = "https://example.com/path?param=" + encodeURIComponent(value);
</script>
This ensures that any special characters, including curly braces, are automatically percent-encoded in the resulting URL.
A URL fragment identifier is the part of a URL that follows the # symbol, typically used to link to a specific section within a page. The URL specification (RFC 3986 and the WHATWG URL Standard) defines a strict set of characters that are permitted in fragments. The > character (greater-than sign) is among those that are not allowed to appear literally. When the W3C HTML Validator encounters > inside an href value — whether in the fragment or elsewhere in the URL — it raises this error.
In most cases, the > character appears in a URL by accident — for example, from a copy-paste error, a typo where the closing > of the tag accidentally ends up inside the attribute value, or a malformed template expression. Less commonly, a developer may genuinely need the > character as part of the URL content.
Why This Matters
- Broken links: Browsers may interpret the > as the end of the HTML tag or handle the URL unpredictably, leading to broken navigation.
- Standards compliance: Invalid URLs violate both the HTML specification and URL syntax standards, causing validation failures.
- Accessibility: Screen readers and other assistive technologies rely on well-formed markup. A malformed href can confuse these tools and prevent users from reaching the intended destination.
- Interoperability: While some browsers may silently correct or ignore the invalid character, others may not. Valid URLs guarantee consistent behavior everywhere.
How to Fix It
- If the > is a typo or copy-paste error, simply remove it from the href value. This is the most common scenario.
- If the > is intentionally part of the fragment or URL, replace it with its percent-encoded equivalent: %3E.
- Review your templates or CMS output — this error often originates from template engines or content management systems that inject malformed values into href attributes.
Examples
Accidental > in the URL path
A common mistake is accidentally including the tag’s closing > inside the attribute value:
<!-- ❌ Invalid: ">" is not allowed in the URL -->
<a href="/page.php>">Read more</a>
Remove the stray >:
<!-- ✅ Valid: clean URL without illegal character -->
<a href="/page.php">Read more</a>
Illegal > in a fragment identifier
The > can also appear inside the fragment portion of the URL:
<!-- ❌ Invalid: ">" in the fragment -->
<a href="/docs#section->overview">Go to overview</a>
If the > is unintentional, remove it:
<!-- ✅ Valid: fragment without illegal character -->
<a href="/docs#section-overview">Go to overview</a>
If the > is genuinely needed in the fragment, percent-encode it:
<!-- ✅ Valid: ">" encoded as %3E -->
<a href="/docs#section-%3Eoverview">Go to overview</a>
Query string or path containing >
The same rule applies outside of fragments. If > appears anywhere in the URL, encode it:
<!-- ❌ Invalid: ">" in query parameter -->
<a href="/search?filter=price>100">Expensive items</a>
<!-- ✅ Valid: ">" percent-encoded as %3E -->
<a href="/search?filter=price%3E100">Expensive items</a>
Template output errors
If you are using a server-side template or JavaScript framework, ensure that dynamic values inserted into href are properly URL-encoded. For example, in a template that generates links:
<!-- ❌ Invalid: unencoded dynamic value -->
<a href="/results#filter=>50">View results</a>
<!-- ✅ Valid: properly encoded value -->
<a href="/results#filter=%3E50">View results</a>
Most server-side languages provide built-in URL encoding functions (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, urllib.parse.quote() in Python) that will handle this automatically. Always use these functions when inserting dynamic content into URLs.
Ready to validate your sites?
Start your free trial today.