6 Commits
Author SHA1 Message Date
danielandClaude Sonnet 5 1ea70c6d26 Make banner and button styling configurable via CSS custom properties
Sites had to copy the entire stylesheet to change colors or sizing.
Every value is now backed by a --cookie-* custom property with the
original value as fallback, so sites can override just what they need
from their own CSS. Also fixes the README's @import path, which had
gone stale since the stylesheet was renamed and moved in 5597e11.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 21:01:18 +02:00
danielandClaude Sonnet 5 3f511f5e6f Log a clear console error when the cookie banner is missing
Silently returning made a missing banner.html integration
indistinguishable from a working page, which cost real debugging
time. Fail loud instead, pointing at the README.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 19:26:04 +02:00
daniel fe2cb13aff Add missing dot. 2026-06-16 21:02:24 +02:00
daniel 7187f7bb2a Fix element ID. 2026-06-16 20:59:17 +02:00
daniel ac0e1ed8c6 Use dash rather than underscore for class attribute. 2026-06-16 20:35:52 +02:00
daniel 5597e11a69 Move stylesheet one level up and rename it. 2026-06-16 17:13:35 +02:00
8 changed files with 138 additions and 81 deletions
+46 -3
View File
@@ -49,10 +49,10 @@ structure with `_partials` and `_shortcode` directories with leading underscores
``` ```
6. Ensure that the SCSS style sheet is being loaded, e.g. by adding this line to 6. Ensure that the SCSS style sheet is being loaded, e.g. by adding this line to
your main *.css file: your main *.scss file:
```scss ```scss
@import "hugo_cookie_consent/style"; @import "hugo_cookie_consent";
``` ```
7. Optionally, insert a `hugo_cookie_consent/settings` partial somewhere on your 7. Optionally, insert a `hugo_cookie_consent/settings` partial somewhere on your
@@ -85,8 +85,51 @@ hugo_cookie_consent:
| `matomo_host` | URL of the Matomo host. | | `matomo_host` | URL of the Matomo host. |
| `matomo_site_id` | Matomo site ID to use for tracking. | | `matomo_site_id` | Matomo site ID to use for tracking. |
## Styling
The banner and its buttons are styled with a small set of [CSS custom
properties][css-vars], each with a sensible default baked in. To adjust the
look of the banner on your site, set any of these properties in your own
stylesheet (no need to copy or override `hugo_cookie_consent.scss`):
```css
:root {
--cookie-banner-bg: #1e293b;
--cookie-banner-color: #f1f5f9;
--cookie-accept-bg: #16a34a;
--cookie-decline-bg: #dc2626;
}
```
| Custom property | Default | Applies to |
|----------------------------------|-----------------|---------------------------------------------|
| `--cookie-banner-bg` | `#4A5568` | Banner background |
| `--cookie-banner-color` | `#E2E8F0` | Banner text color |
| `--cookie-banner-border-color` | `#e2e2e2` | Banner border |
| `--cookie-banner-border-radius` | `12px` | Banner corner radius |
| `--cookie-banner-shadow` | `0 0 36px #111` | Banner drop shadow |
| `--cookie-banner-max-width` | `480px` | Banner max width |
| `--cookie-banner-top` | `2.5rem` | Banner distance from top of viewport |
| `--cookie-banner-padding` | `1rem 1.25rem` | Banner inner padding |
| `--cookie-banner-font-size` | `14px` | Banner message text size |
| `--cookie-banner-z-index` | `9999` | Banner stacking order |
| `--cookie-button-padding` | `.45rem 1rem` | All buttons |
| `--cookie-button-border-radius` | `8px` | All buttons |
| `--cookie-button-border-color` | `#ccc` | All buttons (overridden by the three below) |
| `--cookie-button-font-size` | `13px` | All buttons |
| `--cookie-accept-bg` | `#4A5E52` | Accept button background |
| `--cookie-accept-color` | `#fff` | Accept button text |
| `--cookie-accept-border-color` | `#1a1a1a` | Accept button border |
| `--cookie-decline-bg` | `#2D3748` | Decline button background |
| `--cookie-decline-color` | `#fff` | Decline button text |
| `--cookie-decline-border-color` | `#1a1a1a` | Decline button border |
| `--cookie-settings-bg` | `#272b2e` | Settings-shortcode button background |
| `--cookie-settings-color` | `#fff` | Settings-shortcode button text |
| `--cookie-settings-border-color` | `#1a1a1a` | Settings-shortcode button border |
[anthropic claude]: https://claude.ai [anthropic claude]: https://claude.ai
[css-vars]: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
[gdpr]: https://en.wikipedia.org/wiki/GDPR [gdpr]: https://en.wikipedia.org/wiki/GDPR
[matomo]: https://matomo.org [matomo]: https://matomo.org
[mod-doc]: https://gohugo.io/hugo-modules/use-modules/#import [mod-doc]: https://gohugo.io/hugo-modules/use-modules/#import
[v0.146.0]: https://github.com/gohugoio/hugo/releases/tag/v0.146.0 [v0.146.0]: https://github.com/gohugoio/hugo/releases/tag/v0.146.0
@@ -1,7 +1,14 @@
(function () { (function () {
var KEY = 'cookie_consent'; var KEY = 'cookie_consent';
var banner = document.getElementById('cookie-banner'); var banner = document.getElementById('cookie-banner');
if (!banner) return; if (!banner) {
console.error(
'[hugo_cookie_consent] #cookie-banner not found in the DOM. ' +
'Did you include the hugo_cookie_consent/banner.html partial in your site\'s layout? ' +
'See the module README ("Installation in your Hugo site").'
);
return;
}
updateStatus(); updateStatus();
var consent = localStorage.getItem(KEY); var consent = localStorage.getItem(KEY);
@@ -1,6 +1,6 @@
(function () { (function () {
function trackVisit() { function trackVisit() {
var banner = document.getElementById('cookie_banner'); var banner = document.getElementById('cookie-banner');
if (!banner) return; if (!banner) return;
var matomoUrl = banner.dataset.matomoUrl; var matomoUrl = banner.dataset.matomoUrl;
var siteId = banner.dataset.matomoSiteId; var siteId = banner.dataset.matomoSiteId;
@@ -23,4 +23,4 @@
if (localStorage.getItem('cookie_consent') === 'accepted') { if (localStorage.getItem('cookie_consent') === 'accepted') {
trackVisit(); trackVisit();
} }
})(); })();
+78
View File
@@ -0,0 +1,78 @@
#cookie-banner {
color: var(--cookie-banner-color, #E2E8F0);
background-color: var(--cookie-banner-bg, #4A5568);
position: fixed;
top: var(--cookie-banner-top, 2.5rem);
left: 50%;
transform: translateX(-50%);
width: calc(100vw - 2rem);
max-width: var(--cookie-banner-max-width, 480px);
border: 1px solid var(--cookie-banner-border-color, #e2e2e2);
border-radius: var(--cookie-banner-border-radius, 12px);
padding: var(--cookie-banner-padding, 1rem 1.25rem);
box-shadow: var(--cookie-banner-shadow, 0 0 36px #111);
display: flex;
align-items: center;
gap: 1rem;
z-index: var(--cookie-banner-z-index, 9999);
transition: opacity 0.5s ease;
@media (max-width: 420px) {
flex-direction: column;
align-items: stretch;
gap: 0.75rem;
}
}
#cookie-banner.fade-out {
opacity: 0;
pointer-events: none;
}
#cookie-banner p {
margin: 0;
font-size: var(--cookie-banner-font-size, 14px);
flex: 1;
}
#cookie-banner .cookie-buttons {
display: flex;
gap: 0.5rem;
flex-shrink: 0;
@media (max-width: 420px) {
width: 100%;
button {
flex: 1;
}
}
}
#cookie-banner button {
margin: 0.1rem 0;
padding: var(--cookie-button-padding, .45rem 1rem);
border-radius: var(--cookie-button-border-radius, 8px);
border: 1px solid var(--cookie-button-border-color, #ccc);
cursor: pointer;
font-size: var(--cookie-button-font-size, 13px);
white-space: nowrap;
}
#cookie-accept {
background: var(--cookie-accept-bg, #4A5E52);
color: var(--cookie-accept-color, #fff);
border-color: var(--cookie-accept-border-color, #1a1a1a);
}
#cookie-decline {
background: var(--cookie-decline-bg, #2D3748);
color: var(--cookie-decline-color, #fff);
border-color: var(--cookie-decline-border-color, #1a1a1a);
}
#cookie-settings-button {
background: var(--cookie-settings-bg, #272b2e);
color: var(--cookie-settings-color, #fff);
border-color: var(--cookie-settings-border-color, #1a1a1a);
}
@@ -1,72 +0,0 @@
#cookie-banner {
color: #E2E8F0;
background-color: #4A5568;
position: fixed;
top: 2.5rem;
left: 50%;
transform: translateX(-50%);
width: calc(100vw - 2rem);
max-width: 480px;
border: 1px solid #e2e2e2;
border-radius: 12px;
padding: 1rem 1.25rem;
box-shadow: 0 0 36px #111;
display: flex;
align-items: center;
gap: 1rem;
z-index: 9999;
transition: opacity 0.5s ease;
@media (max-width: 420px) {
flex-direction: column;
align-items: stretch;
gap: 0.75rem;
}
}
#cookie-banner.fade-out {
opacity: 0;
pointer-events: none;
}
#cookie-banner p {
margin: 0;
font-size: 14px;
flex: 1;
}
#cookie-banner .cookie-buttons {
display: flex;
gap: 0.5rem;
flex-shrink: 0;
@media (max-width: 420px) {
width: 100%;
button {
flex: 1;
}
}
}
#cookie-banner button {
margin: 0.1rem 0;
padding: .45rem 1rem;
border-radius: 8px;
border: 1px solid #ccc;
cursor: pointer;
font-size: 13px;
white-space: nowrap;
}
#cookie-accept {
background: #4A5E52; color: #fff; border-color: #1a1a1a;
}
#cookie-decline {
background: #2D3748; color: #fff; border-color: #1a1a1a;
}
#cookie-settings-button {
background: #272b2e; color: #fff; border-color: #1a1a1a;
}
@@ -1,7 +1,7 @@
<div id="cookie-banner" style="display:none" role="dialog" <div id="cookie-banner" style="display:none" role="dialog"
aria-label="Cookie consent" aria-live="polite" aria-label="Cookie consent" aria-live="polite"
data-matomo-url="{{ .Site.Params.hugo_cookie_consent.matomo_host }}" data-matomo-url="{{ .Site.Params.hugo_cookie_consent.matomo_host }}"
data-matomo-site-id="{{ .Site.Params.hugo_cookie_consent_matomo_site_id }}" > data-matomo-site-id="{{ .Site.Params.hugo_cookie_consent.matomo_site_id }}" >
<p> <p>
{{ i18n "site_wants_cookie" }} {{ i18n "site_wants_cookie" }}
<a href="{{ .Site.Params.hugo_cookie_consent.privacy_policy_url }}"> <a href="{{ .Site.Params.hugo_cookie_consent.privacy_policy_url }}">
@@ -3,4 +3,5 @@
{{- if eq .Site.Params.hugo_cookie_consent.enable_tracking true -}} {{- if eq .Site.Params.hugo_cookie_consent.enable_tracking true -}}
{{- $js := resources.Get "js/hugo_cookie_consent/tracker_code.js" | minify -}} {{- $js := resources.Get "js/hugo_cookie_consent/tracker_code.js" | minify -}}
<script src="{{ $js.RelPermalink }}" defer></script> <script src="{{ $js.RelPermalink }}" defer></script>
{{- end -}} {{- end -}}
@@ -1,6 +1,6 @@
<p> <p>
{{ i18n "cookie_status" }}: {{ i18n "cookie_status" }}:
<strong id="cookie_status" <strong id="cookie-status"
data-accepted="{{ i18n "cookie_accepted" }}" data-accepted="{{ i18n "cookie_accepted" }}"
data-declined="{{ i18n "cookie_declined" }}" data-declined="{{ i18n "cookie_declined" }}"
data-none="{{ i18n "cookie_none" }}"> data-none="{{ i18n "cookie_none" }}">