mozilla-mobile / firefox-ios

Firefox for iOS
Mozilla Public License 2.0
12.2k stars 2.92k forks source link

[iOS 13] Night mode makes black background white, making dark theme websites light theme #5772

Open Scripter17 opened 4 years ago

Scripter17 commented 4 years ago

Version: 20.1 (16561)

Phone: iPhone SE (13.2.2)

Description: When dark mode is enabled while browsing a website with a black background by default, the browser makes the background white, and inverts all other text colors as well. This effectively converts it to a light theme. This does not occur in Safari, or when FireFox is set to use light mode. It also isn't affected by whether the iPhone itself is set to dark or light mode.

I discovered this bug when making a custom new tab page for my phone, but it appears to affect all dark mode websites.

Page with dark mode enabled

Page with dark mode disabled

Ideally, FireFox would automatically detect if a website uses a dark theme by default. Other, arguably better, solutions would be to include a HTML/CSS solution to this, as well as having a manual per-website toggle. I think the best solution would be all three of these.

The only workaround I've found is manually changing all styles to light theme so that FireFox re-fixes it, which would work because this project is only me and only on FireFox, but this is nowhere near a good solution for sites meant for more than just the creator.

Side note: This is the first issue I've submitted on GitHub, so uh... Yeah. If I'm doing this wrong, let me know.

┆Issue is synchronized with this Jira Task

Scripter17 commented 4 years ago

Quick and dirty fix: Add filter: invert(70%) hue-rotate(180deg) brightness(0.8) saturate(2); to the CSS of whatever's affected.

It ain't perfect, but it looks good enough (at least from my limited testing)

EDIT: Found an actual solution!
In firefox-ios-master\Client\Frontend\UserContent\UserScripts\MainFrame\AtDocumentStart\NightModeHelper.js there are the following lines

   14  
   15: const NIGHT_MODE_INVERT_FILTER_CSS = "brightness(80%) invert(100%) hue-rotate(180deg)";
   16  
   17  const NIGHT_MODE_STYLESHEET =
   18  `html {
   19   -webkit-filter: hue-rotate(180deg) invert(100%) !important;
   20  }
   21  iframe,img,video {
   22   -webkit-filter: ${NIGHT_MODE_INVERT_FILTER_CSS} !important;
   23  }`;
   24  

Therefore, the following CSS should fix everything but background images!

html{filter:brightness(1.25) invert(100%) hue-rotate(180deg);}
iframe,img,video{filter:invert(100%) hue-rotate(180deg);}

Unfortunately @media(prefers-color-scheme:dark) seems to detect the phone's theme setting instead of the browser's, but it's a massive leap

EDIT 2: The actual actual solution is to use the following JavaScript; if(window.__firefox__){window.__firefox__.NightMode.setEnabled(false);}

nixoye commented 4 years ago

Is there any progress being made on this? Would be great if Firefox detected websites that are already Dark especially since Dark Mode detection on websites is becoming more widely used. Would be great especially since Firefox will soon be able to become a default browser on iOS

MasterJubei commented 4 years ago

Same issue here

isaacjara17 commented 3 years ago

Same issue here. Happening on iOS 14 as well. Firefox is currently my default browser and I’d love to use this feature if it worked, since no other iOS browser has it

james-culp commented 3 years ago

Just echoing the other commenters that it would be great to improve this feature, since it's such a nice differentiator from other iOS browsers :)

elsiehupp commented 3 years ago

@Scripter17 is your solution something that would be able to be implemented by Firefox, rather than by individual websites? In general, websites with their own dark themes do look better than a browser- or extension-implemented CSS hack, but, again, Firefox does not recognize these, and it seems unreasonable to expect every website to implement a browser-specific hack.

As an example, Ars Technica has its own night theme, which Firefox converts back into a day theme.

If you have the necessary expertise, would you be willing to try modifying firefox-ios-master\Client\Frontend\UserContent\UserScripts\MainFrame\AtDocumentStart\NightModeHelper.js and submitting a pull request, since this issue has gotten little to no attention from the Firefox maintainers? (It presumably doesn't help that @dnarcese tagged this a "nice to have" rather than as a bug... there is a duplicate issue that is tagged as a bug, though: https://github.com/mozilla-mobile/firefox-ios/issues/7256)

As an extremely basic heuristic, it could be reasonable for Firefox to disable dark mode on pages where body-background is less than 50% brightness and/or body-text is greater than 50% brightness. I'm not a web developer, so implementing this is a bit beyond my expertise, but it seems like it should be relatively straightforward? Thanks!

Scripter17 commented 3 years ago

I can try, but I can't guarantee any actual result
I can't compile IOS apps so I'm just using the JavaScript in that file to make a solution on my computer

Scripter17 commented 3 years ago

So I quickly hacked together a solution

  1. Add the following function to the script:

    function isWebsiteCSSNightMode(){
    // Fixes FXIOS177 (enabling night mode makes websites with night mode CSS into day mode)
    var splitRGB=/rgba?\((\d+), *(\d+), *(\d+)(?:, *(\d+\.?\d*))?\)/g;
    var bodyBG=window.getComputedStyle(document.body).backgroundColor;
    var bodyBGSplit=splitRGB.exec(bodyBG);
    bodyBGSplit.shift();
    if (bodyBGSplit.length==4){
    bodyBGSplit.pop();
    }
    // https://css-tricks.com/using-javascript-to-adjust-saturation-and-brightness-of-rgb-colors/#how-to-find-the-lightness-of-an-rgb-color
    var bodyBGBrightness=(Math.max(...bodyBGSplit)+Math.min(...bodyBGSplit))/2/255;
    return bodyBGBrightness<=0.5;
    }
  2. Put the following at the top of the firefox.NightMode.setEnabled definiton:

    if (isWebsiteCSSNightMode() && enabled){
      return;
    }

Granted, it doesn't work if the body element doesn't explicitly have a style, but it's a start

boek commented 3 years ago

https://www.ajaypalcheema.com/dark-mode-js/

I wonder if this would work 🤔

drgrib commented 3 years ago

This is a problem again. This solution from @Scripter17 was working until a recent update:

if(window.__firefox__){window.__firefox__.NightMode.setEnabled(false);}

Can we get some news on a replacement for this solution? It is so frustrating that we can't take advantage of sites that have put work into providing a standard dark mode while also protecting from sites that haven't.

elsiehupp commented 3 years ago

I think the most productive thing to do would be to do a pull request, since the maintainers don't really seem to engage with the issue tracker here. (They engage more with the one over at Bugzilla, but I don't know if there's a Bugzilla for Firefox Mobile specifically.)

dnarcese commented 3 years ago

We don’t have any update right now but it is on our radar!

elsiehupp commented 3 years ago

Well, I just did a pull request before I saw your response, so hopefully it's helpful!

camspiers commented 3 years ago

The following is a complete hack and in my opinion this shouldn't have been necessary for a website to do, and is only needed because Firefox mobile is inappropriately inverting colors on websites that are actually designed with a dark scheme (for example as a default), or themselves offer a night/dark mode already.

But, the hack is to remove Firefox mobile's custom style sheet by detecting it has been added:

Array.from(document.querySelectorAll("style")).forEach((sheet) => {
  if (
    sheet.textContent?.includes(
      "-webkit-filter: hue-rotate(180deg) invert(100%) !important;"
    )
  ) {
    sheet.parentNode?.removeChild(sheet);
  }
});

Again, this is a complete hack and it would be much better if there was a nicer way to disable Firefox's customizations for example by communicating to the browser that the app or website in question is already in dark mode or is designed to be a dark scheme.

My recommendation is for Firefox mobile to remove this automated CSS overriding feature completely, and instead inform the website using the prefers-color-scheme feature, and rely on the website to appropriately style accordingly:

https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme

As a worstcase fallback a "Force night mode" option could apply the current "Night mode"'s CSS overrides.

Scripter17 commented 3 years ago

For anyone who's confused as to what on earth sheet.textContent?.includes is doing: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Related: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator