nextjs - 💡(How to fix) Fix Link component creates poor SEO anchor text by including image markup alongside text content [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#85454Fetched 2026-04-08 02:15:28
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
labeled ×2closed ×1commented ×1issue_type_added ×1

Fix Action

Code Example

import Link from 'next/link';
import Image from 'next/image';

export default function CardComponent() {
  const data = {
    url: '/walk-in-dining',
    title: 'Walk-in Dining',
    image: 'https://example.com/dining.png'
  };

  return (
    <Link key={index} href={data.url}>
      <div className="card">
        <span className="title">
          {data.title}
        </span>
        <div className="image-wrapper">
          <Image
            src={data.image}
            width={88}
            height={56}
            alt={data.title}
          />
        </div>
      </div>
    </Link>
  );
}

---

<a href="/walk-in-dining">
  <div class="card">
    <span class="title">Walk-in Dining</span>
    <div class="image-wrapper">
      <img alt="Walk-in Dining" loading="lazy" decoding="async" ... />
    </div>
  </div>
</a>

---

Walk-in Dining<img alt="Walk-in Dining" loading="lazy" decoding="async" data-nimg="intrinsic" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%" src="https://example.com/dining.png?format=auto&quality=80"/>


**Expected Behavior**
The anchor text for SEO should only be: Walk-in Dining
The image should be part of the clickable area but NOT included in the semantic anchor text used by search engines for ranking and context.

**1. Attempted Workarounds**

Using legacyBehavior (deprecated) - Works but not a long-term solution:

---

Correct anchor text
⚠️ Uses deprecated API

**2. Nested anchor tags - Invalid HTML:**

---

Creates nested <a> tags (invalid HTML)
Console errors

**3. Separate Link for text only - Loses clickable card:**

---

Correct anchor text
Entire card is not clickable (poor UX)

### Provide environment information
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/vercel/next.js/compare/canary...waquarmahboob4:next.js:patch-3

To Reproduce

Steps to reproduce the behavior:

Create a Next.js component using the Link component to wrap a card Include both text content and an Image component inside the Link Build and inspect the rendered HTML Check the anchor text using SEO tools or browser inspection

Minimal reproduction code:

import Link from 'next/link';
import Image from 'next/image';

export default function CardComponent() {
  const data = {
    url: '/walk-in-dining',
    title: 'Walk-in Dining',
    image: 'https://example.com/dining.png'
  };

  return (
    <Link key={index} href={data.url}>
      <div className="card">
        <span className="title">
          {data.title}
        </span>
        <div className="image-wrapper">
          <Image
            src={data.image}
            width={88}
            height={56}
            alt={data.title}
          />
        </div>
      </div>
    </Link>
  );
}

Current vs. Expected behavior

Current Behavior The rendered HTML creates an anchor tag that wraps all content:

<a href="/walk-in-dining">
  <div class="card">
    <span class="title">Walk-in Dining</span>
    <div class="image-wrapper">
      <img alt="Walk-in Dining" loading="lazy" decoding="async" ... />
    </div>
  </div>
</a>

Actual anchor text perceived by search engines:

Walk-in Dining<img alt="Walk-in Dining" loading="lazy" decoding="async" data-nimg="intrinsic" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%" src="https://example.com/dining.png?format=auto&quality=80"/>


**Expected Behavior**
The anchor text for SEO should only be: Walk-in Dining
The image should be part of the clickable area but NOT included in the semantic anchor text used by search engines for ranking and context.

**1. Attempted Workarounds**

Using legacyBehavior (deprecated) - Works but not a long-term solution:
<Link legacyBehavior href={data.url}> <a> <div className="card"> <span>{data.title}</span> <Image ... /> </div> </a> </Link> ``` ✅ Correct anchor text ⚠️ Uses deprecated API

2. Nested anchor tags - Invalid HTML:

<Link href={data.url}>
  <div>
    <a href={data.url}>{data.title}</a>
    <Image ... />
  </div>
</Link>

❌ Creates nested <a> tags (invalid HTML) ❌ Console errors

3. Separate Link for text only - Loses clickable card:

<div className="card">
  <Link href={data.url}>{data.title}</Link>
  <Image ... />
</div>

✅ Correct anchor text ❌ Entire card is not clickable (poor UX)

Provide environment information

Next.js version: [^16.0.0] 
React version: [^19.2.0]
Node version: [v20.11.1]
Operating System: [Windows]

Which area(s) are affected? (Select all that apply)

Linking and Navigating

Which stage(s) are affected? (Select all that apply)

next build (local)

Additional context

Additional Context This is a common pattern where developers need:

✅ Entire card clickable for good UX ✅ Client-side navigation and prefetching (Link benefits) ✅ Clean anchor text containing only relevant text for SEO ✅ Images as part of the clickable area but NOT in anchor text

The legacyBehavior prop solved this but is now deprecated, leaving no clear migration path for this use case.

extent analysis

TL;DR

The most likely fix involves using a wrapper element inside the Link component to separate the anchor text from the image, ensuring the image is part of the clickable area but not included in the semantic anchor text.

Guidance

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING