summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2026-06-17 15:26:06 -0400
committerGitHub <noreply@github.com>2026-06-17 15:26:06 -0400
commit133de3b86faf07d70a8a915dd2a95d9a9906057f (patch)
treedd4470a0a716153f1dfed1005bd394eea6e41298
parente535682b8136a52f7dc66ec7af5a41c181bd8976 (diff)
downloadvyos-documentation-1.4.tar.gz
vyos-documentation-1.4.zip
Fix Cookiebot consent dialog rendering unstyled and breaking the page (#2108) (#2110)1.4
On a fresh (no-consent) load the consent banner could render completely unstyled and expand to full page height. Cookiebot delivers its dialog CSS as a constructed stylesheet on document.adoptedStyleSheets; ReadTheDocs' readthedocs-addons.js reassigns that whole-array property with a destructive replace, and when that lands after Cookiebot's network-gated adoption it drops Cookiebot's sheet, leaving #CybotCookiebotDialog at position:static expanded to ~6700px. It is a race, so it is intermittent and clears once consent is given (the dialog then never renders). - layout.html: a small adoptedStyleSheets shim, installed before any page script, that preserves Cookiebot's sheet so another library cannot drop it. - custom.css: a leak-safe safety net that keeps the dialog contained even if its adopted sheet is ever absent. It uses only properties Cookiebot itself sets, so it has verifiably no effect on the normal, styled banner. 🤖 Generated by [robots](https://vyos.io) (cherry picked from commit dce7bb521e3947af59fe18895b609ec353e0450e) Co-authored-by: Yuriy Andamasov <yuriy@vyos.io>
-rw-r--r--docs/_static/css/custom.css24
-rw-r--r--docs/_templates/layout.html40
2 files changed, 64 insertions, 0 deletions
diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css
index cdb036d2..c19f436b 100644
--- a/docs/_static/css/custom.css
+++ b/docs/_static/css/custom.css
@@ -532,4 +532,28 @@ html {
.closeButtonDivLine {
bottom: 85px;
}
+}
+
+/* Cookiebot consent dialog — safety net (defense-in-depth).
+ Cookiebot delivers its dialog styling as a constructed stylesheet on
+ document.adoptedStyleSheets. The adoptedStyleSheets shim in layout.html keeps that
+ sheet from being dropped by another library (e.g. ReadTheDocs' readthedocs-addons.js,
+ which reassigns the whole list with a destructive replace). As a backstop, these
+ rules live in a regular stylesheet — which cascades *before* adopted stylesheets, so
+ Cookiebot's own CSS overrides every one of them whenever its sheet is present, and
+ they have no effect on the normal styled banner. They only take effect if that sheet
+ is ever absent, keeping the dialog a contained, scrollable, centered panel instead of
+ falling back to position:static and expanding to full page height. Only properties
+ Cookiebot itself sets are used here, so there is verifiably no leak into the good state. */
+#CybotCookiebotDialog {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ max-width: 920px;
+ max-height: 90vh;
+ overflow: auto;
+ background: #fff;
+ box-shadow: 0 0 24px rgba(0, 0, 0, 0.25);
+ z-index: 2147483631;
} \ No newline at end of file
diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html
index adc6278d..0b8ee41b 100644
--- a/docs/_templates/layout.html
+++ b/docs/_templates/layout.html
@@ -2,6 +2,46 @@
{%- set current_version = "1.4.x sagitta" %}
{% block extrahead %}
{% if gtm_id and cookiebot_id %}
+ {# Keep Cookiebot's consent dialog from rendering unstyled and breaking the page.
+ Cookiebot delivers its dialog CSS as a constructed stylesheet via
+ document.adoptedStyleSheets. That property holds the *whole* sheet list, and
+ ReadTheDocs' readthedocs-addons.js reassigns it with a destructive replace; when
+ that lands after Cookiebot's (network-gated) adoption it drops Cookiebot's sheet,
+ leaving #CybotCookiebotDialog at position:static, expanded to full page height.
+ This shim makes assignment preserve Cookiebot's sheet specifically. It must run
+ before the first adoptedStyleSheets write, so it is the first thing in <head>. #}
+ <script>
+ (function () {
+ try {
+ var desc = Object.getOwnPropertyDescriptor(Document.prototype, "adoptedStyleSheets");
+ if (!desc || !desc.get || !desc.set) return;
+ var guarded = null;
+ var isCookiebot = function (sheet) {
+ try {
+ var rules = sheet.cssRules;
+ for (var i = 0; i < rules.length; i++) {
+ if (rules[i].selectorText && rules[i].selectorText.indexOf("CybotCookiebotDialog") !== -1) return true;
+ }
+ } catch (e) {}
+ return false;
+ };
+ Object.defineProperty(document, "adoptedStyleSheets", {
+ configurable: true,
+ get: function () { return desc.get.call(document); },
+ set: function (sheets) {
+ for (var i = 0; i < sheets.length; i++) {
+ if (isCookiebot(sheets[i])) { guarded = sheets[i]; break; }
+ }
+ if (guarded && Array.prototype.indexOf.call(sheets, guarded) === -1) {
+ sheets = Array.prototype.slice.call(sheets).concat(guarded);
+ }
+ desc.set.call(document, sheets);
+ }
+ });
+ } catch (e) {}
+ })();
+ </script>
+
{# Cookiebot CMP — must load first so its auto-blocker can scan/block other tags #}
<script id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"