如何在Hugo中检测浏览器并根据浏览器类型显示不同图片
Great question! Let’s break down the core issue first, then walk through practical solutions.
The key limitation here is: Hugo templates run at build time (when you generate your static site files), while browser detection happens at runtime (when a visitor loads your page in their browser). That means you can’t directly pass your JavaScript isSafari variable into Hugo’s template logic like you tried—by the time the browser runs that JS, Hugo has already finished generating the HTML.
But don’t worry, there are two solid ways to achieve your goal:
1. JavaScript Dynamic Image Swap (Strict Browser Targeting)
This uses your existing Safari detection code to swap the image source after the page loads. It’s perfect if you need to target Safari specifically, regardless of whether it supports WebP.
Here’s how to implement it in your Hugo template:
<!-- Render a default WebP image with an ID we can target --> <img id="banner-phone" src="{{ "img/bannerphone.webp" | absURL }}" alt="phone"> <!-- Add the Safari detection and image swap script --> <script> // Your existing Safari detection logic var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification)); // Swap to PNG if we're in Safari if (isSafari) { const bannerImg = document.getElementById('banner-phone'); bannerImg.src = "{{ "img/bannerphone.png" | absURL }}"; // Optional: Replace srcset too if using responsive images // bannerImg.srcset = "{{ "img/bannerphone@2x.png" | absURL }} 2x"; } </script>
To avoid loading two images unnecessarily, you can also initialize the image without a src and set it dynamically:
<img id="banner-phone" alt="phone"> <script> var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification)); const bannerImg = document.getElementById('banner-phone'); bannerImg.src = isSafari ? "{{ "img/bannerphone.png" | absURL }}" : "{{ "img/bannerphone.webp" | absURL }}"; </script>
2. Use the <picture> Element (Feature-Based Detection)
If your real goal is to serve WebP to browsers that support it and PNG to those that don’t (a more modern, future-friendly approach), you can skip browser detection entirely. The <picture> element lets browsers pick the first supported image format automatically.
Here’s the code:
<picture> <!-- Serve WebP to browsers that support it --> <source srcset="{{ "img/bannerphone.webp" | absURL }}" type="image/webp"> <!-- Fallback to PNG for unsupported browsers (including older Safari versions) --> <img src="{{ "img/bannerphone.png" | absURL }}" alt="phone"> </picture>
Note: This doesn’t strictly target Safari—newer Safari versions that support WebP will load the WebP image. Use this if your priority is format support rather than browser brand.
Why Your Original Approach Didn’t Work
Just to recap: Hugo processes your templates when you build your site, before any visitor opens it in a browser. There’s no way for Hugo to know which browser a future visitor will use, so you can’t use a runtime JavaScript variable in Hugo’s build-time if statements. The solutions above handle the decision on the client side, where browser information is available.
内容的提问来源于stack exchange,提问作者jakerupp11

