How to properly create SEO-friendly links?
When people talk about SEO, they often mention <title> tags, <h1> structure, performance, sitemap… But they often forget one of the fundamental pillars: links.
Every link is a strong signal to Google — it indicates what’s important, what’s related, and what should be explored. But only if it’s coded properly…
Unfortunately, most developers make the same mistakes: poor HTML structure, polluted anchor text, improper use of attributes. While the result might look right visually, semantically it’s often unclear for search engine bots.
This article will teach you how to create clean, accessible, SEO-friendly links.
Link anchor text: SEO Signal #1
The visible text of a link — the anchor — is the first thing Google reads to understand what the link is about. It helps the bot know what’s behind the link without crawling the target page.
A good anchor is:
- Descriptive: explains what users will find
- Natural: no keyword stuffing
- Relevant: matches the destination page content
Examples:
✅ List of chocolate-based recipes
❌ Click here
Stop polluting anchor text with useless tags!
A common mistake is wrapping links with unnecessary tags like <div>
, <span>
, or poorly handled <img>
. The most common misuse appears in cards, like this:
<a href="...">
<article class="card">
<picture class="card--thumbnail"> ... </picture>
<h3 class="card--title">The health benefits of chocolate</h3>
<p class="card--resume">
Chocolate brings happiness, reduces stress, anxiety, and even depression.
</p>
</article>
</a>
Issue 1: Mixing block and inline elements
Historically, the <a>
element is inline
by default, while <article>
, <h3>
, and <p>
are block
elements.
Even though HTML5 allows more flexibility, mixing block and inline can cause:
- Unexpected CSS rendering
- Broken behavior on some devices
- Accessibility issues and confusion for screen readers
To maintain a correct HTML structure in your pages, be sure to never put a block
inside an inline
.
For example, let's say you want to put a link inside an <h3>
. We would naturally write this first example rather than the second, since hh3> is a block type, <a>
is an inline type, so <a>
can not contain an <h3>
:
<!-- ✅ Good -->
<h3><a href="...">Why is chocolate so good?</a></h3>
<!-- ❌ Bad -->
<a href="..."><h3>Why is chocolate so good?</h3></a>
You might argue this pollutes the <h3> with link text, but semantically it’s acceptable: you can place an <a> inside an <h3>, not the other way around.
You might argue this pollutes the <h3>
with link text, but semantically it’s acceptable: you can place an <a>
inside an <h3>
, not the other way around.
In the XHTML 1.0 era, long before HTML5, it was customary to validate its inline in the W3C's Markup Validation Service. At that time, a block within an inline would have generated this error:
Issue 2: Polluted anchor text
Google analyzes the raw text inside the <a> tag. If that text is broken up by other tags or wrapped in visual-only elements, Google may misinterpret it or consider it less important.
A clear, clean, noise-free anchor sends a stronger signal.
<!-- ✅ Good -->
<a href="...">The health benefits of chocolate</a>
<!-- ❌ Bad -->
<a href="...">
<div>
<span><img src="icon.svg"> The health benefits of chocolate</span>
</div>
</a>
A clean anchor means a clean HTML structure.
The ultimate hack: Making entire blocks clickable
Often, we want an entire card to be clickable. But instead of wrapping the whole thing in an <a>
, there’s a better solution.
Clean card implementation:
<article class="card">
<picture class="card--thumbnail"> ... </picture>
<h3 class="card--title">
<a href="...">The health benefits of chocolate</a>
</h3>
<p class="card--resume">
Chocolate brings happiness, reduces stress, anxiety, and even depression.
</p>
</article>
To make the whole card clickable, use a CSS pseudo-element:
.card {
position: relative;
}
.card a::after {
content: "";
position: absolute;
z-index: 1;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
Voilà! The card is now fully clickable while keeping the HTML clean for SEO and accessibility.
What if I need a second link on the card?
You may want to add a secondary link on a card, for example, a tag or category. In this case, just position the secondary link as relative
and adjust z-index
if needed, so it isn’t hidden by the main pseudo-element.
How to link an image properly
When a link contains only an image, there’s no text anchor. Google can't see images; it relies on the alt
attribute to understand what the image is.
So that alt
acts as your anchor.
Since <img>
is an inline element, it’s perfectly valid inside a link:
<a href="...">
<img src="..." alt="Steaming hot chocolate" />
</a>
As a fallback, Google can use the
title
attribute as anchor text if the<a>
element is for some reason empty.
So, if needed, the title
attribute on <a>
can also act as fallback anchor text:
<a href="..." title="Homemade hot chocolate recipe">
<img src="..." alt="Steaming hot chocolate" />
</a>
If the anchor and image description are the same, the title
attribute is unnecessary.
If the link has no anchor text or image, title
attribute will be used as the anchor.
Going Further: Hiding Useless Anchors
Sometimes you might want to display links like "Read more", "View article", etc., which don’t add SEO value but help user experience.
You can hide these anchors from the HTML but keep them visually present using a CSS pseudo-element:
<a href="..." title="All chocolate-related articles"></a>
a::after {
content: "Read more";
}
Voilà! We display a useful label without polluting the anchor text for SEO.
TLDR: Golden Rules for SEO-Friendly Links
- Clear, descriptive, non-polluted anchor text
- No
<div>
or complex layout inside<a>
tags - Use CSS for extended clickable areas
- For image links, use meaningful
alt
text - Use
title
attribute if there's no visible anchor or image