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.

Robot explodes after reading bad code

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:

Error generated when using a block element within an inline element for an XHTML 1.0 page
Error generated when using a block element within an inline element for an XHTML 1.0 page  —  Crédits : W3C

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.

— Google Search Central, Link best practices for Google

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
  • SEO
  • Web Development
  • Best practices
  • Link Building
  • Code Quality
  • HTML structure
Jerome Musialak

Jerome Musialak

CEO @ Enodo

A passionate developer since the age of 11, Jérôme cut his teeth at MinuteBuzz and then as CTO of MeltyGroup, where he managed the technical infrastructure of around thirty high-traffic sites including Virgin Radio, L'Étudiant, ... and the group's media. With this experience and aware of the recurring challenges faced by companies in creating and effectively distributing their content, he founded Enodo (from the Latin "to untie knots") with the mission of simplifying the digital ecosystem. An expert in performance optimization and high-availability architecture, he puts his obsession with technical details to the service of business challenges to build reliable systems that allow everyone to sleep soundly.

On the same subject