I’ve written about this code in Customizing Zulip CSS Dark Mode. You can also just grab the gist here, which is fully documented.
zulip-dark-sri.css
This is my live CSS file, which should mirror the public gist if I haven’t goofed something up.
/*/
Sri's Dark Mode Zulip Desktop Custom CSS
Makes default dark mode theme hurt Sri's eyes less!
blog post: https://dsriseah.com/journal/2026/0226/
-
Inspired by github.com/botder/zulip-discord-css
Tested on Zulip Desktop Mac v5.12.3
License: MIT
** THESE OVERRIDES ARE TUNED FOR DARK MODE **
** JANKY LIGHT MODE JUST FLIPS FG AND BG **
TO USE THE FILE
1. first save this css file somewhere on your computer
2. go to "Desktop Settings" menu then general->advanced settings
3. upload the css file
TO SEE CHANGES AS YOU MAKE THEM
1. edit the base colors at the top of the file
2. after saving changes, command-r to reload app
REFERENCES
github.com/zulip/zulip/.../web/styles/*
github.com/zulip/zulip/.../web/templates/*
In particular, web/styles/app_variables.css lists the
semantic global vars that are redefined in this css
/*/
:root {
/* default base colors */
--color-sri-dark: hsl(225 4% 20%); /* a dark gray-blue */
--color-sri-lite: hsl(225 0% 83%); /* a light gray */
--color-sri-dmbg: hsl(250 40% 40%); /* a purple */
--color-sri-dark-top: hsl(240 29% 14%); /* deep blue-purple */
--color-sri-dark-bot: hsl(222 46% 17%); /* bottom lighter */
/* - - - derived values only after this point - - - */
/* janky light-dark theme support */
--sri-bg: light-dark(
var(--color-sri-lite), /* light mode: light gray background */
var(--color-sri-dark) /* dark mode: dark gray-blue background */
);
--sri-fg: light-dark(
var(--color-sri-dark), /* light mode: dark text on light bg */
var(--color-sri-lite) /* dark mode: light text on dark bg */
);
--sri-dm: light-dark(
oklch(from var(--color-sri-dmbg) calc(l + 0.25) calc(c - 0.05) h),
var(--color-sri-dmbg)
);
--sri-bold: light-dark(
oklch(from var(--color-sri-dark) calc(l - 0.4) c h),
oklch(from var(--color-sri-lite) calc(l + 0.5) c h)
);
/* derived colors using perceptually accurate color calculations */
--sri-bg-lighter: oklch(from var(--sri-bg) calc(l + 0.05) c h);
--sri-bg-lighter-hover: oklch(from var(--sri-bg-lighter) calc(l + 0.05) c h);
--sri-bg-darker: oklch(from var(--sri-bg) calc(l - 0.03) c h);
--sri-bg-darker-hover: oklch(from var(--sri-bg-darker) calc(l - 0.05) c h);
}
/* - - - ZULIP COLOR OVERRIDES - - - */
:root {
/* bg overrides inherited by sidebars */
--color-background: var(--sri-bg) !important;
/* hilite overrides used for selected/hovering over sidebar bg items */
--color-background-hover-narrow-filter: var(--sri-bg-lighter-hover) !important;
--color-background-active-narrow-filter: var(--sri-bg-lighter) !important;
/* bg overrides for stream and dms message blocks in center column */
--color-background-stream-message-content: var(--sri-bg-darker) !important;
--color-background-private-message-content: var(--sri-bg-darker) !important;
/* bg overrides for the compose box at the bottom of center column */
--color-compose-box-background: var(--sri-bg-lighter) !important;
/* overrides for compose buttons when the compose box is minimized */
--color-compose-collapsed-reply-button-area-background: var(--sri-bg) !important;
--color-compose-collapsed-reply-button-area-border: transparent !important;
--color-compose-embedded-button-background: var(--sri-bg) !important;
--color-background-compose-new-message-button: var(--sri-bg) !important;
--color-background-compose-new-message-button-hover: var(--sri-dm) !important;
--color-border-compose-new-message-button: transparent !important;
--color-border-compose-new-message-button-active: transparent !important;
/* overrides for DM header to make it distinct */
/* note: stream messages inherit bg color from their channel color, so no override for that */
--color-background-private-message-header: var(--sri-dm) !important; /* DM pane */
/* override for message text color to make it less jarring */
--color-text-message-default: var(--sri-fg) !important;
/* hyperlink color overrides to improve contrast */
--color-text-url: var(--color-text-url-hover) !important; /* make link same as hover */
--color-markdown-link: var(--color-text-url) !important;
--color-markdown-code-link: var(--color-text-url) !important;
/* remove border visual noise by making them transparent */
--color-message-list-border: transparent !important;
--color-message-header-contents-border: transparent !important;
--color-message-header-contents-border-bottom: transparent !important;
--color-private-message-header-border: transparent !important;
--color-private-message-header-border-bottom: transparent !important;
--color-border-compose-content: transparent !important;
--color-message-content-container-border: transparent !important;
--color-message-content-container-border-focus: transparent !important;
--color-compose-recipient-box-border-color: transparent !important;
--color-compose-recipient-box-hover: transparent !important;
--color-compose-recipient-box-has-focus: transparent !important;
/* declutter message emoji reaction styles */
--color-message-reaction-border: transparent !important;
--color-message-reaction-border-reacted: transparent !important;
--color-message-reaction-button-border: transparent !important;
--color-message-reaction-button-border-hover: var(--sri-bg-lighter) !important;
--color-message-reaction-background-hover: var(--sri-bg-lighter-hover) !important;
--color-message-reaction-background: var(--sri-bg-lighter) !important;
--color-message-reaction-background-reacted: var(--sri-bg-lighter) !important;
}
/* - - - ZULIP CSS OVERRIDES - - - */
/* fix DM component divider transparency */
.direct-message-section-bottom-divider-container {
background-color: transparent !important;
}
/* make bold words bolder relative to text default */
.message_content strong {
color: var(--sri-bold);
}
/* - - - UNDER DEVELOPMENT - - - */
/* optional: make background have luscious purple gradient */
body {
/* background-image: linear-gradient(to bottom, var(--color-sri-dark-top), var(--color-sri-dark-bot)) !important;
background-attachment: fixed !important; */
}
/* optional, make background of center darker */
#main-div {}
/** headers for channels */
.stream-list-subsection-header {
/* background-color: transparent !important; */
}
/* background of left-column search bar */
#left-sidebar-search {
/* background-color: cyan !important; */
}