Doing dark theme right is hard, especially the details. For example, the âtoggleâ border when disabled. Similar issues with alerts, popovers etcâŠ
Changing themes and colors is now much easier in Ionic4 and we have seen some really good samples and examples posted by other developers and even Ionic team members with dark themes, and toggling between dark and light themes. We have tried to combine some of these into our apps to get a dark theme, but it is hard to get all the details right.
Are there any plans for default dark theme colors in Ionic? Now that the OS has its own dark theme, it will be even better to pick the same iOS/Android default dark colors instead using just another shade of gray.
Hi there,
Ionic does ship with a "dark" color palette. For most components, you can do color="dark"
as a property on the component. Does this address your use case?
Thanks!
We don't have plans to add a dark theme at the moment, but it is something that could easily be done in the starters. We have a dark theme added in the conference app, and plans to include a "toggle" to switch between light and dark theme there. It wouldn't be too much more to have it added to the starters.
https://github.com/ionic-team/ionic-conference-app/blob/master/src/theme/variables.scss#L198-L243
@liamdebeasi This is more about application wide dark mode. Similar to what @mhartington described here: https://ionicframework.com/blog/hot-take-dark-mode/
@brandyscarney A lot more needs to be done to make it truly complete. Like we also need to swap the 'dark' and 'light' colors or just use a different set of colors for all colors including primary, secondary etc... to match whatever colors iOS13 and Android10 are defaulting to in their native dark themes.
There are issues with borders of some controls like toggles as described above, and also with borders and background colors of alerts, popovers, action-sheets when trying to make everything dark. Currently they just 'blend' in too much with the content dark background - almost invisible.
Having a toggle in the sidebar to let user switch between light and dark themes will be great. Bulk of the users are not going to be on the latest OS release for a long time, and some may want to change settings per app.
A lot of it can be implemented at the application level and we have been trying to implement this by modifying the theme/variables.scss. But not everything can be fixed there. Moreover it seems like something that will help all Ionic applications.
A lot more needs to be done to make it truly complete. Like we also need to swap the 'dark' and 'light' colors or just use a different set of colors for all colors including primary, secondary etc... to match whatever colors iOS13 and Android10 are defaulting to in their native dark themes.
@sachingarg05 Why would we swap the dark and light colors? You may still have use for a light color or a dark color on a dark theme. You can override the colors though if desired, it would look like the following:
@media (prefers-color-scheme: dark) {
:root {
--ion-color-primary: #3880ff;
--ion-color-primary-rgb: 56, 128, 255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255, 255, 255;
--ion-color-primary-shade: #3171e0;
--ion-color-primary-tint: #4c8dff;
}
}
These colors are meant to be customized, but they don't match either iOS or Android by default. The primary color is the Ionic blue.
There are issues with borders of some controls like toggles as described above, and also with borders and background colors of alerts, popovers, action-sheets when trying to make everything dark. Currently they just 'blend' in too much with the content dark background - almost invisible.
If there are any specific issues with dark theme variables not working to override specific components we can fix it but we need to have issues reported to track this. I recently fixed this issue regarding the overlay background color: https://github.com/ionic-team/ionic/issues/18658
Here's how I see our dark theme in MD mode:
I don't see it blending here, but if there are specific cases where it does we can look into it.
The way the defaults for dark theme work is by looking at the default light color. For example, alert's background uses #f9f9f9
in ios
light theme. So we look at what "step" color of the background is closest to that, as documented here: https://ionicframework.com/docs/theming/advanced#stepped-colors
The closest is step 50, so we use the --ion-color-step-50
for the alert background. If using dark mode, it would be whatever you set in your theme file, such as:
--ion-color-step-50: #232323;
--ion-color-step-100: #2e2e2e;
--ion-color-step-150: #3a3a3a;
--ion-color-step-200: #454545;
--ion-color-step-250: #515151;
--ion-color-step-300: #5d5d5d;
--ion-color-step-350: #686868;
--ion-color-step-400: #747474;
--ion-color-step-450: #7f7f7f;
--ion-color-step-500: #8b8b8b;
--ion-color-step-550: #979797;
--ion-color-step-600: #a2a2a2;
--ion-color-step-650: #aeaeae;
--ion-color-step-700: #b9b9b9;
--ion-color-step-750: #c5c5c5;
--ion-color-step-800: #d1d1d1;
--ion-color-step-850: #dcdcdc;
--ion-color-step-900: #e8e8e8;
--ion-color-step-950: #f3f3f3;
These can be manipulated to use lighter or darker colors or have more variation, or you can use our generator here that uses the same formula as we do for the light colors: https://ionicframework.com/docs/theming/advanced#generate-stepped-color-variables
In the case of the toggle, it is using the proper colors between light and dark, but the box-shadow isn't updated for dark theme. Notice the difference (top one using a box shadow that is light):
Here's light theme if the box-shadow was the same:
Thanks, I understand this better now. Looks like some of our issues can be resolved by fixing our --ion-color-step values. We had just copied the step values from someone's sample code and the step-50 was less than our chosen background gray.
Will report any specific issues that we can't resolve using variables.scss and step colors. I do feel that the variables.scss in "Ionic start" templates should include a dark theme section, even if its commented out by default.
For toggle shadow color, can this be fixed by us in our application - in variables.scss or a parameter when creating the toggle? Or do you plan to change the shadows for toggle (and other components) to use one of the step color values?
By swapping the dark and light colors, I meant that in light theme - light is the low-contrast color (closest to background color) and dark is the high-contrast color (opposite of background color).
If we only change background color to dark, then a light becomes the high contrast color and dark becomes the low contrast color.
So in our apps in dark theme, we would want light buttons to look 'dark' and the dark buttons to look light. To maintain same contrast effect as they did in light theme. I understand that we can fix this in our app by changing the colors in media-query in theme/variables.scss.
Ah, okay! Yeah, if the stepped colors aren't set to a gradient going from the background -> text color it will look off by default.
Will report any specific issues that we can't resolve using variables.scss and step colors. I do feel that the variables.scss in "Ionic start" templates should include a dark theme section, even if its commented out by default.
I agree with this, but I'd like to work through fixing some of the bugs and making sure all of the defaults are good before we add it so that it doesn't need several iterations.
For toggle shadow color, can this be fixed by us in our application - in variables.scss or a parameter when creating the toggle? Or do you plan to change the shadows for toggle (and other components) to use one of the step color values?
I believe it would need to be updated in Ionic. The box-shadow uses a value of:
0 3px 12px rgba(0, 0, 0, .16), 0 3px 1px rgba(0, 0, 0, .1)
So it needs to be something like:
0 3px 12px rgba(var(--ion-text-color-rgb, 0, 0, 0), .16), 0 3px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), .1)
This would make the box shadow use the RGB text color variable by default with a fallback of 0, 0, 0
.
By swapping the dark and light colors, I meant that in light theme - light is the low-contrast color (closest to background color) and dark is the high-contrast color (opposite of background color).
This makes sense. I'm not sure if it should be something we provide by default but I can definitely see the use case for it.
Actually, after revisiting iOS 13's styles, it seems they keep the toggle icon the same color in dark mode:
This may be a case where we need to individually compare components against native.
I started on some fixes here: https://github.com/ionic-team/ionic/pull/18735
Here's a preview:
@brandyscarney So based on your answer we do need to reverse our steps if we switch to a dark theme? Or is it better to make our light to dark and our dark to light? What is considered best practice here?
After talking with our designer, we decided we would be switching the light
and dark
colors as @sachingarg05 suggested. The stepped colors do need to be reversed if you're going from
background: white -> black
text: black -> white
This can be generated for you in the documentation though, here: https://ionicframework.com/docs/theming/themes#stepped-color-generator
We're currently working on the dark theme. Our designer provided some new Ionic colors and I have been tweaking some of the bugs in the components as I've found them in this PR here: https://github.com/ionic-team/ionic/pull/18735
Here's the latest design:
Using the following variables:
:root {
--ion-color-primary: #428CFF;
--ion-color-primary-rgb: 66,140,255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255,255,255;
--ion-color-primary-shade: #3a7be0;
--ion-color-primary-tint: #5598ff;
--ion-color-secondary: #50C8FF;
--ion-color-secondary-rgb: 80,200,255;
--ion-color-secondary-contrast: #ffffff;
--ion-color-secondary-contrast-rgb: 255,255,255;
--ion-color-secondary-shade: #46b0e0;
--ion-color-secondary-tint: #62ceff;
--ion-color-tertiary: #6A64FF;
--ion-color-tertiary-rgb: 106,100,255;
--ion-color-tertiary-contrast: #ffffff;
--ion-color-tertiary-contrast-rgb: 255,255,255;
--ion-color-tertiary-shade: #5d58e0;
--ion-color-tertiary-tint: #7974ff;
--ion-color-success: #2FDF75;
--ion-color-success-rgb: 47,223,117;
--ion-color-success-contrast: #000000;
--ion-color-success-contrast-rgb: 0,0,0;
--ion-color-success-shade: #29c467;
--ion-color-success-tint: #44e283;
--ion-color-warning: #FFD534;
--ion-color-warning-rgb: 255,213,52;
--ion-color-warning-contrast: #000000;
--ion-color-warning-contrast-rgb: 0,0,0;
--ion-color-warning-shade: #e0bb2e;
--ion-color-warning-tint: #ffd948;
--ion-color-danger: #FF4961;
--ion-color-danger-rgb: 255,73,97;
--ion-color-danger-contrast: #ffffff;
--ion-color-danger-contrast-rgb: 255,255,255;
--ion-color-danger-shade: #e04055;
--ion-color-danger-tint: #ff5b71;
--ion-color-dark: #F4F5F8;
--ion-color-dark-rgb: 244,245,248;
--ion-color-dark-contrast: #000000;
--ion-color-dark-contrast-rgb: 0,0,0;
--ion-color-dark-shade: #d7d8da;
--ion-color-dark-tint: #f5f6f9;
--ion-color-medium: #989AA2;
--ion-color-medium-rgb: 152,154,162;
--ion-color-medium-contrast: #000000;
--ion-color-medium-contrast-rgb: 0,0,0;
--ion-color-medium-shade: #86888f;
--ion-color-medium-tint: #a2a4ab;
--ion-color-light: #222428;
--ion-color-light-rgb: 34,36,40;
--ion-color-light-contrast: #ffffff;
--ion-color-light-contrast-rgb: 255,255,255;
--ion-color-light-shade: #1e2023;
--ion-color-light-tint: #383a3e;
}
/* Customize the Toolbar Segment by Mode */
.ios {
--ion-background-color: #000000;
--ion-background-color-rgb: 0,0,0;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255,255,255;
--ion-border-color: #222222;
--ion-color-step-50: #0d0d0d;
--ion-color-step-100: #1a1a1a;
--ion-color-step-150: #262626;
--ion-color-step-200: #333333;
--ion-color-step-250: #404040;
--ion-color-step-300: #4d4d4d;
--ion-color-step-350: #595959;
--ion-color-step-400: #666666;
--ion-color-step-450: #737373;
--ion-color-step-500: #808080;
--ion-color-step-550: #8c8c8c;
--ion-color-step-600: #999999;
--ion-color-step-650: #a6a6a6;
--ion-color-step-700: #b3b3b3;
--ion-color-step-750: #bfbfbf;
--ion-color-step-800: #cccccc;
--ion-color-step-850: #d9d9d9;
--ion-color-step-900: #e6e6e6;
--ion-color-step-950: #f2f2f2;
--ion-item-background: #1c1c1e;
--ion-item-background-activated: #19191a;
}
.md {
--ion-background-color: #121212;
--ion-background-color-rgb: 18,18,18;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255,255,255;
--ion-border-color: #222222;
--ion-color-step-50: #1e1e1e;
--ion-color-step-100: #2a2a2a;
--ion-color-step-150: #363636;
--ion-color-step-200: #414141;
--ion-color-step-250: #4d4d4d;
--ion-color-step-300: #595959;
--ion-color-step-350: #656565;
--ion-color-step-400: #717171;
--ion-color-step-450: #7d7d7d;
--ion-color-step-500: #898989;
--ion-color-step-550: #949494;
--ion-color-step-600: #a0a0a0;
--ion-color-step-650: #acacac;
--ion-color-step-700: #b8b8b8;
--ion-color-step-750: #c4c4c4;
--ion-color-step-800: #d0d0d0;
--ion-color-step-850: #dbdbdb;
--ion-color-step-900: #e7e7e7;
--ion-color-step-950: #f3f3f3;
--ion-item-background: #1A1B1E;
}
This is not finalized, but when it is we will add it to the conference app and once we're satisfied with it we will add it to the starters as a toggle.
A few observations, all for the iOS theme (MD theme looks OK):
1) The empty white circle for Unchecked by Default checkmark isnât visible enough. Maybe the circle color is too dark or the circle line is too thin.
2) The light-gray background inside the Blueberry off toggle, doesnât have enough contrast with the background gray. I compared with the iOS13 screenshot you posted above and there is a small color difference. #303032 in your ionic screenshot vs #3B393F in your iOS13 screenshot.
Not sure if these need attention, maybe its OK the way it is:
1) The filled-gray circle around âLightâ checkmark has almost the same color as background.
2) The toggle handle is now white (text-color) which looks great everywhere except for the âlightâ toggle Blackberry. The handle is almost not visible inside the toggleâs filled area, not enough contrast in color or not enough shadow.
Thanks a lot for all the effort you are putting into this.
A few observations, all for the iOS theme (MD theme looks OK):
I fixed the checkmark, but the toggle is due to us having to match light mode first. We can use an rgba
of the text color, but that only has it looking perfect in light mode. In order to match their #E9E9E9
in light theme our dark theme becomes:
Ours uses #303030
Native iOS uses #393939
Not sure if these need attention, maybe its OK the way it is:
Our Ionic colors will not always look great on top of every background. It is up to you to design your app to only use colors where appropriate. Just like in a light theme application, you could have a dark header that you want a light checkbox on, for example, where it would be visible.
There is no way for us to provide extra contrast based on the color, unless we were to use the contrast of the color but then it becomes a black knob and goes against the iOS standard. I think this is still fine because even in iOS 12 they used a white knob on a white background, and the "off" and "on" states are completely different.
Here's a dev release of the fixes from #18735 if you'd like to try it out:
in Core
npm i @ionic/[email protected]
in Angular:
npm i @ionic/[email protected]
@brandyscarney what is generating those screenshots that you are posting showing the different themes? Is this just a demo app or something else? This would be SUPER useful for us when theming apps for different projects if it's something we can get access to.
Thanks!!
@ghenry22 It's one of our e2e tests, here: https://github.com/ionic-team/ionic/tree/master/core/src/themes/test/css-variables
@ghenry22 It's one of our e2e tests, here: https://github.com/ionic-team/ionic/tree/master/core/src/themes/test/css-variables
Awesome thanks!
@ghenry22 It's one of our e2e tests, here: https://github.com/ionic-team/ionic/tree/master/core/src/themes/test/css-variables
Really nice design đ
I started messing around with ideas for how we can provide the official dark theme to the developers. There are a few different ways we could add this.
1) We could expose a CSS class that has the CSS set for ios
and md
, something like ion-dark-theme
. This would include the CSS I linked here, but instead of using :root
it would target .ion-dark-theme
: https://github.com/ionic-team/ionic/issues/18713#issuecomment-510644371
- Problem 1: there would be less control over the variables as a developer so you would have to know what to change if you wanted to tweak it
- Problem 2: it wouldn't work with prefers-color-scheme in the CSS, the developer would have to set the class via JavaScript, however this can be done by setting a variable in the media query and changing the class that way.
2) We could expose a Sass mixin that can be used to include the relevant variables in a project, see https://www.sassmeister.com/gist/9e68689abc4ffd0b514e933da98379a0
- Problem 1: Same as 1, less control
- Problem 2: Not all users are using CSS, they would need an alternative
3) We could add the CSS variables / themes directly to the starters so that developers would have our provided styles for a dark theme and full control over changing them.
- Problem: Any updates to the dark theme would have to be manually copied as a developer from the starter when it changes, plus we would have to update each of them every time.
Let me know if anyone has ideas I'm missing!
IMO this could just be put into the documentation with the other generator stuff:
https://ionicframework.com/docs/theming/color-generator
Top option could be light vs dark.
This way you're not adding bloat to the framework and it all still fits with convention. I would definitely use this and would have found it in the documentation without any issues.
Thanks for the feedback @CitizenBeta! I agree, I think it would be easier maintenance to have a docs page devoted to theming in dark mode and maybe some demos to show it off. I put together this Codepen on our official Ionic account: https://codepen.io/ionic/pen/zYOpQLj
I created a new guide for dark mode in the docs in this PR: https://github.com/ionic-team/ionic-docs/pull/940
Here is the main file in a README format: https://github.com/ionic-team/ionic-docs/blob/3e76eac99772bb2921b33912a04d9e1290688225/src/pages/theming/dark-mode.md
Please let me know any feedback of how this can be improved, anything missing, and anything else. Thank you!
Added a guide on dark mode here: https://ionicframework.com/docs/theming/dark-mode
Please let us know if you have any feedback for docs improvement on this repo: https://github.com/ionic-team/ionic-docs
Thank you!!
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.
Most helpful comment
I started on some fixes here: https://github.com/ionic-team/ionic/pull/18735
Here's a preview: