How AI is powering better personalization in e-commerce [with Vercel]. Sign up now

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

15 repliesLast updated: Nov 29, 2025

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 (
        &lt;div className="front-container" data-row-id='1'&gt;
            &lt;div className="row-grid-container"&gt;
                &lt;Link href={`/posts/${slug}`}&gt;

                    &lt;CoverImage slug={slug} imageObject={coverImage} title={displayTitle} url={coverImage}/&gt;
                    &lt;div className="title-container"&gt;
                        &lt;p className="excerpt"&gt;{displayExcerpt}&lt;/p&gt;
                        &lt;h3 className="title"&gt;
                            &lt;a&gt;{displayTitle}&lt;/a&gt;
                        &lt;/h3&gt;

                    &lt;/div&gt;
                &lt;/Link&gt;

            &lt;/div&gt;
            &lt;SectionSeparator/&gt;
        &lt;/div&gt;

    );
};

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 (
        &lt;article&gt;
            &lt;Link href={`/posts/${slug}`}&gt;
                &lt;div className="image-container"&gt;
                    &lt;CoverImage slug={slug} title={title} imageObject={coverImage}
                                url={imageBuilder(coverImage).url()}/&gt;
                &lt;/div&gt;
                &lt;p className="excerpt"&gt;{displayExcerpt}&lt;/p&gt;
                &lt;h3 className="title"&gt;
                    &lt;a className='hover:underline'&gt;{displayTitle}&lt;/a&gt;
                &lt;/h3&gt;
            &lt;/Link&gt;
        &lt;/article&gt;
    );
}
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,

&lt;NavLink href="#x"&gt;&lt;Link id="RouterNavLink" style={None} to="/contact"&gt;anywords&lt;/Link&gt;&lt;/NavLink&gt;
Which is converted to,

&lt;a&gt;&lt;a&gt;&lt;/a&gt;&lt;/a&gt;
So you are getting error,

Warning: validateDOMNesting(…): &lt;a&gt; cannot appear as a descendant of &lt;a&gt;
To solve this just use one of the follow,

&lt;NavLink id="RouterNavLink" style={None} to="/contact"&gt;anywords&lt;/NavLink&gt;
OR,

&lt;Link id="RouterNavLink" style={None} to="/contact"&gt;anywords&lt;/Link&gt;
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 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

Was this answer helpful?

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.

Related contributions