Next.js: Duplicate <meta name="viewport"> if the custom one is defined in _document.js

Created on 6 Apr 2019  Â·  19Comments  Â·  Source: vercel/next.js

Bug report

I recently upgraded to the latest canary and noticed horizontal scrolling on some mobile devices. As it turned out, this was caused by #6754 (cc @developit).

Although the default new value of viewport is inserted only when there is no custom one, this logic did not work for me, because my custom viewport tag was in _document.js and not inside <Head />.

<meta name="viewport" content="width=device-width" />

Moving the tag into <Head /> solved the issue, but it took a while to investigate.

Expected behavior

It'd be great if Next.js searched for <meta name="viewport" content="..." /> inside custom _document.js and either did not insert the default one or asked developers to move their tag into <Head />. WDYT folks?

System information

  • Version of Next.js: 8.0.5-canary.17

Most helpful comment

I would like to confirm the Expected behavior so that I can solve this one as soon as possible

  • If there is a viewport in _document don't add the default one
  • If there is a viewport in _document and another in a page and they don't have the same key value add both of them
  • If there is a viewport in _document and another in a page and they do have the same key value add the one in the page

All 19 comments

same issue on 8.0.4
I was trying to set viewport-fit=cover in the viewport meta tag in _document.js, but it was overridden by the default tag.
I believe it will be a better approach if the viewport meta is already set in _document.js, the default tag shouldn't be added

Anybody see this question?

Our team ran into this problem as well and ended up moving our <meta viewport...> tag from _document.js and into _app.js. In _app.js, we are importing Head from 'next/head'; which seems to remove the duplicate, whereas _document.js is importing { Head } from 'next/document';, which did not remove the duplicate.
_app.js seems like an appropriate place to put a global <meta viewport...> tag since it's not SSR related anyway.

So the approach at the moment is to use _app instead of _document?

@cesarvarela yes that is our approach at the moment and does seem to be working..but if anyone has any other suggestions or best practices, we'd love to hear them!

@timneutkens should I make PR to rise a warning in production mode like for the title

In my case, whenever i use "key" property on , unwanted duplicated meta tag appears like below. even in _app.js

<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" class="next-head">

@cheeki I made a PR to fix that but logically there is no need to use the key property on meta tags (But I am not sure, maybe there is a need because I remember that like there was a situation in which key is necessary)

key is needed if you have a child component rewriting the father's component "head".

_app:
<meta key="meta_description" name="description" content="general description"/>

ChildPage:
<meta key="meta_description" name="description" content="page description"/>

I would like to confirm the Expected behavior so that I can solve this one as soon as possible

  • If there is a viewport in _document don't add the default one
  • If there is a viewport in _document and another in a page and they don't have the same key value add both of them
  • If there is a viewport in _document and another in a page and they do have the same key value add the one in the page

I think it's correct.
but also notice viewport might be in _app as well.
possible in all of them:
in _document in _app and in page

If there is a viewport in _document and another in a page and they do have the same key value add the one in the page

@vzaidman what if they don't have a key value? I am considering it to be the same as the above

@cheeki

In my case, whenever i use "key" property on , unwanted duplicated meta tag appears like below. even in _app.js

<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" class="next-head">

I think that it's the right behavior check @vzaidman https://github.com/zeit/next.js/issues/6919#issuecomment-487374749 so if you want to overwrite the default meta you shouldn't use the key

The expected behavior:

  • every meta component without "key" is added to the head.

  • every meta component with key overrides all the other meta components with the same key so only one is added to the head. the overrides will happen in the following order:

    1. page - most important (most specific)
    2. _app
    3. _document - least important (most general)

good to have:

  • console.warn about the possibility to add "key" in development if two meta headers with the same name exists.

Hi! After careful review we've decided this is the intended behavior. Head elements that are expected to be deduped should be added using next/head.
The reason this surfaced is because we started defaulting a more commonly used <meta> tag -- not that something is working unexpectedly.


The correct solution in this scenario is to move to using _app over _document.

It might help to mention this in the documentation https://nextjs.org/docs#custom-document

Feel free to send a PR, @Soundvessel!

Head elements that are expected to be deduped should be added using next/head

A downside of this approach is whenever you need some npm package to build global <meta>s which are always the same (e.g. mobile-detect package to add <meta name="viewport"> conditionally) you're forced to include it on both server and client side.
Even though the package is actually needed only once in _document on server side (as this type of <meta>s don't need to be re-rendered in _app).

Was this page helpful?
0 / 5 - 0 ratings