diff --git a/src/content/posts/authentik-css-greater-than-bug.md b/src/content/posts/authentik-css-greater-than-bug.md new file mode 100644 index 0000000..f700094 --- /dev/null +++ b/src/content/posts/authentik-css-greater-than-bug.md @@ -0,0 +1,270 @@ +--- +title: "The Character That Silently Broke My authentik CSS" +description: "My authentik custom CSS looked correct, matched the right elements, and did nothing. The cause was a single > character that authentik escapes into invalid text." +pubDate: 2026-09-20 +category: devops +tags: ["authentik", "css", "self-hosting", "debugging", "browser"] +ogImage: /og/authentik-css-greater-than-bug.png +banner: /banners/authentik-css-greater-than-bug.png +draft: true +--- + +I spent an afternoon on a CSS rule that should have taken thirty seconds. + +I wanted to hide one line in the authentik login page footer — the +hardcoded "Powered by authentik" credit. The rule I wrote has worked in +every other project I've touched: + +```css +ul.pf-c-list > li:last-child { + display: none !important; +} +``` + +It did nothing. Not "it looked slightly off" — the element stayed +fully visible. What follows is the four wrong answers I chased, the one +correct answer, and the debugging move I should have made first. + +## Why this matters beyond one footer line + +If you self-host authentik and have ever pasted CSS into +**System → Brands → Custom CSS** and seen zero effect, you have probably +concluded you did something wrong. You almost certainly didn't. The +stylesheet is accepted, stored, served to the browser, and parsed — and +then silently fails, with no error in any log you can reach. + +That is the worst kind of bug: no feedback loop. This post gives you the +loop back. + +## Wrong answer #1: it's shadow DOM, so CSS can't reach it + +My first assumption. Modern web components often hide their markup +behind a shadow root, and normal document CSS cannot cross that +boundary. The authentik login page is rendered by web components — I had +seen `` and `` in the page source — so this +felt obviously right. + +I read the component definition out of the shipped bundle to confirm: + +```js +var oe = class extends L { + createRenderRoot() { return this } + render() { ... } +} +``` + +`createRenderRoot(){ return this }` means **no shadow root** — the +component renders into the light DOM. Ordinary CSS reaches it just fine. + +Wrong answer. Moving on. + +## Wrong answer #2: the CSS isn't being injected at all + +Next theory: my CSS never made it into the page. I grepped the served +HTML for a distinctive class from my rule: + +``` +