From 096f0d9c226e402a54b71746bcfbb67b21269c8a Mon Sep 17 00:00:00 2001 From: Xin <5097752+imfing@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:04:19 +0800 Subject: [PATCH] fix(favicon): dynamic favicon switching based on color scheme in js (#735) * fix(favicon): dynamic favicon switching based on color scheme in js * refactor(favicon): simplify favicon logic and ensure dynamic switching based on color scheme * docs(favicon): enhance favicon setup instructions with dark mode support and adaptive SVG guidance --- assets/js/favicon.js | 22 +++++++++++++++++++ .../content/docs/guide/configuration.md | 22 ++++++++++++++++--- .../static}/favicon-dark.svg | 0 layouts/_partials/favicons.html | 3 +-- layouts/_partials/scripts/core.html | 3 ++- 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 assets/js/favicon.js rename {static => exampleSite/static}/favicon-dark.svg (100%) diff --git a/assets/js/favicon.js b/assets/js/favicon.js new file mode 100644 index 0000000..36fd132 --- /dev/null +++ b/assets/js/favicon.js @@ -0,0 +1,22 @@ +// {{ $faviconDarkExists := fileExists (path.Join "static" "favicon-dark.svg") }} +(function () { + const faviconEl = document.getElementById("favicon-svg"); + const faviconDarkExists = "{{ $faviconDarkExists }}" === "true"; + + if (faviconEl && faviconDarkExists) { + const lightFavicon = '{{ "favicon.svg" | relURL }}'; + const darkFavicon = '{{ "favicon-dark.svg" | relURL }}'; + + const darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)"); + + function updateFavicon(e) { + faviconEl.href = e.matches ? darkFavicon : lightFavicon; + } + + // Set favicon on load + updateFavicon(darkModeQuery); + + // Listen for system preference changes + darkModeQuery.addEventListener("change", updateFavicon); + } +})(); diff --git a/exampleSite/content/docs/guide/configuration.md b/exampleSite/content/docs/guide/configuration.md index f7220e0..3ca2a54 100644 --- a/exampleSite/content/docs/guide/configuration.md +++ b/exampleSite/content/docs/guide/configuration.md @@ -188,10 +188,26 @@ To customize the [favicon](https://en.wikipedia.org/wiki/Favicon) for your site, {{< /filetree/folder >}} {{< /filetree/container >}} -Include `favicon.ico`, `favicon.svg` and `favicon-dark.svg` files in your project to ensure your site's favicons display correctly. +#### Basic Setup -While `favicon.ico` is generally for older browsers, `favicon.svg` and `favicon-dark.svg` are supported by modern browsers. -Use tools like [favicon.io](https://favicon.io/) or [favycon](https://github.com/ruisaraiva19/favycon) to generate such icons. +At minimum, include `favicon.svg` in your `static` folder. This will be used as the default favicon for your site. + +You can create an adaptive SVG favicon that responds to system theme preferences by using CSS media queries within the SVG itself, following the approach described in [Building an Adaptive Favicon](https://web.dev/articles/building/an-adaptive-favicon). + +#### Dark Mode Support + +For enhanced dark mode support, add `favicon-dark.svg` to your `static` folder alongside `favicon.svg`. When both files are present, Hextra will automatically: + +- Use `favicon.svg` for light mode or when no theme preference is detected +- Switch to `favicon-dark.svg` when the user's system is set to dark mode +- Respect the system's `prefers-color-scheme` setting for automatic switching + +The dark mode favicon switching works across all modern browsers, including Firefox, and provides a seamless experience that matches your site's theme. + +#### Additional Formats + +While `favicon.ico` is generally for older browsers, modern browsers support SVG favicons which are preferred for their scalability and small file size. +Use tools like [favicon.io](https://favicon.io/) or [favycon](https://github.com/ruisaraiva19/favycon) to generate additional favicon formats if needed. ### Theme Configuration diff --git a/static/favicon-dark.svg b/exampleSite/static/favicon-dark.svg similarity index 100% rename from static/favicon-dark.svg rename to exampleSite/static/favicon-dark.svg diff --git a/layouts/_partials/favicons.html b/layouts/_partials/favicons.html index 66a8018..78442d4 100644 --- a/layouts/_partials/favicons.html +++ b/layouts/_partials/favicons.html @@ -1,6 +1,5 @@ - - + diff --git a/layouts/_partials/scripts/core.html b/layouts/_partials/scripts/core.html index db97c9b..26931ee 100644 --- a/layouts/_partials/scripts/core.html +++ b/layouts/_partials/scripts/core.html @@ -7,8 +7,9 @@ {{- $jsFileTree := resources.Get "js/filetree.js" -}} {{- $jsSidebar := resources.Get "js/sidebar.js" -}} {{- $jsBackToTop := resources.Get "js/back-to-top.js" -}} +{{- $jsFavicon := resources.Get "js/favicon.js" | resources.ExecuteAsTemplate "favicon.js" . -}} -{{- $scripts := slice $jsTheme $jsMenu $jsCodeCopy $jsTabs $jsLang $jsNavMenu $jsFileTree $jsSidebar $jsBackToTop | resources.Concat "js/main.js" -}} +{{- $scripts := slice $jsTheme $jsMenu $jsCodeCopy $jsTabs $jsLang $jsNavMenu $jsFileTree $jsSidebar $jsBackToTop $jsFavicon | resources.Concat "js/main.js" -}} {{- if hugo.IsProduction -}} {{- $scripts = $scripts | minify | fingerprint -}} {{- end -}}