Nested `<a>` tags causing validateDOMNesting warning in clickable article

15 replies
Last updated: Jan 29, 2026
I'm trying to make whole article clickable, but got the warning: Warning: validateDOMNesting(...): &lt;a&gt; cannot appear as a descendant of &lt;a&gt; AND Warning: Expected server HTML to contain a matching &lt;figure&gt; in &lt;a&gt;.

components/HeroPost/index.js
import CoverImage from '../../CoverImage';
import Link from '../../Link';
import SectionSeparator from '../../SectionSeparator';
import React from 'preact/compat';


export default function HeroPost({
                                     coverImage,
                                     slug,
                                     displayExcerpt,
                                     displayTitle,
                                 }) {
    return (
        <div className="front-container" data-row-id='1'>
            <div className="row-grid-container">
                <Link href={`/posts/${slug}`}>

                    <CoverImage slug={slug} imageObject={coverImage} title={displayTitle} url={coverImage}/>
                    <div className="title-container">
                        <p className="excerpt">{displayExcerpt}</p>
                        <h3 className="title">
                            <a>{displayTitle}</a>
                        </h3>

                    </div>
                </Link>

            </div>
            <SectionSeparator/>
        </div>

    );
};

components/PostPreview/index.js:

import CoverImage from '../../CoverImage';
import Link from '../../Link';
import {imageBuilder} from '../../../lib/sanity';

export default function PostPreview({
                                        title,
                                        coverImage,
                                        slug,
                                        displayTitle,
                                        displayExcerpt,
                                    }) {
    return (
        <article>
            <Link href={`/posts/${slug}`}>
                <div className="image-container">
                    <CoverImage slug={slug} title={title} imageObject={coverImage}
                                url={imageBuilder(coverImage).url()}/>
                </div>
                <p className="excerpt">{displayExcerpt}</p>
                <h3 className="title">
                    <a className='hover:underline'>{displayTitle}</a>
                </h3>
            </Link>
        </article>
    );
}
If i put Link over &lt;h3&gt; i will not get the warning, but then the article is not clickable, only the img and title.


I found this:

This is the code which causing the error,

<NavLink href="#x"><Link id="RouterNavLink" style={None} to="/contact">anywords</Link></NavLink>
Which is converted to,

<a><a></a></a>
So you are getting error,

Warning: validateDOMNesting(…): <a> cannot appear as a descendant of <a>
To solve this just use one of the follow,

<NavLink id="RouterNavLink" style={None} to="/contact">anywords</NavLink>
OR,

<Link id="RouterNavLink" style={None} to="/contact">anywords</Link>
but i'm not sure how to apply this in this code, i might need a work around or structure the code differently. Hope there is someone here who can help, thanks!
AI Update

This is a React/Next.js nested anchor tag issue, not specifically a Sanity problem, but I can help you solve it!

The warning is happening because you have nested <a> tags - your Link component wraps everything, and then inside it you have another <a> tag in your <h3>. HTML doesn't allow <a> tags to be nested inside other <a> tags.

Solution: Remove the inner <a> tags

For HeroPost component:

export default function HeroPost({
    coverImage,
    slug,
    displayExcerpt,
    displayTitle,
}) {
    return (
        <div className="front-container" data-row-id='1'>
            <div className="row-grid-container">
                <Link href={`/posts/${slug}`}>
                    <CoverImage slug={slug} imageObject={coverImage} title={displayTitle} url={coverImage}/>
                    <div className="title-container">
                        <p className="excerpt">{displayExcerpt}</p>
                        <h3 className="title">
                            {displayTitle}  {/* Remove the <a> tag here */}
                        </h3>
                    </div>
                </Link>
            </div>
            <SectionSeparator/>
        </div>
    );
}

For PostPreview component:

export default function PostPreview({
    title,
    coverImage,
    slug,
    displayTitle,
    displayExcerpt,
}) {
    return (
        <article>
            <Link href={`/posts/${slug}`}>
                <div className="image-container">
                    <CoverImage slug={slug} title={title} imageObject={coverImage}
                                url={imageBuilder(coverImage).url()}/>
                </div>
                <p className="excerpt">{displayExcerpt}</p>
                <h3 className="title hover:underline">
                    {displayTitle}  {/* Remove the <a> tag here */}
                </h3>
            </Link>
        </article>
    );
}

Why this works:

  • The outer Link component already renders as an <a> tag that wraps all the content
  • Everything inside it (image, excerpt, title) becomes clickable automatically
  • You don't need inner <a> tags at all
  • Move any styling classes (like hover:underline) directly to the <h3> or to the Link component itself

The entire card/article will now be clickable without any nesting warnings. This is the standard pattern for making card-style components fully clickable in React/Next.js applications.

Show original thread
15 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?