Homepage    |    GitHub    |    API    |    FAQ

๐ŸŽจ macOS theme for Joplin

Hi everyone, hereby I like to share my macOS theme for Joplin v2.0.2 and above. Curious to hear what you think. Let me know if you run into any issues.

  • :sparkles: Completely styled UI, including all controls
  • :last_quarter_moon_with_face: Auto light/dark mode based on system theme
  • :ok_hand: Native icons for macOS users, alternative icons for non-mac users
  • :man_artist: Easy to customise with CSS custom properties

Installation

  • Download the latest .css from releases and copy the CSS to the clipboard,
  • Open Joplin's preferences (cmd + ,) and go to the 'Appearance'-tab,
  • Click on 'Show Advanced Settings' โ€บ 'Custom stylesheet for rendered Markdown'. A file named userstyle.css should open in a texteditor. Paste in the CSS. Do the same for 'Custom stylesheet for Joplin-wide app styles' (filename userchrome.css),
  • Mac users: Download and install SF Pro from the Apple website here,
  • Non-mac users: Download and install the .ttf from the Phosphor icon family (direct link to .ttf). Also make sure to uncomment all the custom properties prefixed with --u-icon- & --u-font-family-icons.
  • Restart Joplin. Enjoy!

Customizing

At the top of the CSS there are a few custom properties prefixed with --u- you can use to easily customize the theme. Uncomment and tweak to your liking.

No icons?

For the icons to work you need to install the correct icon font. macOS can download and install SF Pro from the Apple website. Since Apple prohibits SF Pro to be redistributed non-mac users can use the Phosphor icon family as a replacement. How to? See the installation instructions above.

Disclaimer

:warning: Joplin uses styled-components for styling, which makes it incredibly hard to theme the app. A lot of hacky CSS workarounds and !importantโ€™s were used. These may cause UI issues with future Joplin releases. Since it's just CSS, your data remains safe and you can easily revert the styles.

Feel free to create an issue or post a message here if you run into issues.

Development

Check the Github repository for more information.

This is a follow-up of this thread.

15 Likes

Thanks, installation works fine.
Minor desc question - * Make sure Theme is set to 'Light' + "Auto light/dark mode based on system theme" is a bit confusing.

Set it to automatic and both preferred themes to light or disable automatic and set it to light?

Thanks, Andre

Ah right. Bottomline: it doesn't really matter what the Theme-setting under Appearance is set to. But 'Light' it's the default Joplin theme I use to test my CSS on. But it seems my CSS is overriding the other theme options (Dracula, Nord, etc.) correctly also.

Also, the Joplin-setting Automatically switch theme to match system theme under Appearence doesn't change things when this theme is applied. This theme will ALWAYS apply light or dark mode, depending on what your systems theme is set to.

Edit: Just as a reference, these are the settings that I use (but they don't really matter):

That looks very good, thanks for sharing. I wonder if such a theme could be packaged as a plugin, to make distribution and update easier.

3 Likes

Tahnks a lot, this theme is amazing!

1 Like

I doubt it otherwise the following wouldn't be needed:

Download and install SF Pro from the Apple website here,

Yes I've noticed that, but perhaps we can still reduce friction by packaging the rest of it as a plugin, with a fallback system font. Then as a bonus the user can install this extra font to get a better result.

Yes, the font is one thing. Apple does not allow the font to be redistributed. But this we can easily overcome with a small notice for the user to go and install it from the Apple website.

I've played with the plugin API before, but if I remember correctly I ran into the limitation that the CSS could not be appended to the main window. Also this plugin would require to append CSS into the editor window as well, which I don't know the plugin API is capable of.

Yes I think the API is missing two things:

  • Loading a userstyle.css file provided by the plugin
  • Loading a userchrome.css file provided by the plugin

There's also the fact that you rely on Light theme being set, which probably mean the plugin should be able to set this, and disable the option so that it can't be changed while the plugin is active. I think that's the trickier part.

Well, as mentioned earlier setting the base theme to light is not a requirement anymore. Before there were a few issues when another theme was selected, but this is not the case anymore with this final version. I'll remove it from the installation instructions to avoid any confusion. :slight_smile:

But yes, setting the userstyle.css and userchrome.css would be nice. It would be even better if we could dynamically update it, so that users can change theme variables in Joplin's settings and the userstyle is updated. Maybe just adding an id to the stylesheet would be sufficient.

Not a Mac User but looks Amazing great Work !
I would totally use it on my Mac-Like elementary OS machine too.

2 Likes

Thanks! Well, it's actually quite easy to make this work for non-macOS'es as well. Just re-assign all icon variables to a different UTF-character from another icon font. I think the real challenge is to find an icon font that contains all necessary icons.

2 Likes

Interesting. I might mess around with it once it's fully running on Mac

Looks great, thank you for continuing to work on this and congrats on releasing it! I am switching to your dark mode to try it out :slight_smile:

(FYI, I had a sync issue the other day and because of the way this theme shows it only on hover, I didn't notice the error on my Mac. I simplified the .sidebar.sidebar>div:last-child>div:first-child section to make sure it always displays the sync status. Seems like an awesome addition to hide the normal "successful" sync and then show the full details if there is an issue. Would likely need a new "error" class of some sort, I haven't dug in deep on it.)

(I see that you already accounted for this in the user preferences, for others who want to see sync status always take a look at line ~40).

I had previously done some work to customize the Rich Markdown Plugin. With this release I went ahead and integrated that code to use the same CSS variables as yours (as best as I could) to make it look more seamless. Including since it might be useful to anyone using that plugin.

Code + Screenshots Note: to use this, you need to install the Rich Markdown Plugin AND enable "Add additional CSS classes for enhanced customization" in preferences



.codeMirrorEditor .CodeMirror *{
    /*setting the font to the system font of theme*/
    font-family: var(--g-font-family-system) !important;
    line-height: var(--g-line-height-2);
    font-size: var(--g-font-size-1);

}
.codeMirrorEditor .CodeMirror * .cm-rm-monospace, .codeMirrorEditor .CodeMirror *  .cm-jn-monospace{{
    /*setting the font to the system font of theme*/
    font-family: var(--g-font-family-mono) !important;
}

.CodeMirror-sizer, iframe.noteTextViewer {
    /*centers and keeps the max text width easier to read*/
    margin-right: auto !important;
    margin-left: auto !important;
    max-width: 80ch !important;
    line-height: 1.6em !important;
}

.cm-rm-hr {
    /*makes a `---` look like a line, but leaves the actual text for easier editing*/
    border-top: 1px solid var(--g-separatorColor);
    color: var(--g-separatorColor) !important;
    display: block;
    line-height: 1px !important;
    width: 100%;
}

.cm-header-1, .cm-header-2, .cm-header-3, .cm-header-4, .cm-header-5, .cm-header-6 {
    /*changes header text color*/
    color: var(--g-headerTextColor) !important;
}

/*changes header sizes*/
.cm-header-1 {
    font-size: var(--g-font-size-4);
    line-height: var(--g-line-height-5);

}

.cm-header-2 {
    font-size: var(--g-font-size-3);
    line-height: var(--g-line-height-4);

}


.cm-header-3, .cm-header-4, .cm-header-5, .cm-header-6 {
    font-size: var(--g-font-size-2);
    line-height: var(--g-line-height-3);

}

.cm-header.cm-rm-header-token {
    /*makes the markdown #, ##, ###, etc less noticable*/
    color: var(--g-unemphasizedSelectedTextBackgroundColor)  !important;
    font-size: 70% !important;
    margin-left: -50px;
    max-width: 50px;
    width: 50px;
    overflow: hidden;
    display: inline-block;
    text-align: right;
    line-height: 1.3em;
}

.cm-variable-2, .cm-variable-3, .cm-variable-4, .cm-variable-5, .cm-variable-6, .cm-s-default .cm-keyword,.cm-keyword,  .cm-variable-2 {
    /*changes list color*/
    color: var(--g-textColor) !important;
}

.cm-rm-list-token, .cm-variable-2.cm-rm-list-token, .cm-variable-3.cm-rm-list-token, .cm-variable-4.cm-rm-list-token, .cm-variable-5.cm-rm-list-token, .cm-variable-6.cm-rm-list-token, .cm-rm-strong-token, .cm-rm-em-token {
    /*makes markdown-specific things fade back, i.e. _ and ** in bold and italic*/
    color: var(--g-unemphasizedSelectedTextBackgroundColor) !important;
}


.cm-header.cm-rm-header-token:after {
    /*this adds space between the markdown ## and the header*/
    content: '--' !important;
    color: transparent;
}


.cm-comment, .cm-jn-monospace {
    /*affects the inline code & block color*/
    color: var(--g-secondaryLabelColor) !important;
}

.cm-rm-checkbox.cm-rm-monospace {
    /*changes the checkbox color*/
    background: transparent;
    color: var(--g-systemBlue) !important;
}

span.cm-rm-link, .cm-variable-2.cm-rm-link, .cm-variable-3.cm-rm-link, .cm-variable-4.cm-rm-link, .cm-variable-5.cm-rm-link, .cm-variable-6.cm-rm-link, span.cm-url, .cm-variable-2.cm-url, .cm-variable-3.cm-url, .cm-variable-4.cm-url, .cm-variable-5.cm-url, .cm-variable-6.cm-url {
    /*changes links*/
    color: var(--g-linkColor) !important;
    cursor: pointer;
}

.CodeMirror-activeline-background {
    /* this is hiding the highlighting of your currently selected line*/
    background: transparent !important;
}


/*Hide URLs https://discourse.joplinapp.org/t/plugin-rich-markdown/15053/140? */
div:not(.CodeMirror-activeline)>.CodeMirror-line .cm-string.cm-url:not(.cm-formatting) {
    font-size: 0;
}

div:not(.CodeMirror-activeline)>.CodeMirror-line .cm-string.cm-url:not(.cm-formatting)::after {
    content: '';
    font-size: 1rem;
}

span.cm-rm-checkbox.cm-property + span.cm-rm-checkbox ~ span.cm-rm-checkbox, span.cm-rm-checkbox.cm-property + span.cm-rm-checkbox, span.cm-rm-checkbox.cm-property, span.cm-rm-checkbox.cm-property + span.cm-rm-link  {
    /*puts a strikethrough on completed checklist items*/
    text-decoration: line-through;
    opacity: 0.5;
}

.cm-variable-2.cm-overlay.cm-rm-list-token.cm-overlay.cm-rm-em-token {
    /*make markdown tokens for list into dots*/
    color: transparent !important;
    background-color: var(--g-unemphasizedSelectedTextBackgroundColor) !important;
    height: 6px;
    width: 6px;
    border-radius: 50%;
    display: inline-block;
    vertical-align: bottom;
    margin: 0 8px 8px 0;
}

fyi @CalebJohn in case you're interested

2 Likes

Awesome theme. I am using it now.

I have just added my custom colors to make markdown more appealing:
.cm-header { color: #FAC05E !important; }
.cm-header-2 { color: #3FA7D6 !important; }
.cm-header-3 { color: #ACEB98 !important; }
.cm-header-4 { color: #FF6978 !important; }
.cm-header-5 { color: #FF6978 !important; }
.cm-variable-2 { color: #a0a0a0 !important; }
.cm-variable-3 { color: #666666 !important; }
.cm-variable-4 { color: #444444 !important; }
.cm-keyword { color: #444444 !important; }
.cm-quote { color: #707070 !important; }
.cm-strong { color: #E94F37 !important; }

1 Like

I've now added support for loading chrome and note CSS files from a plugin. It's already on the dev branch if you want to give it a try, or it will be in the next pre-release otherwise. There's a demo plugin there that shows how to use it:

In your case, I think all you'd need to do is setup your build script so that they create the chrome.css and note.css files. I've tried with your theme and it works fine.

Also you can load multiple CSS files like this, so you could even dynamically generate one based on user settings and load it. If you need some info about all this let me know!

6 Likes

That's awesome! I'll take a look at turning this into a plugin.

@uxamanda Yes, there indeed is a user setting to turn off hiding the sync status. I'll make it the default with the next release as sync errors are now easily overlooked. :sweat_smile: Best solution would be to have an error classname on the sync block, which I might give a go eventually.

@h3y1mr0b1n I've started working on making the icons configurable, so that non-mac users can also use the theme. :+1:

@Nifaal Nice to hear you're enjoying the theme!

6 Likes

Looking forward to this plugin. :partying_face:

1 Like

People like you make the world a better place.

2 Likes