-
Notifications
You must be signed in to change notification settings - Fork 27k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NEXT-1332] App Router: Chromium browsers prefer favicon.ico over icon.svg #52002
Comments
@seidior Maybe it should look for |
@FrimJo Yeah, that's what I had narrowed it down to on my end as well, and I was going to add it as a PR directly after setting up a dev environment and making sure there were not any unintended effects. My biggest worry with this is that there will be a side effect whenever an SVG file is incorporated on the page, since it's a reasonable assumption that an .ico file would not be used in an on-page On top of this, I'm not as clear with the culture of the repo to make a determination one way or the other on "sizes" here; I figured that would come out in the PR had I decided to include .svg alongside .ico to add I see that @huozhi self-assigned this in the meantime though; I'm happy to help wherever possible here. |
Finally got my local dev environment working only to find out there's a Chromium bug relating to this issue. The first relevant Chromium issue is #1162276, which is regarding the "sizes" attribute with .ico files. This issue is closed, with a commit fixing the issue landing in December 2022. That's not relevant for the issue at hand, however; that only explains why the conditional logic that's already there is there now. The second relevant Chromium issue is #1450857, which relates to Chromium's internal scoring for favorites icons for figuring out which favicon to use. It's linked from that previous issue, and is currently marked as open. The .ico that is in this test case does actually have three embedded sizes inside it, 48x48, 32x32, and 16x16. It's not clear to me why Chrome would ever request the .ico after having seen there's an .svg, but given that it does request it, there's no way to fix the code in Next.js and verify that it is working without the Chromium fixes landing first. So:
That leaves us the most minimal code changes that resolve the issue being: ...(extension in imageExtMimeTypeMap && {
type: imageExtMimeTypeMap[extension as keyof typeof imageExtMimeTypeMap],
}),
...(numericSizes
? { width: imageSize.width as number, height: imageSize.height as number }
: {
sizes:
['ico', 'svg'].includes(extension)
? 'any'
: `${imageSize.width}x${imageSize.height}`,
}),
} This produces the technically correct but not-to-best-practices code: <link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="any"/>
<link rel="icon" href="/icon.svg?2e107c23de4929db" type="image/svg+xml" sizes="any"/> Which, again, does resolve the issue. Chromium still requests the .ico but doesn't rank it higher because the .svg doesn't have the pixel sizes specified in its markup. However, if we wanted to get closer to the example best practices code, code that looks more like this: ...(extension in imageExtMimeTypeMap && {
type:
extension === 'ico'
? undefined
: imageExtMimeTypeMap[extension as keyof typeof imageExtMimeTypeMap],
}),
...(numericSizes
? { width: imageSize.width as number, height: imageSize.height as number }
: {
sizes:
['ico', 'svg'].includes(extension)
? extension === 'ico'
? 'any'
: null
: `${imageSize.width}x${imageSize.height}`,
}),
} will produce output that looks more like the reference material: <link rel="icon" href="/favicon.ico" sizes="any"/>
<link rel="icon" href="/icon.svg?2e107c23de4929db" type="image/svg+xml"/> but that TypeScript code is awful, dirty, and hacky, and I'd want to refactor that before it landed in the codebase. I'm just including it here as a proof-of-concept, and I'll leave the implementation details to people more familiar with the codebase, code conventions, and styles. |
@seidior I run into the same issue and the following solution that is documented here worked well for me: <link rel="icon" href="/favicon.ico" sizes="48x48" >
<link rel="icon" href="/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png"/>
<link rel="manifest" href="/site.webmanifest" /> |
@miukimiu For sure! Thanks for sharing that. That page does actually link to the best practices document I linked in my bug report, and I've used guides like this in the past when making sites that aren't using Next.js. However, the bug report is for creating an idiomatic solution that uses App Router and Next.js's built-in favorites icon support, as placing link tags inside the Thank you for sharing the resource though, and for sharing the example code! Hopefully anyone else who comes across this bug report can use that code on their own sites in the meantime. Although that may only work if your Windows Icon file ( |
EvilMartians have just updated their blog post: https://twitter.com/sitnikcode/status/1679164028541714432
|
For `link` tag's `sizes` property, the property is defined as: > This attribute defines the sizes of the icons for visual media contained in the resource. It must be present only if the [rel](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#rel) contains a value of icon or a non-standard type such as Apple's apple-touch-icon. It may have the following values: `any`, meaning that the icon can be scaled to any size as it is in a vector format, like image/svg+xml. x-ref: https://html.spec.whatwg.org/#attr-link-sizes x-ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link (`sizes` property definition section) Closes #52002 Closes NEXT-133
Updated the svg
I don't think we should change |
But then how are users of the app router supposed to use SVG icons? Chrome is still preferring the .ico version. |
@huozhi Sorry about the ping, but just wanted to make sure you knew this is still broken, and can be fixed by adding Can this be reopened, or should we open a new issue? |
### What? Change the `favicon.ico` metadata `sizes` property from always `"any"` to using the actual size possible ### Why? When chrome/firefox browsers search for icon it needs the proper metadata to determine which one to use, giving `favicon.ico` sizes with `"any"` will prevent it loading the `icon.svg` as default icon when available. Changing to set proper size of `favicon.ico` (as the `favicon.ico` sizes could be 16x16, 32x32, etc.) fixes the issue. It works (loading svg icon) for chrome and firefox: Firefox <img width="505" alt="image" src="https://github.com/vercel/next.js/assets/4800338/6873e595-479d-4d9e-ae5c-39e5f938fcf5"> Chrome <img width="460" alt="image" src="https://github.com/vercel/next.js/assets/4800338/03bbe4c7-ef76-4f34-a611-337b0d4b97a3"> It loads favicon.ico for Safari: Using the `test/e2e/app-dir/metadata` app it shows the favicon.ico for Safari <img width="1000" alt="image" src="https://github.com/vercel/next.js/assets/4800338/92cc8714-ea5e-432d-8144-2a4a42ee4ce2"> Can't have it as an e2e test as I tested it always loads the `favicon.ico` in headless mode which can't determine the behaviors Fixes #52002 Co-authored-by: JJ Kasper <jj@jjsweb.site>
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. |
Verify canary release
Provide environment information
Which area(s) of Next.js are affected? (leave empty if unsure)
Metadata (metadata, generateMetadata, next/head, head.js)
Link to the code that reproduces this issue or a replay of the bug
https://github.com/seidior/next-favicon-issue
To Reproduce
Environment setup:
Then, open a new (Chromium-based) web browser window in private mode. Use the Web Inspector to disable your browser's cache via the "Network" tab. Then navigate to http://localhost:3000 in this window.
With the "Network" tab in Web Inspector open, observe that
favicon.ico
is retrieved, buticon.svg
is not, even though both appear in the<head>
of the page:Describe the Bug
With Next.js 13.4 (stable or canary) set up to use App Router, when both
/app/favicon.ico
and/app/icon.svg
are present, Chromium-based browsers (Google Chrome and Vivaldi were tested) do not use the SVG-based favorites icon and opt only to download the favorites icon in Windows Icon (.ico) format. This is following the metadata documentation.In my attached test case, the following output is generated in the
<head>
section of the page:However, this does not conform to best practices nor to the HTML spec.
sizes="any"
for SVG icons.However, Next.js — as seen above — specifies the "sizes" attribute with the value chosen from the
viewBox
from the SVG image. (This issue presents no matter if the "height" and "width" attributes are specified for the SVG image.)This causes an issue with Chromium-based browsers, which will not choose the SVG icon over the favorites icon if "sizes" is specified with pixel values for the SVG icon.
This issue appears regardless of whether or not standalone is specified and whether or not Next.js is running in dev mode or built as a standalone app.
Expected Behavior
When given an SVG-based favorites icon, Next.js should use one of the above methods (either
sizes="any"
or no "sizes" attribute) so these Chromium-based browsers will use the SVG icon regardless of any other icons specified. It should disregard any sizing information provided by the SVG.Which browser are you using? (if relevant)
Google Chrome 114.0.5735.198 (Official Build) (x86_64)
How are you deploying your application? (if relevant)
dev environment / standalone
From SyncLinear.com | NEXT-1332
The text was updated successfully, but these errors were encountered: