Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a white shadow in dark mode #277

Closed
aplaice opened this issue Apr 10, 2020 · 11 comments · Fixed by #278
Closed

Add a white shadow in dark mode #277

aplaice opened this issue Apr 10, 2020 · 11 comments · Fixed by #278
Labels
structure Templates, tags, generated decks, etc.
Milestone

Comments

@aplaice
Copy link
Collaborator

aplaice commented Apr 10, 2020

This might help distinguish the edges of flags which have black elements. (See #274 (comment).)

For example, Afghanistan, Belgium, Ceuta, Egypt or Uganda.

To remind myself: I'll need to test this on both types of Ankidroid's night theme (dark and black).

@aplaice aplaice self-assigned this Apr 10, 2020
aplaice added a commit to aplaice/anki-ultimate-geography that referenced this issue Apr 10, 2020
Fix anki-geo#277.

I suggest #ccc (202,202,202) rather than pure white, since pure white
looked slightly too glowy with Ankidroid's "dark" theme.
@axelboc axelboc added the structure Templates, tags, generated decks, etc. label Apr 11, 2020
@axelboc axelboc added this to the v3.3 milestone Apr 11, 2020
@ukanuk
Copy link
Contributor

ukanuk commented Apr 16, 2020

This may seem nitpicky, but what do you guys think of changing it to a centered white glow instead of an offset white shadow? I'm not 100% sure, but I think this is the main reason it rubbed me wrong when I first saw it.

I also notice that in light mode, the shadow is barely visible except when against white, whereas in dark mode the glow is still visible against most colors, not just black, especially at the bottom. Removing the offset helps, and removing the spread helps even more. Maybe we could decrease 202 or increase the alpha even more?

It's a little hard to see in these screenshots on GitHub, but if you open each image in a new tab at the regular resolution, you will see that on the proposal there's still a clear white border next to the black flag edges for both grey and black backgrounds. I've tested on mobile as well and it looks better to me there, too.

It seems the glow is more visible against grey than against black. Perhaps setting a darker color with a higher alpha-value would reduce this effect? Not sure. If you guys like the direction of this, I can do some additional testing.

Parameters for reference;
box-shadow: offset-x | offset-y | blur-radius | spread-radius | color

Anki Desktop Dark Mode (proposing offset-y = 0 and spread-radius = 0):
box-shadow: 0 0 4px 0 rgba(202, 202, 202, 0.2);
image
image

Anki Desktop Dark Mode:
box-shadow: 0 1px 4px 1px rgba(202, 202, 202, 0.2);
image

Anki Desktop Light Mode:
box-shadow: 0 1px 4px 1px rgba(0, 0, 0, 0.2);
image

@aplaice
Copy link
Collaborator Author

aplaice commented Apr 16, 2020

I had tested with no offset or spread-radius (as well as a couple of other parameter sets with fractional y-offset and spread-radius) — the issue was that at least on my phone, on AnkiDroid, for the flags that needed the white outline (e.g. Egypt or Uganda), the outline still wasn't visible — so I had decided to not deviate from the "white mode" parameters. Also, reducing the asymmetry (y-offset vs. x-offset) made the shadow look less like a shadow, though that's probably less of an issue.

However, I'm obviously very much in favour of finding a better value for the shadow, if the current one is disliked.


Some alternative ideas:

  1. Use the shadow only for the flags where it's needed, by adding something like -whitebox to the filename, in the way we've done for the lack of a box or the blurred flags.

  2. Use the shadow only when the background is pure black, since that's only when the black elements of flags merge with the background (to the extent that's possible in a cross-platform way — I don't think that anything like[style*="#000"] would work, not to mention that it'd be extremely fragile).

@ukanuk
Copy link
Contributor

ukanuk commented Apr 16, 2020

... Reducing the asymmetry (y-offset vs. x-offset) made the shadow look less like a shadow, though that's probably less of an issue.

I think this is a main reason it looked strange to me at first. Dark shadows should be offset, but light glows ought to be symmetrical. Maybe it would work on your phone with zero offset but a larger spread-radius? We definitely ought to ensure something appears on all devices.

  1. Use the shadow only for the flags where it's needed, by adding something like -whitebox to the filename, in the way we've done for the lack of a box or the blurred flags.

I agree this could work if we can't find pure CSS that's satisfactory.

  1. Use the shadow only when the background is pure black, since that's only when the black elements of flags merge with the background

How about removing the alpha channel and setting shadow color to dark grey? This should effectively be invisible on grey unless looking very closely. Alpha is useful for putting a shadow over a changing background (e.g. gradient or photo), but to me doesn't seem useful for plain backgrounds. For example:

box-shadow: 0 0 4px 2px #333;

@aplaice
Copy link
Collaborator Author

aplaice commented Apr 16, 2020

I think this is a main reason it looked strange to me at first. Dark shadows should be offset, but light glows ought to be symmetrical. Maybe it would work on your phone with zero offset but a larger spread-radius?

If anything, reducing the offset increases (worst-case) visibility, so if the asymmetry is what bothered you, then the y-offset can be safely set to zero without changing the spread-radius. (When testing, the part that I considered as potentially most objectionable was the "glowiness" itself, so what I had been trying to minimise was the spread-radius, decreasing the y-offset only as much as was necessary to compensate for the decrease in spread-radius.)

You're probably right, though, that for a light glow, asymmetry doesn't make sense!

How about removing the alpha channel and setting shadow color to dark grey?

That's pretty clever! After all, if the shadow colour is the same as the background colour, then the shadow won't be visible. (I'm not convinced a priori that the alpha should be 1, though in practice it just about could be — see below.)

The disadvantage of that approach is that if the background is lighter than the glow colour, then the glow will become a (symmetric) shadow again, which isn't really desirable. For reference, AnkiDroid's dark gray background is #303030, while Anki's is #2F2F31. If we set the glow to slightly lighter than #313131, then (assuming iOS's dark gray mode isn't too different) we should be safe (for now...). Let's say #353535 to have a slight margin for changes in Anki or AnkiDroid.

With an alpha of 0.2, glow/shadow colour of #CCC and background colour of #000, the current "effective" colour of the glow is #282828 (0.2 * 202 ≈ 40 = 0x28), and I think it's approximately suitable (neither too "glowy" nor too weak).

To achieve the same "effective" colour, if the colour of the glow/shadow itself is #353535, we need an alpha of ~ 0.8 (or more precisely 0.76 (0.76 * 0x35 = 0.76 * 53 ≈ 40)). Ignoring it (setting it to 1) would probably also be OK.

Overall, perhaps (removing the asymmetry, as discussed):

box-shadow: 0 0 4px 1px rgba(53, 53, 53, 0.8);

Testing it provides the same visibility as the current parameters.

(Just using #333 (ignoring alpha) would also be OK, if possibly making the glow slightly too strong.)

@ukanuk
Copy link
Contributor

ukanuk commented Apr 18, 2020

I'm ambivalent to whether alpha stays or goes away, as long as it looks good in practice I'm fine. I think the alpha=0.8 in your last example looks good on grey with the glow essentially invisible.

However, I'm noticing another potential problem that also applies to the currently-released styling when on a black background. This occurs when my phone brightness is completely turned down (and I'm in a darkish room, not direct sunlight). In light mode, I can still clearly see the shadow-on-white (shadow contrasting against white flag borders). But in night mode with my phone brightness turned down completely, I can no longer discern glow-on-black (the glow contrasting against black flag borders on black background). I was especially surprised because I can discern the glow against grey, just not against black.

I investigated the contrast of various combinations using the tool at leaverou/contrast-ratio.

Click to expand contrast investigation

(Background Key: Anki Desktop Grey = pc-g, AnkiDroid Grey = droid-g, AnkiDroid Black = droid-b)
Contrasts ≥ 1.6 are bolded for emphasis (at least as much contrast as original shadow-on-white)

Condition Shadow/Glow Color Background Contrast
Shadow on white rgba(0, 0, 0, 0.2) #FFFFFF 1.606
v3.3 glow rgba(202, 202, 202, 0.2) #303030 droid-g 1.606
v3.3 glow rgba(202, 202, 202, 0.2) #2F2F31 pc-g 1.609
v3.3 glow rgba(202, 202, 202, 0.2) #000000 droid-b 1.432
v3.3 glow, α=1 rgb(202, 202, 202) #303030 droid-g 8.052
v3.3 glow, α=1 rgb(202, 202, 202) #2F2F31 pc-g 8.151
v3.3 glow, α=1 rgb(202, 202, 202) #000000 droid-b 12.812
Last apliace idea rgba(53, 53, 53, 0.8) #303030 droid-g 1.060
Last apliace idea rgba(53, 53, 53, 0.8) #2F2F31 pc-g 1.070
Last apliace idea rgba(53, 53, 53, 0.8) #000000 droid-b 1.471

I also tested various parameters which achieve contrast with black background of at least 1.6 (CwB≥1.6).
(Background Key: Anki Desktop Grey = pc-g, AnkiDroid Grey = droid-g, AnkiDroid Black = droid-b)
Contrasts ≥ 1.6 are bolded for emphasis (at least as much contrast as original shadow-on-white)

Condition Shadow/Glow Color Background Contrast
α=0.8, rgb=var, CwB≥1.6 rgba(61, 61, 61, 0.8) #303030 droid-g 1.167
α=0.8, rgb=var, CwB≥1.6 rgba(61, 61, 61, 0.8) #2F2F31 pc-g 1.179
α=0.8, rgb=var, CwB≥1.6 rgba(61, 61, 61, 0.8) #000000 droid-b 1.610
α=0.9, rgb=var, CwB≥1.6 rgba(54, 54, 54, 0.9) #303030 droid-g 1.082
α=0.9, rgb=var, CwB≥1.6 rgba(54, 54, 54, 0.9) #2F2F31 pc-g 1.094
α=0.9, rgb=var, CwB≥1.6 rgba(54, 54, 54, 0.9) #000000 droid-b 1.605
α=1.0, rgb=var, CwB≥1.6 rgba(49, 49, 49, 1) #303030 droid-g 1.015
α=1.0, rgb=var, CwB≥1.6 rgba(49, 49, 49, 1) #2F2F31 pc-g 1.027
α=1.0, rgb=var, CwB≥1.6 rgba(49, 49, 49, 1) #000000 droid-b 1.614
α=var, rgb=255, CwB≥1.6 rgba(255, 255, 255, 0.19) #303030 droid-g 1.836
α=var, rgb=255, CwB≥1.6 rgba(255, 255, 255, 0.19) #2F2F31 pc-g 1.839
α=var, rgb=255, CwB≥1.6 rgba(255, 255, 255, 0.19) #000000 droid-b 1.601

The background change from #303030 to the darker #2F2F31 increases contrast as expected, but the change from #303030 to #000000 unintuitively decreases contrast. The calculation of contrast is difficult to intuitively understand because it's based on a ratio of luminance, but luminance is non-linear. The equations are defined at W3C: Contrast Ratio and W3C: Luminance (L). For my reference I also graphed the single-function mapping from R/G/B (sRGB) to R/G/B (for luminance) on Wolfram|Alpha here. And even though contrast is non-linear, alpha blending is done linearly. So when the background goes from dark-grey to black, the luminance barely decreases (e.g. 5%) even though the RGB values decrease significantly (e.g. 10%). When the foreground glow alpha is near 0 instead of near 1, it linearly maps the 10% RGB drop to the foreground glow, but this turns into (for example) a 20% drop in luminance.

You can see in the tables above that with the released v3.3 glow with alpha near 0, the black background actually has less contrast than the grey background, which is very non-intuitive. That's why I thought the glow was more visible against grey compared to black---because it actually was more visible.

With alpha near 1 like your example of alpha=0.8, the darker backgrounds do end up with more contrast, matching intuition. However, I think it's a good idea having the same contrast with glow-on-black as we do with shadow-on-white. Choosing rgba(61, 61, 61, 0.8) or rgba(49, 49, 49, 1) (aka #313131) both give mathematically the same contrast against black as shadow-on-white, so I would expect this combination to be fully visible:
box-shadow: 0 0 4px 1px rgba(61, 61, 61, 0.8);

But apparently I still seem to be missing something because when testing on my phone at minimum brightness, the glow is still invisible in the same condition where shadow-on-white is crystal-clear. Even though mathematically, these two should have the same contrast of 1.6. Increasing spread-radius to 2px definitely increases visibility, though only at low brightnesses. At minimum brightness it's still essentially invisible.

TLDR: Rather than matching a theme color, how about matching the contrast of the shadow-on-white? I'm not fully satisfied the results of this as it doesn't fix my issue on minimum brightness, but it does significantly increase contrast at the low brightnesses I more typically use. And it seems to be a better basis to me than the somewhat choice of matching theme color #CCC and α=0.2. This suggestion still keeps some alpha, is still symmetrical, is still being mostly invisible against a grey background, and seems to me to still have a low amount of "glowy", Note, I chose α=0.9 rather than α=0.8 because it further reduces visibility against grey.
box-shadow: 0 0 4px 1px rgba(54, 54, 54, 0.9);

I also wouldn't be opposed to increasing spread-radius to 2px, now that the glow is symmetrical and barely-visible against grey.

Lastly, it could be nice to apply this css only to flags and not also maps. It could be done easily enough by targeting flag in the attributes. Just a thought that came to me, I'm okay if this is not implemented.
.nightMode .value > img[src*="-flag"]:not([src*="-nobox"])

@aplaice
Copy link
Collaborator Author

aplaice commented Apr 18, 2020

Wow! That's incredibly comprehensive and also really fascinating!

(I had indeed also thought that the contrast was greater against the grey background than the black one, but I had been convinced that I was imagining it. The argument about non-linearity in luminance (but not alpha), as well as the calculated contrasts, have persuaded me, though!)

box-shadow: 0 0 4px 1px rgba(54, 54, 54, 0.9);

Testing this, it looks great (and works) under both backgrounds and most screen brightnesses! (Under the very lowest screen brightness on AnkiDroid, the glow-on-black still isn't visible, for me (like for you), though obviously that was also the case with the current configuration, and with this the "bad" range has shrunk from the lowest ~10% of brightness to the lowest ~5%.)

(Weirdly, unlike you, I do get ~ exactly the same appearance for rgba(54, 54, 54, 0.9) as for rgba(61, 61, 61, 0.8), in line with what would be naïvely expected.)

I also wouldn't be opposed to increasing spread-radius to 2px, now that the glow is symmetrical and barely-visible against grey.

With box-shadow: 0 0 4px 2px rgba(54, 54, 54, 0.9); the glow-on-black is visible at all brightnesses. However, the glow is also very strongly visible beside a blue flag (e.g. Marshall Islands or American Samoa). It looks rather weird and, even more importantly, it looks as if it's part of the flag itself (as if it has a grey border).

I'm not sure if there's a set of parameters which will allow the glow to be visible on a black edge, at all screen brightnesses, while not being strongly visible on a blue edge. Hence, I think that we either need to compromise between the "glow-on-black" not being visible at the lowest brightnesses and the glow being annoying against a dark-but-not-black flag, or constrain the glow to only be present for the flags that need it (have black elements that can "merge" with the background) and for them, dial it up.

Lastly, it could be nice to apply this css only to flags and not also maps. It could be done easily enough by targeting flag in the attributes. Just a thought that came to me, I'm okay if this is not implemented.
.nightMode .value > img[src*="-flag"]:not([src*="-nobox"])

Definitely! (It probably doesn't help much, as most of the maps have light edges against which the glow wouldn't be seen anyway, but the CSS is entirely clear/self-explanatory, so it doesn't hurt readability and possibly even improves it.)


TLDR; My vote would go to your suggestions:

.nightMode .value > img[src*="-flag"]:not([src*="-nobox"]) {
      box-shadow: 0 0 4px 1px rgba(54, 54, 54, 0.9);
}

or perhaps a targeted "-whitebox" approach.

@ukanuk
Copy link
Contributor

ukanuk commented Apr 18, 2020

Wow! That's incredibly comprehensive and also really fascinating!

Thank you, I enjoyed the rabbit hole of discovery as well!

(Weirdly, unlike you, I do get ~ exactly the same appearance for rgba(54, 54, 54, 0.9) as for rgba(61, 61, 61, 0.8), in line with what would be naïvely expected.)

Do you mean they look the same to you on a grey background? They have the same appearance on black (both have ~1.6 contrasts), but should have slightly different appearances on grey (1.08 versus 1.17 contrasts). It's not a lot, but on Anki Desktop if I set blur-radius to 0 and increase spread-radius to 20px, then I can see a clear distinction between the two. And once I've clearly seen it, I can still slightly see it at the 4px blur, 1px spread settings, at least on my system. Or it could be confirmation bias lol.

What surprises me is how different all our systems apparently are. I guess I shouldn't be surprised considering the variation I already see between my computer and phone, but I still am lol.

TLDR; My vote would go to your suggestions or perhaps a targeted "-whitebox" approach.

The [src*="-flag"] and -whitebox approach solve the same problem, so only one or the other should be implemented. In any case, adding -whitebox to the small number of relevant files is not unreasonable. However, I am concerned that if -whitebox only appears on certain flags, some people might be confused into thinking it's part of the flag itself. Just like you were concerned about people thinking the American Samoa flag has a grey border if we set spread-radius to 2px.

@axelboc
Copy link
Collaborator

axelboc commented Apr 18, 2020

Yeah, I wouldn't recommend the -whitebox approach as it would apply to way too many flags.

I actually think keeping a box shadow on all flags (and maps?) is a good idea for visual consistency... unless it's particularly unappealing? Removing the shadow with -nobox was worth the inconsistency because it definitely wasn't appealing when the shadow didn't match the outline.

@aplaice
Copy link
Collaborator Author

aplaice commented Apr 18, 2020

I've made a pull request with what I think is closest to the current consensus:

.nightMode .value > img:not([src*="-nobox"]),
.night_mode .value > img:not([src*="-nobox"]) {
  box-shadow: 0 0 4px 1px rgba(54, 54, 54, 0.9);
}

but please feel free to tear this apart. :)


Clearing up my misreading and random musings on luminance

Do you mean they look the same to you on a grey background? They have the same appearance on black (both have ~1.6 contrasts), but should have slightly different appearances on grey (1.08 versus 1.17 contrasts). It's not a lot, but on Anki Desktop if I set blur-radius to 0 and increase spread-radius to 20px, then I can see a clear distinction between the two. And once I've clearly seen it, I can still slightly see it at the 4px blur, 1px spread settings, at least on my system. Or it could be confirmation bias lol.

when testing on my phone at minimum brightness, the glow is still invisible in the same condition where shadow-on-white is crystal-clear. Even though mathematically, these two should have the same contrast of 1.6.

Sorry, I'm a total idiot — I was in a bit of a hurry but still wanted to respond, and misread that section (I completely missed the part about shadow-on-white and illogically assumed you were referring to the variation in alpha from the previous paragraph). (In my reply I had meant that they look the same with a black background, which they obviously have to. FWIW with the grey background they look the same to me at 1px blur, though I see the distinction at 20px.)

Replying to what you had previously actually written (rather than what I imagined) regarding the difference in visibility of glow-on-black vs. shadow-on-white, at low brightness, despite the contrast being technically the same — I also see shadow-on-white well, at the lowest brightness, while not seeing glow-on-black.

I guess it depends exactly on how screen brightness maps onto actual luminance, and how well actual luminance maps onto "W3 luminance". Assuming that screen brightness maps linearly onto the actual luminance of any given pixel and that the actual luminance maps linearly onto "W3 luminance" (with a white pixel, at maximum screen brightness, having a "W3 luminance" of 1), then I think that the discrepancy in glow-on-black vs. shadow-on-white that we observe is due to the 0.05 term in the contrast ratio.

In the case of shadow-on-white, at full screen brightness, L1w=1 while L2w(≈0.6) is such that (L1w + 0.05) / (L2w + 0.05) = 1.6 — both L1w and L2w are much larger than 0.05, so they "dominate" the contrast ratio (the contrast ration is close to just L1w/L2w). In the case of glow-on-black, at full brightness, L2b=0 while L1b(≈0.03) is again such that the contrast is 1.6, but now the 0.05 is the only term in the denominator, and it's about as important as L1b in the numerator. When the screen brightness is decreased, L1w, L2w and L1b are all scaled down by the same factor (since that's how we're modelling the effect of screen brightness — I can't think of anything better). The shadow-on-white contrast ratio decreases only slightly, since both L1w and L2w are still larger than 0.05, but the glow-on-black contrast ratio almost drops to 1, since L1b is now much smaller than 0.05 and L2b is still 0 (so we have (0.05 + L1b)/0.05→1)

These are obviously just my rather random thoughts...

@ukanuk
Copy link
Contributor

ukanuk commented Apr 19, 2020

I think your PR is good. Maybe someone else will find an even better solution in the future, but it's better than the existing styling imo and the best we've come up with, so I'm content.

For reference, I count 39 flags with black edges that would need -whitebox if we went with that modification:

  1. Afghanistan
  2. Angola
  3. Antigua and Barbuda
  4. Belgium
  5. Botswana
  6. Brunei
  7. Ceuta
  8. Dominica
  9. East Timor
  10. Egypt
  11. Estonia
  12. Germany
  13. Guyana
  14. Iraq
  15. Jamaica
  16. Jordan
  17. Kenya
  18. Kuwait
  19. Libya
  20. Malawi
  21. Mozambique
  22. Palestine
  23. Papua New Guinea
  24. Sahrawi Arab Democratic
  25. Saint Kitts and Nevis
  26. South Africa
  27. South Sudan
  28. Sudan
  29. Syria
  30. Tanzania
  31. The Bahamas
  32. Trinidad and Tobago
  33. Uganda
  34. United Arab Emirates
  35. Vanuatu
  36. Yemen
  37. Zambia
  38. Zanzibar
  39. Zimbabwe

@ukanuk
Copy link
Contributor

ukanuk commented Apr 19, 2020

I actually think keeping a box shadow on all flags (and maps?) is a good idea for visual consistency... unless it's particularly unappealing?

I find the current glow particularly unappealing on the map of Melilla. On the other maps I didn't notice it as much, and with the new proposed glow I pretty much don't notice it at all.

I also think the visual consistency goals of light and dark mode don't necessarily need to be the same. In light mode the shadow looks good on all rectangular images, and happens to be necessary to add contrast to some flags with white borders. In night mode, glow would ideally be completely unnecessary, but it's necessary for some flags with black borders.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
structure Templates, tags, generated decks, etc.
Development

Successfully merging a pull request may close this issue.

3 participants