Why the most-installed "PDF dark mode" Chrome extensions do nothing on a web PDF

작성자

카테고리:

← 피드로
DEV Community · Hao · 2026-07-25 개발(SW)

Hao

Chrome still ships no dark mode for its built-in PDF viewer. Open a white paper at 1am and you get a
flashbang. So you go to the Web Store, install the extension with the most installs, click it, and…
nothing happens. The page stays white.

I went and read the manifests of the top results to find out why. Two reasons, and both are boring.

Reason 1: the popular ones only handle file://

The extension named “PDF Dark Mode” (about 10,000 users, rated 2.5) declares exactly this:

"permissions": ["scripting", "declarativeContent"],
"host_permissions": ["file:///*.pdf"]

Enter fullscreen mode Exit fullscreen mode

The runner-up, “PDF Dark Theme” (about 9,000 users, rated 2.9), does the same thing with a content
script:

"content_scripts": [{ "matches": ["file://*.pdf"], "js": ["content-script.js"] }]

Enter fullscreen mode Exit fullscreen mode

file:///*.pdf matches a PDF you dragged in from your own disk. It does not match
https://arxiv.org/pdf/1706.03762, or the invoice your bank linked, or the syllabus on a course
site. That is where almost everyone actually meets a PDF. So the extension is installed, enabled,
and structurally incapable of touching the document in front of you.

To be fair about the scope of this: it is the two most-installed ones that are scoped this way,
not the whole category. Several smaller ones (a few hundred to a few thousand users) request
<all_urls> or use activeTab and do handle web PDFs. The ranking is weighted by install count, so
the two that cannot do the common case are the two you see first.

This is also why the reviews are full of people being told to flip “Allow access to file URLs” and
reporting back that it changed nothing. It was never the missing piece.

You can check any extension for this in ten seconds: chrome://extensions → Details → look at
“Site access”. If it says nothing beyond file URLs, that is your answer.

Reason 2: the CSS target moved

The other approach is a CSS filter on the viewer element:

embed[type="application/x-google-chrome-pdf"] { filter: invert(90%) hue-rotate(180deg); }

Enter fullscreen mode Exit fullscreen mode

That used to be right. When you navigate straight to a PDF today, the document you are styling has
no <embed> in it. The viewer lives in an out-of-process child frame that your CSS cannot reach.
Your selector matches zero elements and fails silently, which is the worst way for CSS to fail.

What does reach it is a filter on the root element of the PDF document itself:

html { filter: invert(90%) hue-rotate(180deg); background-color: #17171a; }

Enter fullscreen mode Exit fullscreen mode

So the two cases need different code, and you can tell them apart cheaply:

const topLevelPdf = document.contentType === "application/pdf";
const css = topLevelPdf
  ? `html { filter: ${f} !important; background-color: #17171a !important; }`
  : `embed[type="application/x-google-chrome-pdf"],
     embed[type="application/pdf"],
     object[type="application/pdf"] { filter: ${f} !important; }`;

Enter fullscreen mode Exit fullscreen mode

An embedded PDF (a viewer inside a normal page) still wants the second form, because filtering
html there would invert the surrounding page too.

Try it without installing anything

Open a PDF in Chrome, open DevTools on it, and paste this into the console:

document.documentElement.style.filter = "invert(90%) hue-rotate(180deg)";
document.documentElement.style.backgroundColor = "#17171a";

Enter fullscreen mode Exit fullscreen mode

Two notes on the numbers, because they matter more than they look.

invert(90%) rather than invert(100%): full inversion turns black text into pure white on pure
black, which vibrates unpleasantly at night. 90% lands on a soft grey.

hue-rotate(180deg) after the inversion: inverting alone also inverts hue, so a blue hyperlink comes
out orange and a red warning box comes out cyan. Rotating the hue 180° puts colours back where they
started while keeping the lightness flipped. Skip it and PDFs with charts become unreadable.

Sepia is the same trick with one more stage:

filter: invert(93%) hue-rotate(180deg) sepia(35%);

Enter fullscreen mode Exit fullscreen mode

What this approach cannot do

Be honest about the limits before you build on it:

  • Photographs and diagrams invert along with the text. A CSS filter has no idea which pixels are content and which are background. Nobody solves this with filter; it needs the PDF parsed and re-rendered.
  • DRM-protected PDFs are outside your reach entirely.
  • The console trick dies on reload. Persisting it is the entire reason extensions exist here.

The extension

I got tired of this and wrote the small version: PDF Dark Mode — Night Reader for
PDFs
. Disclosure: mine,
free, no account, no network calls at all.

It does the branch above, so web PDFs work and not only local ones; it uses activeTab so it reads
one tab when you click it and holds no standing permission on your browsing; the three themes are
soft dark, true black and sepia, with brightness and contrast sliders.

If you would rather not install a thing, the console snippet is genuinely the whole idea. Take it.
The frustrating part of this category was never the CSS. It was ten extensions all quietly scoped
to file://.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다