The code returns the following error:
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:
- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.
It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.
https://react.dev/link/hydration-mismatch
...
<HotReload globalError={[...]} webSocket={WebSocket} staticIndicatorState={{pathname:null, ...}}>
<AppDevOverlayErrorBoundary globalError={[...]}>
<ReplaySsrOnlyErrors>
<DevRootHTTPAccessFallbackBoundary>
<HTTPAccessFallbackBoundary notFound={<NotAllowedRootHTTPFallbackError>}>
<HTTPAccessFallbackErrorBoundary pathname="/" notFound={<NotAllowedRootHTTPFallbackError>} ...>
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<Head>
<__next_root_layout_boundary__>
<SegmentViewNode type="layout" pagePath="layout.tsx">
<SegmentTrieNode>
<link>
<script>
<RootLayout>
<html
lang="en"
- style={{--vsc-domain:"\"vm-vb13t..."}}
>
...
at html (<anonymous>)
at RootLayout (app/layout.tsx:38:5)
36 | }>) {
37 | return (
> 38 | <html lang="en">
| ^
39 | <body
40 | className={`${notoSerifKR.variable} ${dmSans.variable} font-sans antialiased`}
41 | > (<anonymous>)
[browser] Please ensure that the container has a non-static position, like 'relative', 'fixed', or 'absolute' to ensure scroll offset is calculated correctly. (<anonymous>)
Revise the code to address the error.
I was previewing: /
I can see two distinct issues in the debug logs:
<html>: The --vsc-domain style attribute is injected by the Vercel Sandbox runtime at the <html> tag level. This is a dev environment artifact and not a real bug in our code. However, I should add suppressHydrationWarning to the <html> tag to suppress this harmless warning.useScroll: The layoutEffect: false option causes a React hook order change error (useLayoutEffect vs useEffect). The real fix is to remove layoutEffect: false and instead avoid targeting a ref entirely -- I'll use the simpler approach of useScroll() without a target (which tracks the window scroll) and compute the progress manually, or use useMotionValueEvent properly.layoutEffect: false changes the internal hook from useLayoutEffect to useEffect, causing "change in the order of Hooks" error on hydration.Let me fix both files:
Now fix the ZodiacHero -- the root cause is useScroll({ target, layoutEffect }). I'll replace the scroll-based parallax with a simpler approach that doesn't cause hook order issues:
Now fix the SectionCarousel -- the "non-static position" warning comes from the carousel container needing position: relative. Let me add explicit inline styles:
Now let me also check if the SectionCarousel has any useScroll calls that might cause the warning:
The useScroll is only in zodiac-hero.tsx. The "non-static position" warnings (6 of them in logs) might be coming from Framer Motion's motion.div drag constraints referencing parent containers. The 6 warnings correspond to the 6 SectionCarousel instances (3 sections x 2 warnings per section could happen). Let me also check if the whileInView in content-sections.tsx could cause issues with the viewport margin:
The whileInView with viewport.margin uses IntersectionObserver internally and can also trigger the "non-static position" warning if the root option's container doesn't have proper positioning. The fix is to ensure viewport.root is not set (which defaults to the browser viewport) and that parent containers have position: relative. Let me also look at the motion.div with drag in the SectionCarousel more carefully:
The motion.div with drag="x" and dragConstraints uses computed values (not a ref), so the warning likely comes from Framer Motion internally trying to measure scroll offset of the parent. The absolute positioned inner motion.div needs its parent to have explicit relative positioning which we've added. But the real issue is that Framer Motion's drag constraint calculation walks up the DOM and checks for positioned ancestors. The <main> in page.tsx doesn't have positioning. Let me add it:
Now let me also ensure the <body> in layout has relative positioning, since that's the ultimate scroll container:
Fixed three issues: (1) Added suppressHydrationWarning to the <html> tag to suppress the harmless --vsc-domain style attribute mismatch caused by the Vercel Sandbox runtime. (2) Removed the layoutEffect: false option from useScroll in ZodiacHero which was causing a React hook order change error between SSR (useLayoutEffect) and client (useEffect). (3) Added explicit position: relative via inline styles and class names to the <body>, <main>, and all carousel container elements to ensure Framer Motion can correctly calculate scroll offsets for its drag constraints and useScroll target.
Now I can see both root causes clearly:
zodiac-hero.tsx): useScroll with target ref uses useLayoutEffect internally. On SSR it runs as useLayoutEffect, but the previous attempt with layoutEffect: false changed it to useEffect on the client, causing the hook order mismatch.useScroll({ target }) walks up the DOM to find a positioned ancestor for scroll offset calculation. This fires before Tailwind classes hydrate.The proper fix for ZodiacHero is to not use useScroll with a target ref at all -- instead use the plain useScroll() (window-level) and manually compute progress. For the carousel, the drag="x" constraint calculation also triggers this warning, so I need to use dragConstraints as a ref instead of computed values.
Now fix the SectionCarousel -- replace the drag="x" with dragConstraints as a ref (the container ref) instead of computed pixel values, which is the proper way to prevent the "non-static position" warning:
Fixed both root causes: (1) ZodiacHero now uses useScroll() without a target ref, tracking the window scroll position directly and mapping pixel ranges instead of percentages -- this eliminates both the "non-static position" warning and the hook order mismatch (useLayoutEffect vs useEffect). (2) SectionCarousel now passes containerRef directly to dragConstraints instead of computed pixel objects, which is Framer Motion's intended API for ref-based drag bounds and prevents it from walking up the DOM tree looking for a positioned ancestor.
The code returns the following error:
Image with src "/images/dancheong.jpg" was detected as the Largest Contentful Paint (LCP). Please add the `loading="eager"` property if this image is above the fold.
Read more: https://nextjs.org/docs/app/api-reference/components/image#loading
Revise the code to address the error.
I was previewing: /