Implementing Dark Mode
Recently we implemented our dark mode theme in our iOS and Android apps. Our initial process wasn’t a piece of cake as we expected it will be. When we first started, we didn’t have Apple’s Dark Mode Guidelines, nor the Material Design Dark Mode to help us better understand how things are done. It took us a few months of research, design & development to release the very first version of it. Now, we are here to share our conclusions and main focus points during the project. The what, how, and why of few of the obstacles we ran into, while sharing the relevant resources we’ve found along the way. But before we jump right in, you might wonder what dragged us into that project?
Why Dark Mode?
A lot of people questioned this decision to implement a dark mode, from inside and outside of the company. I guess I can understand their agenda — We just have better things to worry about. Sure, we could have spent some more time improving retention rate, and the overall metrics aren’t going to raise themselves. But, we had a few things in mind at the beginning of the project that led us to it. The basic advantages of a dark mode are focused on Battery consumption (For OLED screens), reducing eye strain, and better accessibility for certain populations. The fact that the dark mode is on the rise and we wanted to join the parade! None of our competitors have done anything similar yet and we wanted to be the first ones to do so. It may be a bit childish, but I can see the value in it. The last thing is… well… we were convinced it will take us much less time than it eventually did. Whoops 😅.
It took us about 4 months of iterations with devs, product managers and the design team. Of course, it wasn’t our main focus during all that time, so probably not everybody felt the same, but as the designer in charge of this project, I could have felt it stretches way out of what I thought it will. I would suggest you avoid over-iterating these kinds of projects, especially when the ‘why’ wasn’t as strong as it usually is. However, putting this aside, let’s go through the steps we went to achieve our desired dark theme.
Start with the Color Palette
We spent some time examining our color palette in different background colors, trying to understand the contrast and accessibility implications of these. Other than changing saturations and other modifications you can find in Material guidelines and plenty of articles, we also tried to maintain a reversible grey-palette. But what does it even mean?
For example, let’s take our highlighted colors (1.0). I choose these on purpose because of its sensitive character. They’re used mainly for visual add-ons, which means we have to be very strict with its appearance on the screen. The shade of white at the top has a 1.1 contrast-ratio with it’s white BG, while the shade of black at the bottom has a 1.3 contrast ratio with it’s black BG. These similarities among shades allowed us to easily swap them when shifting from dark and light modes, no matter if it was a text color or a border color. We also applied a ‘Mid-Color’, used in many places across the product, that has sufficient contrast ratio with both backgrounds. That way we could avoid too many color swaps between themes and make the devs life a bit easier.
Don’t use fully negative display — Which means don’t put fully white(#FFF) texts on black(#000) backgrounds. Yes, the dark mode reduces eye strain, but when fully negative displayed, it also damages the readability of the content and can create smearing and halation effect. We made this mistake during the re-coloring process, and we are already working on changing it. For now, however, it didn’t seem important enough to hold us back from rolling it out. Moving on.
Cross-functional Assets
In a strong recommendation from our devs, we decided not to create a second set of icons for the dark mode. The concerns were on our side as well. Other than the fact that BE will have to support 2 sets of icons and pull them by theme, we wondered how can we even maintain such an approach — It’ll require us to double our work on every asset we create.
So, our alternative was simple — dividing the icons and assets into 2 groups. The first group, One-Color icons, will be recolored within the code using tint
according to the reversible color palette guidelines. The second group, Multi-Color icons, can’t be overwritten within the code, so we had to deal with them in one of these two ways.
Color Blocks — We changed many multi-color icons to fit both themes by turning them into an inverted version of themselves. The inverted icon used the same dominant color as the original icon (2.0). That way, we provided sufficient contrast and legibility for each icon without having to manually adjust it within an SVG or providing an alternative for dark mode specifically. We also took the chance to simplify and polish our set of icons.
Transparency & Neutral Colors — For most of our illustrations and more complex assets across our product, we used neutral colors to fit both dark and light themes. Apply the right level of transparency on these colors and you can find yourself with a nice cross-functional asset that can deliver a very similar visual result within two different environments (2.1).
Elevations
The Material Guidelines mentions how to apply elevation within its system — the general approach is to add a white-overlay-layer with a certain level of transparency, depends on the elevation level (3.0). This approach will create elevations in different hues than the hues on our palette, but this shouldn’t be a problem by itself. Our problem is that our iOS team didn’t support this approach, it uses dynamic colors instead, as Apple recommended in its latest WWDC. Don’t see the problem yet?
If we used dynamic colors in iOS, it will mean that our blue-hued palette is applied on elevated surfaces. If we used the pre-defined Android elevation approach, we will have greyscaled elevation in android, and a difference between the platforms.
The elevation system needs to be visually aligned on iOS and Android, even if it’s not technically aligned. So, our first thought was to change the color of the overlay-layer to a more suitable one. A color that will create the same hued elevation as we get in iOS using our palette. Apparently, none of our palette’s light-colors was suitable to create the right hues using these level of transparency. We got stuck, and the solution came from an unexpected direction.
Surprisingly, one of our devs came up with the idea we should take one of the palette’s darker-colors, and subtract black (3.1) out of it. When it was tested with the predefined transparency levels Android are providing, the results were very similar to what we had on iOS. You can see the different results we got between white overlay the light blue one (3.0). Now we were ready to hold both approaches and achieve the same result on the different platforms.
Conclusions
Dealing with the dark mode really made us dive into the anatomy of user interfaces in levels we’ve never experienced before, and forced us to think of our design system in a much broader view. I can only guess it is a matter of time until designers should be able to fully control and maintain these two approaches one next to each other. We hope we made you one step closer to it, as this whole process made us.
For any questions, notes, mistakes that I might have, or bits of advice— you’re more than welcome to email me:
aviv@gojuno.com