next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Next13: unwanted div element added inside layout

Open mehrdad-shokri opened this issue 3 years ago • 5 comments

Verify canary release

  • [x] I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 22.1.0: Sun Oct  9 20:14:30 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T8103
Binaries:
  Node: 16.17.1
  npm: 8.15.0
  Yarn: 1.22.19
  pnpm: N/A
Relevant packages:
  next: 13.0.0
  eslint-config-next: 13.0.0
  react: 18.2.0
  react-dom: 18.2.0

warn - Latest canary version not detected, detected: "13.0.0", newest: "13.0.2-canary.0". Please try the latest canary version (npm install next@canary) to confirm the issue still exists before creating a new issue. Read more - https://nextjs.org/docs/messages/opening-an-issue

What browser are you using? (if relevant)

Chrome

How are you deploying your application? (if relevant)

No response

Describe the Bug

I can confirm that for every nested layout that I've used, there is a parent div which children is wrapped inside them. I've checked my code I don't return that <div> so I suspect is wrapping children around another div.

Expected Behavior

I expect it to be wrapped inside Fragment(if necessary) because,

messes my styles

Link to reproduction

yarn create next-app nextjs-server-components --experimental-app

To Reproduce

Check the default Next.js rendered HTML for path /, there is a <div> around page container which is neither present inside the default layout nor inside the page

mehrdad-shokri avatar Nov 02 '22 11:11 mehrdad-shokri

After upgrading to next 13.0.1 this is the div which gets added inside layouts: <div data-nextjs-scroll-focus-boundary I don't know what its use is but it messes my styles. Seriously, we though our pages is gonna mount inside layouts and adding another intermediate <div> between these can mess a lot of things.

mehrdad-shokri avatar Nov 02 '22 11:11 mehrdad-shokri

I've put a video to show what I mean but adding intermediate div elements between layout and pages causes to not be able to use nested layouts since you can't style the nested layout because it's gonna be rendered inside a bunch of other divs and what you meant to be placed in place of the children would end of inside a bunch of divs so you won't be able to style the nested layout https://user-images.githubusercontent.com/13661520/199484479-71b0696d-eff8-44a4-8433-b1bbd99168cb.mov

mehrdad-shokri avatar Nov 02 '22 12:11 mehrdad-shokri

This is a known Issue and is being discussed in https://github.com/vercel/next.js/discussions/41745#discussioncomment-3973420

Background: If you navigate inside nested layouts, Next.js needs to restore the scroll position or scroll the loaded element into view. Nevertheless React currently has no API to select the DOMNodes of a React subtree (inside strict mode), because a subtree could be a string or even a boolean. So the current solution is to wrap the subtree inside a div to ensure we can scroll the new element into view.

Afaik the React Team and Next.js Team is aware of this issue. Hopefully it will be resolved in the future.

HaNdTriX avatar Nov 02 '22 12:11 HaNdTriX

@HaNdTriX couldn't Nextjs register that ref on the first child of the children? is that possible?

mehrdad-shokri avatar Nov 02 '22 13:11 mehrdad-shokri

If that component has a DOM Node to reference and if React would expose an API like findDOMNode that might be possible.

Please note that this issue is not trivial, because of the way the DOM works. JSX supports all kinds of Node DOMNode like React Components (strings, booleans, arrays, undefined, etc.). These component results are currently not referenceable using traditional DOM APIs.

function MyComponent() {
  return <>I am a string, you can\'t reference me via traditions DOM APIs</>
}

The DOM only allows us to query components in a performant way. If you want to query a specific TextNode (e.g. 3rd word in a sentence) or an HTML comment things get complicated and slow.

Disclaimer: I am not part of Next.js Core Team

HaNdTriX avatar Nov 02 '22 15:11 HaNdTriX

How about this document.getElementById("childrenWrapper").firstChild. I think in case of Fragments, boolean, string, undefined, null and array(basically where firstChild is null) we can register the ref on the childWrapper itself. so we can have a common ID that we can wrap children inside that ID and Next.js can handle it this way without the need to add another HTML element

mehrdad-shokri avatar Nov 02 '22 21:11 mehrdad-shokri

Hi, While waiting for a proper solution, I wanted to mention that this simple CSS resolve a lot of my issues with these unwanted div.

[data-nextjs-scroll-focus-boundary] {
  display: contents;
}

it will not work for older browsers unfortunately.

long-lazuli avatar Nov 06 '22 01:11 long-lazuli

I'm going to close this issue as this is behaving as intended for right now. As said in https://github.com/vercel/next.js/discussions/41745#discussioncomment-3973420 we're planning to remove it in the near future.

timneutkens avatar Nov 06 '22 16:11 timneutkens

It was fixed in the last canary

https://github.com/vercel/next.js/pull/43717

danieljpgo avatar Dec 13 '22 12:12 danieljpgo

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

github-actions[bot] avatar Jan 13 '23 00:01 github-actions[bot]