Skip to content

hervad/webtoons-dark-mode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

110 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Webtoons Dark Mode

A targeted dark theme for Webtoons — desktop and mobile. No global filter inversion, no white-text-on-white-panel bugs, no per-frame JavaScript work. Just CSS.

License: MIT

What it does

Applies a dark theme to Webtoons by overriding background, text, border, and surface colors on the actual containers the site uses — header, sub-nav, cards, episode lists, viewer, carousel arrows, comments, footer, popups, inputs. Built around a small CSS-variable palette so the whole look can be re-skinned by editing a handful of values.

On the viewer page, the comic panel strip renders as a single elevated card — rounded corners, hairline outline, soft halo on all sides — without inserting any extra DOM elements (one container box-shadow does the lift, so there are no per-image seams). Homepage, series detail, /canvas (home + genre tabs), and /rankings pages get matching three-level elevation (page → section card → comic card), per-card depth shadows, and a :hover darken that makes title overlays readable. Active GNB and SNB tabs render in accent green at the base font size; carousel prev/next arrows are centered SVG chevrons with a green hover tint.

An optional reader dim mode (Alt+Shift+N) lowers comic-panel brightness for late-night reading without affecting the rest of the page.

WCAG-aware: contrast ratios verified for text and UI components (border 3:1, body text 14:1, accent 9:1 against the base surface, dim text 9.1:1). A :focus-visible ring is drawn on every interactive control so keyboard navigation is usable — the base site ships no visible focus indicator.

Two reasons:

  1. Inverting the whole page also inverts comic panels — colors look wrong and tones are off.
  2. Inversion shifts hues (hue-rotate(180deg)) so pinks turn green and brand colors look broken.

This script does the opposite: scoped overrides on the chrome, comic images left untouched.

Install

Recommended (with auto-updates):

Install from Greasyfork — open the link in a browser that has a userscript manager installed, then click Install this script.

Manual:

  1. Install a userscript manager:
  2. Open the raw .user.js file and confirm the install prompt.

Chrome users: since Manifest V3, Tampermonkey requires Developer Mode to be enabled in chrome://extensions/ for userscripts to actually run. Flip the toggle in the top-right of that page once.

Usage

Once installed, the theme is on by default. To toggle:

  • Tampermonkey/Violentmonkey menuToggle Webtoons dark mode / Toggle reader dim
  • Keyboard: Alt + Shift + T (theme), Alt + Shift + N (night-reading dim)

State persists across pages and reloads via GM_setValue.

How it works

A single <style> element is injected at document-start (before paint, so no flash of light theme). The CSS targets the actual container classes Webtoons uses — .gnb, .detail_lst, .viewer_lst, the WCC comment widget ([class*="wcc_*"]), etc. — and overrides background, color, and border properties. Comic panels (img._images) are explicitly excluded with filter: none, so they render exactly as the artist intended.

A small amount of JavaScript runs to handle Webtoons' SPA navigation: a <head> MutationObserver re-injects the <style> if Webtoons swaps stylesheets, pushState / popstate hooks sync three body classes (wt-viewer, wt-detail, wt-home) that scope page-specific CSS, and fixViewerBanners() clears rogue background colors that Webtoons sets via JS inside the viewer column. All listeners are bounded — no requestAnimationFrame loops, no per-frame work.

The script uses three Greasemonkey grants (GM_getValue, GM_setValue, GM_registerMenuCommand) for persistence and the toggle menu — nothing network-facing, nothing that could exfiltrate data.

Configuration

The palette is the first block in the script. Edit any of these CSS variables to re-skin:

:root {
    --wt-bg:             #15171a;  /* page background */
    --wt-bg-elev:        #22262b;  /* cards, header */
    --wt-bg-elev2:       #2c313a;  /* secondary cards, hover */
    --wt-bg-hover:       #30353c;  /* interactive hover surface */
    --wt-bg-input:       #2a2e35;  /* form fields */
    --wt-border:         #4a5360;  /* subtle dividers, card borders */
    --wt-border-strong:  #5a6472;  /* focus rings, selected outlines */
    --wt-text:           #e6e6e6;
    --wt-text-dim:       #b5b9c0;  /* metadata, dates */
    --wt-text-mute:      #7b828d;  /* placeholders */
    --wt-text-on-accent: #0a0a0a;  /* text on accent-colored surfaces */
    --wt-link:           #7cb6ff;
    --wt-accent:         #00d564;  /* Webtoons brand green */
    --wt-accent-soft:    #4ade80;  /* desaturated companion for hover tints */
    --wt-shadow:         0 1px 2px rgba(0,0,0,.6);
}

To change the keybindings, edit the handleKey function. The script accepts both Alt+Shift+T / Alt+Shift+N and Ctrl+Alt+D / Ctrl+Alt+Shift+D as backup combos (the Alt+Shift family conflicts with the Windows input-language switcher on multi-keyboard setups).

Compatibility

  • Tampermonkey, Violentmonkey, Greasemonkey
  • Chromium browsers: Chrome, Edge, Brave, Opera, Vivaldi
  • Firefox (stable + ESR)
  • Safari (with Userscripts app or Tampermonkey)
  • Desktop site (www.webtoons.com) and mobile site (m.webtoons.com)

Performance

The script keeps runtime cost low:

  • One <style> element insert at document-start (~60 KB of CSS, parsed once).
  • One global keydown listener (capture phase) that early-exits on non-modifier keys.
  • A <head> MutationObserver watching only direct childList changes — fires when Webtoons swaps stylesheets and re-injects the theme if it's been removed. No work on attribute or text changes.
  • SPA-navigation hooks on history.pushState / replaceState / popstate schedule three short callbacks (sync body classes, wrap viewer sidebar sections, normalize viewer banners) on a [200, 800, 2000]ms retry cohort, then go idle until the next navigation.
  • No requestAnimationFrame loops, no scroll handlers on the comic strip.
  • No global CSS transitions (an earlier draft used body * { transition: ... } — removed because it makes the browser track transitions on every descendant of <body>, including comic panels).
  • @noframes set, so the script doesn't re-run inside ad iframes or embedded frames.

Known issues

  • Selector drift. Webtoons occasionally renames classes when they redesign sections. If a panel goes white again, please open an issue with the URL and a screenshot — the fix is usually a one-line selector add.
  • WCC comment widget (Webtoon Comment Component) uses CSS-module class names of the form wcc_<Component>__<element> that occasionally gain hashes. Wildcard attribute selectors are used ([class*="wcc_CommentItem__root"]) to survive minor renames, but a major widget refactor will need follow-up.

Contributing

Issues and pull requests welcome. For "this surface is still light" bug reports, please include:

  • The page URL where it reproduces
  • The element class/ID (right-click → Inspect)
  • A screenshot if possible

For local development setup (Fedora + VS Code recommended), see SETUP.md. The short version: git clone, npm install, open in VS Code, install Tampermonkey in your browser. The repo includes ESLint config (with userscript-metadata validation), helper scripts to grep Webtoons' minified CSS bundles, and a metadata validator.

License

MIT — see LICENSE.

About

Scoped dark theme for Webtoons (desktop + mobile) — comic panels untouched. Elevated viewer card, accent-green active nav, WCAG-tuned contrast, optional reader dim. OS preference on first install; persistent toggle (Alt+Shift+T).

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors