Home / GitHub Page

Custom stylesheets

Custom stylesheet on Android is not supported and if I understand it correctly by a previous comment in another thread, it is not possible currently.

I’ve created a small draft PR playing around with this concept: https://github.com/laurent22/joplin/pull/2099

@laurent I’d be curious to get your perspective before I go further with it. Apologies, I forgot to mention in this thread before I started, so this whole addition may not be welcome. No worries if not, I should’ve remembered to check in with you first.

1 Like

@laurent,

As far as I see now, the adaptable userstyle.css has been implemented for Windows and macOS. I don’t know about Linux and Android, but the iOS version does not support it (or it must be well hidden). Are there any serious plans for doing so? It’s one of the things I miss most as a fresh Joplin user, because the current style settings are too space consuming on the tiny screen of my iPhone.

I’d love to be able to set custom styles across notes in iOS, too!

As far as my implementation of custom stylesheets goes, there’s unfortunately no way to set a default stylesheet for iOS because there’s no way to access an equivalent of the ~/.config/joplin-desktop/ directory.

In the short term, I’ve been adding this to the bottom of my notes to get the styles I want. Not the most elegant solution, but it makes the rendering look much nicer at least:

<style>
    body {
        font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
        margin-bottom: 2em !important;
    }
    code, pre  {
        font-family: "iA Writer Mono V", "Fira Code";
        // font-weight: 600;
        // font-size: .95em;
        line-height: 1.5em;
    	background: rgba(0, 76, 114, .08) !important;
    	border-radius: 4px;
    }
	.code, .inline-code {
		border: none;
		background: rgba(0, 76, 114, .08);
		border-radius: 4px;

	}
    img[title="250px"] { width: 250px; }
    img[title="350px"] { width: 350px; }
    mark {
        background: #3edbff53 !important;
        padding: 1px 3px;
    }
    .md-checkbox .checkbox-label-checked { cursor: pointer; }
    /*********************************
     **** Links to internal notes ****
     *********************************/
    a .resource-icon { display: none; }
    a[href="#"] { color: green; }
</style>

Longer-term, we could consider supporting a Meta Joplin notebook or something, where you can create a note called userstyle.css (just like the one in ~/.config/joplin-desktop/) that applies the styles there. Or, we could consider adding it under the Configuration panel as a big string, similar to how we store the themes. I think either of these would be a more intuitive solution for the desktop app too, rather than having to dig into the fairly hard-to-find ~/.config/joplin-desktop/ directory.

3 Likes

We had a good discussion going, but it died down…

An alternative for inline style definitions could be this:

<link rel="stylesheet" href="c:/Users/memophenon/.config/joplin-desktop/altuserstyle.css">
<link rel="stylesheet" href="/Users/memophenon/.config/joplin-desktop/altuserstyle.css">

The first one for my pc, the second for my Mac. I would prefer a relative stylesheet address, but I couldn’t find a way to get that working. Nor do I have any clue what kind of address I should use on iOS.

It was a good decision to make the userstyle.css device-dependent, in my opinion. Different devices demand for different stylings. But a cascade allows you to play with style scopes:

  1. on your device — built-in AppStyleSheet (dynamic)
  2. on your device — UserStyleSheet
  3. in notes — CSS files linked by <link> tag
  4. in notes — CSS block embedded as <style> element, optionally containing @import functions
  5. in notes — style attributes added to HTML tag

Thanks for sharing your stylesheet BTW. I hadn’t realized I could suppress the J icon at internal links this way. It’s too big, too low positioned, and ruins the regular line spacing.

I would like to get this discussion going again, so in that spirit here is my proposal.

I would propose 3 different modes for setting css.

  1. No CSS
  2. Select from filesystem (this will use the system default file picker). The selected file can be displayed underneath the setting along with a reload button. The file will be reloaded on application start (same as now)
  3. Load from note. This will add an option to the note context menu “Set Userstyle” and “Set Userchrome” (can also have an input in settings similar to the goto anything feature). This will allow users to take advantage of syncing notes across platforms.

Having these options means users can manage css as they want without having to create any specific folders or directories.

To make option 3 a bit smoother we should add in the ability for users to hide notebooks, this will allow users to create a config notebook which holds all the styling notes without those notes always being visible.

2 Likes

I think option 3 is the easiest one. Technically it would take very little to get this working, but it’s in terms of UX that it’s not great.

It’s a bit messy, even with hidden notebooks, because it’s mixed with the other notes. There’s also the problem of requiring the user to create notes with magic names so that they are picked up by the app. And what if there’s a syntax error in the config file? We also don’t have a good way to report that. They’ll also show up in search results, which might be unexpected.

Maybe it would make sense to create a separate class of sync items for this. They’ll be used only for config, and we could list them in a separate config screen and manage them differently than the notes.

You could use a reserved tag name, like .system or something, to identify and group config notes.

This wouldn’t be a problem because the user will select the note they want to use, which means no specific naming pattern.

I don’t think there is currently any method for reporting syntax errors with css. This is probably something that should be considered in any case.

We could possibly use manual excludes but I can see how this might not be desirable.

This could be the best option but it’ll also be the most work.

I actually think a convention of something like a notebook named Joplin config with notes inside called Markdown rendering styles and Joplin app styles would be quite elegant (or userstyle.css and userchrome.css to be consistent). I might just be biased from GitHub’s approach, but I like it when content and config are stored in the same way.

I could see this implemented along a spectrum of name customization:

  1. On one extreme, we could just say “The folder must be named X, and the files must be named Y and Z”. This would likely minimize confusion down the line, because then everyone has files with the same name. This would make it harder for people to make mistakes, and support questions will be easier to phrase properly rather than having a dance where we try to figure out what folks are talking about.
  2. On the other extreme, the folder and file names could be totally customizable. We let folks determine their names in Settings, similar to how they can set their text editor. This would entail 3 new fields: Configuration notebook, Markdown rendering styles, and Joplin app styles (or some other names).

I don’t recommend creating a complex abstraction on top of these files, like hiding them or anything like that. I think that makes it much more likely that folks get confused, forgetting that it’s even there. If it gets annoying to see this config notebook in the sidebar, here are two suggested solutions that I think would create less confusion:

  • Right now, when I have an old notebook I don’t use much anymore, I just nest it under a meta notebook called Archive, which lets me minimize all of the sub-notebooks. This takes up less visual space than having lots of old notebooks lying around, without making it easy to forget they even exist. (The problem is this might break the config notebook because I guess now the notebook name would be nested? I think it’d be fine, but worth checking)
  • Perhaps we could create some more formal concept of archival, rather than having to nest it into a meta notebook.

I’ve explained some of the challenges in the other topic (which I referenced earlier).
One thing we have to allow people is to choose the files per platform. Desktop vs Mobile.
This does not mean it shouldn’t be possible to share one css file for all clients. However, we should use a unique device identifier to allow a device css file, if wanted that is.

I would like to keep Joplin as minimalistic as possible, without too much concessions to usability. Creating two types of notes, data and configuration, is confusing to the user in my opinion and may break the architecture (e.g. search facilities). A lot can be done with the current setup. Some problems don’t have to be solved by Joplin, as they can be solved by CSS. Let’s start with considering the wishes before thinking in solutions, and weigh their importance. Here are some wishes:

  1. I want some platform-independent styling, for instance all headings being Joplin-blue.
  2. I want to adapt some styles to my platforms.
  3. I want to adapt some styles to my devices, for instance geared to their screen size and resolution.
  4. I want to style some notes in a notecategory-specific way.
  5. I want to style some notes in a notecategory×platform-specific way.
  6. I want to style some notes in a notecategory×device-specific way.
  7. I want to style some notes in a note-specific way.
  8. I want to style some notes in a note×platform-specific way.
  9. I want to style some notes in a note×device-specific way.

As far as the desktop versions are concerned, the wishes 3, 6, 7, and 9 are already fulfilled, as mentioned in my previous post. The wishes 1 and 2 have to be realized by 3, the wishes 4 and 5 by 6, and wish 8 by 9. This violates the DRY principle, but as I don’t use Joplin on hundreds of devices, it’s is not a big issue for me (but how about other users?). As for 6 and 9, I would like to have a generic way to refer to the directory .config/joplin-desktop/ where I store all my CSS files, that’s all. But even that’s not indispensable. BTW, I think 6 could also be realized by some CSS-tricks in userstyle.css (I haven’t experimented with it yet), which would make the <link> construction unnecessary.

Synchronization is only needed for 1, 4 and 7. But as 7 can be built in in the note itself, only 1 and 4 would demand for extra provisions.

And to conclude with a very personal opinion: I don’t think platform (2, 5, 8) is a very significant dimension for styling. The individual devices (3, 6, 9) with al their particular properties are far more important. But you may convince me of the contrary.

I agree. Either you haven’t read my text completely or you ignored its meaning.

However, we should use a unique device identifier to allow a device css file

So there’s a hierarchy: mobile/desktop -> OS -> device. The granularity depends on the person who will implement it. I’m all in for all levels, but I doubt that Laurent will accept this type of complexity. e.g. how to merge the levels?

Your hierarchy could be extended to mobile/desktop -> OS -> device -> screen. On further consideration, screen is a dimension of its own. So there are at least four dimensions to deal with:

  1. The cascade of stylesheets, i.e. the sequence in which style specs are processed
  2. Devices (synchronization of specs for individual devices is not needed, but for higher levels in the hierarchy it might be a nice to have)
  3. Screens (synchonization between devices might be desirable, but is not essential)
  4. Notes (are already synchonized)

I do hope that the configuration interface won’t reflect this complexity in the future. In fact, the current desktop version meets my needs to a great extent, since I can do a lot of manipulations outside Joplin. What I’m really still missing is the possibility to use references in <link> tags and hyperlinks like:

  • ./«file»
  • ~/.config/joplin-desktop/«file»
  • $HOME/.config/joplin-desktop/«file»

That would facilitate generic constructions in my notes. More has to be built for mobile devices: at least provisions for creating, editing, renaming, and deleting (and maybe copying) CSS files in some dedicated config folder. Support for hyperlinks to HTML files on the synchonization target might be another challenge. I have no ideas about that yet.

Just another wild idea: how about making userstyle.css a parametrized stylesheet? It would be possible then to make your self defined color schemes dependent on the chosen theme.

Thanks, nice discussion. So 3 other points to consider :

  1. Have a CSS editor for easy styling of the css file
  2. Give some templates (themes) that user could choose without any css coding
  3. These two features should support desktop AND mobile (styles could be different on mobile, have to use responsive design in the css - the editor could make it more easy to build)

(Just some petty facts from my side. This post was intended as an answer here to @DominicDesbiens, or in fact to anyone who is interested in where to find the built-in style definitions.)

If you know how to interpret the CSS language and know how to open a file in a safe way for reading (i.e. without the risk that you unintentionally change something), you could peek in the following file to see what’s predefined by Joplin, before deciding what to (re)define by yourself in other places:

  • on Windows: section noteStyle.js of Joplin/resources/app.asar in the folder where Joplin is installed
  • on macOS: Joplin.app/Contents/Resources/app/lib/noteStyle.js

I expect this also gives a clue where to find it on Linux. Maybe there is a way to unpack an ASAR file. That would allow for a more user-friendly view experience. Anyway, it’s a good start for adjustments of the styling in userstyle.css, since the CSS cascade is:

  1. the built-in script noteStyle.js (parametrized, so it adapts to the chosen theme)
  2. ~/.config/joplin-desktop/userstyle.css
  3. links to other CSS files in your notes
  4. hard coded <style> blocks in your notes
  5. hard coded styles= attributes in HTML tags in your notes

Joplin interprets this cascade from 1 to 5, and the last specifications prevail. In the current Joplin architecture, the notes are synchronized, the JavaScript code and CSS files themselves not.

2 Likes

Thanks @memophen. I don’t think my knowledge is advanced enough. Don’t know where to find the CSS tags :slight_smile:

Ohhh ! New in the latest version of Joplin (1.0.178). In Appearance section in Options, there is two buttons to open userstyle.css and userchrome.css !

Just impressed about development of this app ! Thanks…

For custom style sheet, here is little trick to know all tags styled in Joplin : export notes in HTML and see the source code of the HTML file. Doing this in empty Joplin cause it export all notes without encryption.

I quote in Checkbox within table cell

as some great progress has been published today