Instantly share code, notes, and snippets.

Embed
What would you like to do?
Theming Slack for OSX

Theming Slack for OSX

So, you love Slack, but you hate applications with large white backgrounds? Why not use Dark Mode!

Unfortunately, Slack does not have a Dark Mode, although it's on their list of possibilities.

But, don't fret - there is a solution! Because the slack native desktop apps are just wrappers around a web app, we can inject our own CSS to customize the application to our liking.

How to (OSX Only)

Prerequisite Your custom CSS needs to be hosted somewhere accessible over HTTP. For a free option, you can use a Gist and use the link to the raw file.

  1. Open up Slack.app, and navigate to any message;
  2. In the message input field, enter /macgap.app.enabledevelopertools(), and press enter
  3. Right click any element in the app (except the team switcher on the left), and choose Inspect Element
  4. Open the Console tab
  5. Run the following snippet of JavaScript in your console, replacing the value of cssURI with the URI that points to your custom stylesheet.
// Using ajax rather than a dynamically injected <link>, to account for sites (like gist.github.com) that don't serve
// a content-type for CSS files
var cssURI = 'https://gist.githubusercontent.com/DrewML/f244d6015c9b690b1dc241669b69dde1/raw/3d6351b8767ee5fba1ac86cad9b8cc5cf2ff9fea/slack-theme.css';
$.get(cssURI).then(function(css) {
   $('<style />').text(css).appendTo('body')
});

Example Dark Theme

image

Writing your own theme

If you know the basics of CSS and browser developer tools, writing a theme should be a breeze. You can either use the Developer Tools exposed in the Slack application itself, or you can visit https://{myteamhere}.slack.com/messages and use the browser dev tools of your choosing.

The part that's a bummer

Because you're just injecting styles in the DOM, this means that your changes do not persist when you exit and re-open the application. However, the Developer Tools will remember the last code you executed, so it should be a few keystrokes to open the panel and re-run your injection script.

@kfix

This comment has been minimized.

kfix commented Aug 23, 2016

Thanks for gisting, this is awesome!

@thilluh

This comment has been minimized.

thilluh commented Sep 21, 2016

Noice!

@marrodriguez

This comment has been minimized.

marrodriguez commented Oct 28, 2016

sadly, this no longer works on the updated 2.3.1 Slack app for Mac (Mac 10.11)

@dhruveonmars

This comment has been minimized.

dhruveonmars commented Nov 10, 2016

Any way to get this to work on 2.3.1 ?

@orekasep

This comment has been minimized.

orekasep commented Dec 7, 2016

Unfortunately, this no longer works on the 2.3.3 Slack for Mac

@Cisneiros

This comment has been minimized.

Cisneiros commented Jan 11, 2017

To get the developer tools, set the SLACK_DEVELOPER_MENU environment variable to true. (On a macOS: http://stackoverflow.com/a/14285335)

@armen52

This comment has been minimized.

armen52 commented Jan 22, 2017

This doesn't seem to work anymore. I get this error in the console:
VM1015:2 Uncaught TypeError: $.get is not a function(…)

They may have stopped using/including jQuery?

@reimertz

This comment has been minimized.

reimertz commented Jan 24, 2017

this injects the css but it seems they have sandboxed views into webviews so it doesn't affect anything. :(

const cssURI = 'https://gist.githubusercontent.com/DrewML/f244d6015c9b690b1dc241669b69dde1/raw/3d6351b8767ee5fba1ac86cad9b8cc5cf2ff9fea/slack-theme.css';

fetch(cssURI)
  .then(response => { 
    return response.text()  
  })
  .then(css => {
    let style = document.createElement('style')
    style.innerHTML = css

    document.body.appendChild(style)
  })
@bradens

This comment has been minimized.

bradens commented Jan 26, 2017

I noticed that if you inspect the sandboxed webview you can still apply styles with @reimertz method.

I outlined the process with my theme here https://gist.github.com/bradens/0ec8b48488e0071bdee947964b45353a

@jouni

This comment has been minimized.

jouni commented Jan 26, 2017

Here’s the workaround I used, which persists across restarts/reloads (but probably not across app updates):

  1. Find Slack.app (usually in /Applications folder)
  2. Right click and select “Show Package Contents”
  3. Navigate to Contents/Resources/app.asar.unpacked/src/static
  4. Open index.js for editing

Find this part of the code at the end of the file:

document.addEventListener("DOMContentLoaded", function() { // eslint-disable-line
  try {
    startup();

  } catch (e) {
    console.log(e.stack);

    if (window.Bugsnag) {
      window.Bugsnag.notifyException(e, "Renderer crash");
    }

    throw e;
  }
});

After the startup(); line, you can add some code that inserts/injects more CSS to the webviews:

    // TODO find a way to avoid an arbitrary delay, e.g. attach an event listener 
    // to the team switcher buttons and rerun when the team is changed.
    // The timeout is used to get a reference of the webview element for all 
    // of the teams you have (those seem to be created asynchronously)
    setTimeout(function() {
      window.webviews = document.querySelectorAll(".TeamView webview");

      for(var i = 0; i < webviews.length; i++) {
        webviews[i].insertCSS(`
         /* Your custom CSS here */
         body { 
           border: 10px solid red;
         }
        `);
      }
    }, 10000);
@bradens

This comment has been minimized.

bradens commented Jan 26, 2017

Nice! that's great @jouni

@gkostov

This comment has been minimized.

gkostov commented Feb 7, 2017

Great job guys!

Using the code from @jouni and adding to the styles of @bradens my Slack looks so much better now :-)
There is definitely the need for some attention from a real designer but still looking nicer than the white one.

It took me a bit to come up with all of it so may be worth adding this snippet for others to start from:

// TODO find a way to avoid an arbitrary delay, e.g. attach an event listener 
// to the team switcher buttons and rerun when the team is changed.
// The timeout is used to get a reference of the webview element for all 
// of the teams you have (those seem to be created asynchronously)	
setTimeout(function() {
	const cssURI = 'https://gist.githubusercontent.com/gkostov/039fe18fac0c27a4350b274f83403dcb/raw/slack-dark-theme.css',
	codeMirrorThemURI = 'https://codemirror.net/theme/cobalt.css';  // also add the "cobalt" theme for the CodeMirror snippets

	window.webviews = document.querySelectorAll(".TeamView webview");

	Promise.all([cssURI, codeMirrorThemURI].map((file)=>{
		return fetch(file)
				.then( response => {
					return response.text();
				});
	})).then(files => {
		window.webviews = document.querySelectorAll(".TeamView webview");
			
		files[1] = files[1].replace(/cm-s-cobalt/g, 'cm-s-default')

		for(var i = 0; i < webviews.length; i++) {
		  webviews[i].insertCSS(files.join('\n'));
		}
	});
}, 10000);

Cheers

@CombatCode

This comment has been minimized.

CombatCode commented Feb 8, 2017

Anyone knows now how to enable developer tools console? I want to better adjust colors for the slack and maybe even implement Maokai styles

@gkostov

This comment has been minimized.

gkostov commented Feb 8, 2017

It needs an environment flag so in the console run

export SLACK_DEVELOPER_MENU=true
open /Applications/Slack.app

then it's just what you would do in the browser.

@widget-

This comment has been minimized.

widget- commented Mar 9, 2017

Did some digging today on Slack's eventing system. This at least works for me:

// First make sure the wrapper app is loaded
document.addEventListener("DOMContentLoaded", function() { // eslint-disable-line
   // Then get its webviews
   let webviews = document.querySelectorAll(".TeamView webview");

   // Fetch our CSS in parallel ahead of time
   const cssURI = 'https://gist.githubusercontent.com/widget-/f97f6e6697b185692f3836e47e2b6ad3/raw/ea5b8764e66c44aa367f44dcff33f89c480ae58b/custom.css';
   let cssPromise = fetch(cssURI).then(response => response.text());

   // Then wait for the views to load
   webviews.forEach(webview => {
      webview.addEventListener('ipc-message', message => {
         if (message.channel == 'didFinishLoading')
            // Finally add the CSS in
            cssPromise.then(css => webview.insertCSS(css));
      });
   });
});

Edit: Works on Windows (%HOMEPATH%\AppData\Local\slack\app-2.5.1\resources\app.asar.unpacked\src\static)

Also, it's worth noting that here we have access to the container webview and can theme that too. I'm not sure if this is on purpose and might change in the future but I noticed that if you Cmd+Opt+I twice with the developer mode environment variable enabled, you get two inspector windows. The floating one is for the currently selected team and the one attached to Slack is for the container view.

Edit again: Here's my theme, based somewhat on what @DrewML had written: https://github.com/widget-/slack-black-theme

@RUSshy

This comment has been minimized.

RUSshy commented Mar 18, 2017

Here is a better one:
laCour/slack-night-mode#73 (comment)

@aalvarado

This comment has been minimized.

aalvarado commented May 8, 2017

if you download the theme you can do this:

document.addEventListener('DOMContentLoaded', function() {
  var fs = require('fs'),
  filePath = '/Applications/Slack.app/Contents/Resources/black-slack.css';

  fs.readFile(filePath, {encoding: 'utf-8'}, function(err, data) {
    if (!err) {
      var css = document.createElement('style')
      css.innerText = data;
      document.getElementsByTagName('head')[0].appendChild(css);
    }
  })
});
@nbau21

This comment has been minimized.

nbau21 commented Aug 22, 2017

Is it just me, or this doesn't work anymore?

slackbot [12:27 PM]
*/macgap.app.enabledevelopertools()* is not a valid command. In Slack, all messages that start with the "/" character are interpreted as commands.

If you are trying to send a message and not run a command, try preceding the "/" with an empty space.
@jez

This comment has been minimized.

jez commented Aug 23, 2017

@nbau21 You can still use the trick mentioned above with SLACK_DEVELOPER_MENU.

@joeyparis

This comment has been minimized.

joeyparis commented Aug 25, 2017

@nbau21 You have two options now. (I can only confirm this works on MacOS).

Permanent Solution
Create the file (or open it if you've already created it for something else) /etc/launchd.conf. Append the line setenv SLACK_DEVELOPER_MENU true to that file (you probably have to be sudo). Then quit Slack (if it's running) and reopen it. You may have to restart your computer for this to work, but if you follow the Temporary Solution below you can avoid restarting.

Temporary Solution
In your terminal run the command launchctl setenv SLACK_DEVELOPER_MENU true. Then quit Slack (if it's running) and reopen it. That's all!

@sw-yx

This comment has been minimized.

sw-yx commented Oct 31, 2017

sadly @widget- 's solution no longer works on beta v3. love to find new alternatives.

@gkostov

This comment has been minimized.

gkostov commented Nov 10, 2017

They have replaced the webview's with BrowserView's and the above hack no longer works. But not all is lost as seen in widget-/slack-black-theme/issues/21 and it's now needed to add to Contents/Resources/app.asar.unpacked/src/static/ssb-interop.js instead:

document.addEventListener('DOMContentLoaded', function() {
	const cssURI = 'https://gist.githubusercontent.com/gkostov/039fe18fac0c27a4350b274f83403dcb/raw/slack-dark-theme.css',
		codeMirrorThemURI = 'https://gist.githubusercontent.com/pdsullivan/32bad68541ccb66ae6d4948f7c9e88bb/raw/f22e0f5de5ff25d2c06337e8a0ea1ce25885b0e4/cobalt.css';  // also add the "cobalt" theme for the CodeMirror snippets

	Promise.all([cssURI, codeMirrorThemURI].map((file)=>{
		return fetch(file)
				.then( response => {
					return response.text();
				});
	})).then(files => {
		files[1] = files[1].replace(/cm-s-cobalt/g, 'cm-s-default')
		$("<style></style>").appendTo('head').html(files.join('\n'));
	});
});

and it's all back to normal ;-)

@jonahx

This comment has been minimized.

jonahx commented Jan 5, 2018

@gkostov, Thanks!

Is it possible to get the darker contrast theme working with this method?

I tried replacing const cssURI = 'https://gist.githubusercontent.com/gkostov/039fe18fac0c27a4350b274f83403dcb/raw/slack-dark-theme.css', with const cssURI = 'https://cdn.rawgit.com/widget-/slack-black-theme/master/custom.css',, but that didn't work.

@gkostov

This comment has been minimized.

gkostov commented Jan 18, 2018

It did work for me when I tried here - both themes did load as I changed the uris.

@focus97

This comment has been minimized.

focus97 commented Feb 21, 2018

Lots of solutions around the web seem to only partially work. Took a few bits from them and created what works for me.

Add this code (below) to the bottom of: Contents/Resources/app.asar.unpacked/src/static/ssb-interop.js

(I used laCour's slack night theme and then customized the elements I wanted by finding them in the Slack Dev tools.)

document.addEventListener('DOMContentLoaded', function() {

    let tt__customCss = `
        body, .channel_header, #footer, .channel_title_info, #channel_topic_text { background: rgb(0, 43, 54); }
        .c-message__body { color: rgb(153, 174, 177); }
        #team_menu, .p-channel_sidebar { background: #023f4e !important; }
        .c-presence--active {color: rgb(177, 202, 17) !important;}
        nav.p-channel_sidebar .p-channel_sidebar__channel--selected, .p-channel_sidebar__link--selected, .c-message_list__day_divider__label__pill, .p-message_pane .c-message_list.c-virtual_list--scrollbar > .c-scrollbar__hider:before { color: #eee !important; background: rgb(27, 139, 210) !important; }
        .c-message_list__day_divider__line { border-top-color: rgb(27, 139, 210) !important}
        #msg_input, #primary_file_button { background: rgb(2, 55, 68) !important; }
        #msg_form #msg_input { border-color: transparent; }
    `;
    $.ajax({
        url: 'https://cdn.rawgit.com/laCour/slack-night-mode/master/css/raw/black.css',
        success: function(css) {
            $('<style></style>').appendTo('head').html(css + tt__customCss);
        }
    });
});

Hope it helps others!

@avelis26

This comment has been minimized.

avelis26 commented Feb 23, 2018

Thanks focus97, looks great.

For all you windows app users, you can find that file at this location:

%LocalAppData%\Slack<latest>\resources\app.asar.unpacked\src\static\ssb-interop.js

i.e.
C:\Users<user>\AppData\Local\Slack\app-3.0.5\resources\app.asar.unpacked\src\static\

@poberherr

This comment has been minimized.

poberherr commented Mar 16, 2018

@focus97 thanks a lot - I also looked around a lot and your approach works the best so far. Thanks 🙇

@jolson490

This comment has been minimized.

jolson490 commented Apr 3, 2018

I don't have root nor sudo access on my Mac, so the solutions that involve editing a *.js file in /Applications/Slack.app/Contents/Resources/ aren't options for me.

Can someone please tell me is there any other option (that is known to be currently working)? I have the Slack app (Version 3.1.0) on my Mac. I went through the 5 steps in this Theming-Slack-OSX.md file (for step 2. I used the workaround described by this comment. As you can see by the following screenshot, for the most part Slack looks good, except the name of the room is missing (where I have the red arrow pointing to the circled area).
screen shot 2018-04-03 at 11 16 23 am

And more importantly than the room name being invisible in that one spot, I'd be all ears if anyone has any ideas how I can automate this (so the dark theme remains in place even after re-starting the Slack app on my Mac).

Any suggestions would be greatly appreciated. thank you!


UPDATE: fyi a co-worker helped me solve this:

I created the following on my Mac (so this env var is always exported)...:

$ cat /etc/launchd.conf
setenv SLACK_DEVELOPER_MENU true

...though it turns out that isn't needed, because I don't need to do step 3. after all, because I found a way to edit a Slack *.js file:

Before I gave up when it looked like only root can edit the file:

$ ls -l Contents/Resources/app.asar.unpacked/src/static/ssb-interop.js
-rw-r--r--  1 root  wheel  2952 Apr  4 12:35 Contents/Resources/app.asar.unpacked/src/static/ssb-interop.js

But I opened Finder, clicked Applications, right-click Slack, Show Package Contents, browse to Contents/Resources/app.asar.unpacked/src/static/ and then I edited the ssb-interop.js file.

I copied the code from https://github.com/widget-/slack-black-theme/blob/master/readme.md into that ssb-interop.js file. (Those instructions (from that readme.md) are for version 2.5.1, but I found with Slack version 3.1.0 that ssb-interop.js is actually the file that needs to be edited.) And in the "cdn.rawgit.com" URL I changed "/widget-/" to "/ViktorQvarfordt/", because personally I like that slightly different css better.

@devtimi

This comment has been minimized.

devtimi commented Apr 3, 2018

FWIW I tried the JS file edit and Slack stopped being able to get past the "Connecting to Slack" window.

@max-sixty

This comment has been minimized.

max-sixty commented Apr 11, 2018

@focus97 - I can't seem to give a thumbs up here, but your theme is superb. Thanks!

@aidasr

This comment has been minimized.

aidasr commented Apr 11, 2018

@focus97 - you are a lifesaver :)

@ktyre

This comment has been minimized.

ktyre commented Apr 17, 2018

@focus97, I've been LOVING your solution which worked for me until today. Wondering if there's an easy tweak to make it work again? I'm feeling blinded by the white background which has returned. Perhaps a class or id name was changed so the background color doesn't work anymore?

Note: Re-pasted your block of code into the ssb-interop.js file and restarted Slack just to be sure to no avail.

@hackel

This comment has been minimized.

hackel commented Apr 17, 2018

FYI - fix for the latest changes is here: laCour/slack-night-mode#73 (comment)

@jorgeorpinel

This comment has been minimized.

jorgeorpinel commented Jun 7, 2018

I get "/macgap.app.enabledevelopertools() is not a valid command." no matter what I do. I tried to set the SLACK_DEVELOPER_MENU env var in all the ways mentioned above.

@jorgeorpinel

This comment has been minimized.

jorgeorpinel commented Jun 7, 2018

I get "/macgap.app.enabledevelopertools() is not a valid command." no matter what I do. Tried to set the SLACK_DEVELOPER_MENU env var in all the ways mentioned above.

@danilodequeiroz

This comment has been minimized.

danilodequeiroz commented Jun 29, 2018

Use this instead.

@micnguyen

This comment has been minimized.

micnguyen commented Jul 8, 2018

@danilodequeiroz That works great. Thanks for that. Incredible that Slack has not properly addressed this yet.

@KrishMehta

This comment has been minimized.

KrishMehta commented Jul 18, 2018

@danilodequeiroz that's fantastic; however, I think it'd be better if your link color (and maybe tags as well) was changed to #0000EE instead of the stale gray that it currently is. Again, just my opinion - but I think a lot of people would like it better.

@willhayslett

This comment has been minimized.

willhayslett commented Aug 27, 2018

If using the solution provided by @danilodequeiroz, you'll notice the menu links are hard to see. Use the following script to make the text white:

document.addEventListener('DOMContentLoaded', function() {
  let tt__customCss = `.menu ul li a:not(.inline_menu_link) {color: #fff !important;}`
  $.ajax({
      url: 'https://cdn.rawgit.com/laCour/slack-night-mode/master/css/raw/black.css',
      success: function(css) {
          $("<style></style>").appendTo('head').html(css + tt__customCss);
      }
  });
});
@brennenawana

This comment has been minimized.

brennenawana commented Oct 23, 2018

Just want to say that this is awesome, just what I was looking for. Thanks so much for sharing.

@UiCandy

This comment has been minimized.

UiCandy commented Nov 13, 2018

Legend, finally my eyes can rest on Mojave. 😃

@ryanpcmcquen

This comment has been minimized.

ryanpcmcquen commented Nov 20, 2018

I wrote a script I can run each time Slack updates: https://gist.github.com/ryanpcmcquen/8a7ddc72460eca0dc1f2dc389674dde1

@bh2smith

This comment has been minimized.

bh2smith commented Nov 22, 2018

@danilodequeiroz worked immediately! Amazing!

@rocajuanma

This comment has been minimized.

rocajuanma commented Dec 12, 2018

@danilodequeiroz thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment