diff --git a/.changeset/prefetch-viewport.md b/.changeset/prefetch-viewport.md
new file mode 100644
index 00000000000..139e10676d2
--- /dev/null
+++ b/.changeset/prefetch-viewport.md
@@ -0,0 +1,6 @@
+---
+"remix": minor
+"@remix-run/react": minor
+---
+
+Add support for `` to prefetch links when they enter the viewport via an [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver)
diff --git a/docs/components/link.md b/docs/components/link.md
index dbc52b29f68..373f6d00489 100644
--- a/docs/components/link.md
+++ b/docs/components/link.md
@@ -30,12 +30,14 @@ In the effort to remove all loading states from your UI, `Link` can automaticall
+
>
```
- **"none"** - Default behavior. This will prevent any prefetching from happening. This is recommended when linking to pages that require a user session that the browser won't be able to prefetch anyway.
- **"intent"** - Recommended if you want to prefetch. Fetches when Remix thinks the user intends to visit the link. Right now the behavior is simple: if they hover or focus the link it will prefetch the resources. In the future we hope to make this even smarter. Links with large click areas/padding get a bit of a head start. It is worth noting that when using `prefetch="intent"`, `` elements will be inserted on hover/focus and removed if the `` loses hover/focus. Without proper `cache-control` headers on your loaders, this could result in repeated prefetch loads if a user continually hovers on and off a link.
- **"render"** - Fetches when the link is rendered.
+- **"viewport"** - Fetches while the link is in the viewport
You may need to use the :last-of-type selector instead of :last-child when styling child elements inside of your links
diff --git a/docs/components/nav-link.md b/docs/components/nav-link.md
index 24fa75e3d8a..a9cad56540f 100644
--- a/docs/components/nav-link.md
+++ b/docs/components/nav-link.md
@@ -5,7 +5,7 @@ toc: false
# ``
-A `` is a special kind of `` that knows whether or not it is "active" or "pending". This is useful when building a navigation menu, such as a breadcrumb or a set of tabs where you'd like to show which of them is currently selected. It also provides useful context for assistive technology like screen readers.
+A `` is a special kind of [``][link] that knows whether or not it is "active" or "pending". This is useful when building a navigation menu, such as a breadcrumb or a set of tabs where you'd like to show which of them is currently selected. It also provides useful context for assistive technology like screen readers.
```tsx
import { NavLink } from "@remix-run/react";
@@ -122,3 +122,4 @@ Adding the `caseSensitive` prop changes the matching logic to make it case sensi
When a `NavLink` is active it will automatically apply `` to the underlying anchor tag. See [aria-current][aria-current] on MDN.
[aria-current]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current
+[link]: ./link.md
diff --git a/integration/prefetch-test.ts b/integration/prefetch-test.ts
index b005c46a774..c07b00abc6e 100644
--- a/integration/prefetch-test.ts
+++ b/integration/prefetch-test.ts
@@ -271,3 +271,74 @@ test.describe("prefetch=intent (focus)", () => {
expect(await page.locator("#nav link").count()).toBe(1);
});
});
+
+test.describe("prefetch=viewport", () => {
+ let fixture: Fixture;
+ let appFixture: AppFixture;
+
+ test.beforeAll(async () => {
+ fixture = await createFixture({
+ config: {
+ future: { v2_routeConvention: true },
+ },
+ files: {
+ "app/routes/_index.jsx": js`
+ import { Link } from "@remix-run/react";
+
+ export default function Component() {
+ return (
+ <>
+