.. -*- coding: utf-8 -*- .. role:: sref(numref) .. role:: xref(numref) .. Copyright (C) 2025, Wolfgang Scherer, .. This file is part of Netflix More More Info. .. Permission is granted to copy, distribute and/or modify this document .. under the terms of the GNU Free Documentation License, Version 1.3 .. or any later version published by the Free Software Foundation; .. with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. .. A copy of the license is included in the section entitled "GNU .. Free Documentation License". .. inline comments (with du_comment_role) .. role:: rem(comment) .. role:: html(raw) :format: html .. role:: shx(code) :language: js .. rst-class:: narrow xmedium xlarge xhuge xultra ################################################## :rem:`|||:sec:|||`\ The Trouble With CSS ################################################## .. . (progn (forward-line 1) (snip-insert "rst_b.peek-a-boo" t t "rst") (insert "")) .. >>CODD See `the components of a doctoral dissertation and their order `_ .. >>CODD Dedication .. >>CODD Epigraph .. >>CODD Abstract **TL;DR**: Content Security Policy (CSP) takes the fun out of CSS and inline style attributes. But do not fear! There is a remedy. When developing a `browser extension`_ following the `WebExtensions API`_, adding HTML elements can easily cause CSS pollution. Conflicting CSS rules either put the host page or the extension elements out of whack. A simple solution is to use explicit *style* attributes on custom extension elements. A better solution is to use the `ShadowRoot`_. The `WebExtensions API`_ provides for injecting CSS into web pages by various means, e.g. - background task (`tabs.insertCSS()`_, `scripting.insertCSS()`_), - content scripts (:file:`manifest.json`). However, none of them can affect or target `ShadowRoot`_. So, the method of choice used to be the simple JavaScript approach of style elements with extension URLs or verbatim text, e.g. - ``, - ``. Neither these methods, nor explicit *style* attributes work with CSP `style-src 'self'` anymore. The remedy is to use `constructable stylesheets (Web APIs)`_ (see also `Constructable Stylesheets (web.dev)`_). .. . |:here:| .. _`Constructable Stylesheets (web.dev)`: https://web.dev/articles/constructable-stylesheets .. _`constructable stylesheets (Web APIs)`: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#constructable_stylesheets .. _`constructable stylesheets`: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#constructable_stylesheets .. _`scripting.insertCSS()`: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/insertCSS .. _`tabs.insertCSS()`: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS .. _`ShadowRoot`: https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot .. _`browser extension`: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions .. _`WebExtensions API`: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions .. _`MDN`: https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot .. \|:here:| .. >>CODD Introduction .. >>CODD Chapter ================================================== :rem:`|||:sec:|||`\ ShadowRoot ================================================== The element tree in the shadow root is independent from the element tree in the main document. (See `Using shadow DOM `_). The shadow root can be created programatically, e.g. .. empty block .. code-block:: js .. code-block:: js :caption: Create shadow root const myStyleSheetText = "#kspan { color: blue; }"; const myDiv = document.createElement("div"); myDiv.setAttribute("id", "koeniglich"); document.querySelector("body").appendChild(myDiv); const myShadow = myDiv.attachShadow({ mode: "open" }); let mySpan = document.createElement("span"); mySpan.setAttribute("id", "kspan"); mySpan.textContent = "I'm in the shadow DOM"; myShadow.appendChild(mySpan); or with the *template* HTML element (see `