Nested `<a>` tags causing validateDOMNesting warning in clickable article
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>
);
}I found this:
This is the code which causing the error,
<NavLink href="#x"><Link id="RouterNavLink" style={None} to="/contact">anywords</Link></NavLink><a><a></a></a>Warning: validateDOMNesting(…): <a> cannot appear as a descendant of <a><NavLink id="RouterNavLink" style={None} to="/contact">anywords</NavLink><Link id="RouterNavLink" style={None} to="/contact">anywords</Link>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
Linkcomponent 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 theLinkcomponent 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 thread15 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.