External CSS (per note) is being ignored


Did use of external css stop working at some point?
Any css that used to be pulled in (in the markdown) with <link ... or @import ... seems to be ignored now.

Is this working (or not working) for anyone else?


I think it's been disabled for some time? The way to set the note CSS now would be to use userstyle CSS.

Ugh. Significant regression.

Most such tags have been disabled now for security reasons. It's mostly a niche feature anyway (I mean I wouldn't be surprised if you were the only one doing this :slight_smile: ), and the same functionality can be achieved with userstyle, so it's not worth the extra security risk.

In fact, I would think using one userstyle is better than having to add HTML tags to every single note?

I'll see how I can work around this. I use Joplin for everything, and that includes drafting webpages (they are all managed with markdown) for three different websites all of which have stacks of different CSS, that until now represented, within Joplin, rather closely to the end product. Floats, formatted tables, boxes, fonts, nearly everything. All using the same stacks of CSS. This only requires a small cut-n-pasted block of HTML at the top of such documents, slightly different for each website and slightly different for the type of page on each website. It's rather simple. The complexity is abstracted away in the CSS. Then various markdown, if need be, is wrapped in div tags (and CSS-triggering classes and ids) for floats and things. Some things like tables ... use full-on html if markdown tables just can't handle it. Yada Yada.

Plus, I just do fancy things on my own for various projects. But with those I can muddle through, it'll just be messy.

With one userstyle for everything. Oi. I suppose I can try to namespace the CSS somehow and link it all through the userstyle CSS. We'll see.

Hmm. I suppose one interim solution is to ditch Joplin as a renderer for everything that requires more than rudimentary CSS and use it only as an organizer / storage tool. Alas, Joplin renders (rendered) better than Atom (which also seems to ignore external CSS? which violates the spec) and Ghostwriter. Anyone else have a suggestion for an external editor / renderer for Linux?

Ok that's interesting, Joplin wasn't designed for this obviously and I'm surprised it was previously working.

But in fact, I've just realised you could restore the feature using a plugin - you would add a fenced block at the top of the note that contains the CSS path. Then in the plugin you grab this and create a <link> tag. If you want to give it a try I've just created one based on the exiting renderer plugin demo and it works:

Copy this to externalCss.js in your profile /plugins directory:

/* joplin-manifest:
	"id": "org.joplinapp.plugin.ExternalCss",
	"manifest_version": 1,
	"app_min_version": "1.4",
	"name": "Allow adding external CSS",
	"version": "1.0.0"

	onStart: async function() {
		await joplin.plugins.registerContentScript(

And then this to _markdownItExternalCss.js still in /plugins:

function plugin(markdownIt, _options) {
	const defaultRender = markdownIt.renderer.rules.fence || function(tokens, idx, options, env, self) {
		return self.renderToken(tokens, idx, options, env, self);

	markdownIt.renderer.rules.fence = function(tokens, idx, options, env, self) {
		const token = tokens[idx];
		if (token.info !== 'external_css') return defaultRender(tokens, idx, options, env, self);
		return '<link href="' + escape(token.content.trim()) + '" media="all" rel="stylesheet"/>';

module.exports = {
	default: function(_context) { 
		return {
			plugin: plugin,

Then you can create block like so at the top of any note, and it will load the CSS file:


Thanks. I will play with it. In the end, a CSS call is just HTML and a markdown renderer groks HTML, so, in theory, the rendering should be close. It was always "close enough" for me to have meaningful edits.

I will play with the plugin stuff. I am not a javascript guy, so ... if it breaks, I will only have mediocre ability to respond. But I will give it a go.

Thanks again. I will look later. I have a farm to attend to (my other life).

UPDATE: Works! Thanks! :slight_smile:

How did you go about adding the path in the note? I only get a square when I added a local path to the .css file. Only by manually editing the DOM to link to the https version did the icon actually get rendered.

How would I go about extending this plugin to actually export what is rendered? Currently it does not get included when it renders as I mentioned in issue 4222.

Yeah. This works ... semi-not-really-okay.

For example, here is the CSS for one of my notes:



This works okay within the app. For print though ... it will just display the paths.

It will also not work with URLs (https:// or even file://) for whatever reason. I.e., if my common.css was on some website (which it is in actuality).

I will have to experiment further.

Hmm, that is strange.

I replaced the ``` with ''' in this example to not destroy the forum codeblock, but if I use this:


<code class="inline-code"><i class="fa fa-windows" aria-hidden="true" style="font-size: 0.73em;"></i></code>

I get a square, but little else.

Any other variation like "C:\Users\user\Downloads\JoplinProfile\test.css", "C:/Users/user/Downloads/JoplinProfile/test.css", "./JoplinProfile/test.css", "./test.css" and "../test.css". Can't remember if I tried any others.

I'm using mine at work, so I'm forced to use Windows. I'm assuming you're using a linux distro considering your file path, maybe there's some difference between the two versions? I can't think of why it should matter, but then again ¯\_(ツ)_/¯

e: Before I forget, I'm using the portable version of v1.4.19 to do testing, maybe that has something to do with it?

Looks like there's a bug as it's supposed to load plugins even when exporting to PDF/HTML or printing, but looks like it's not doing it.

A bug in the way the application deals with plugins or with the plugin itself?

e: Looks like the reason for why https: links doesn't work is because : is converted to UTF-8/Windows-1252 %3A in the HTML DOM. While %3A is Ascii encoded for :, it does not actually work in the href="" value without actually being a :. I don't know if this is because of something Joplin does, or if it is something else though.

e^2: Didn't work in Firefox Developer Edition.

e^3: Well, hardcoding "https://" into the return value does work, it's far from ideal, but there's still the problem of the rendered output not being included in an export.

return '<link href="' + escape(token.content.trim()) + '" media="all" rel="stylesheet"/>';

Hardcoded version:

return `<link rel="stylesheet" href="https://${escape(token.content.trim())}" media="all"/>`;

e^4: Looking at how the href value is treated, it seems to be the path that is the problem.

/Users/user/Downloads/JoplinProfile/test.css is treated as file:///Users/user/Downloads/JoplinProfile/test.css

Meanwhile, C:/Users/user/Downloads/JoplinProfile/test.css is treated as file:///C:/Users/user/AppData/Local/Temp/1l3Gmwf908YIor5JaIooxNZsQcC/resources/app.asar/gui/note-viewer/C:/Users/user/Downloads/JoplinProfile/test.css

So while linking a local .css still doesn't work for some reason, it at least explains why one gets a default square while the other one doesn't.

e^5: Doesn't work in a regular v1.4.19 install either, so at least not an issue singular to the portable version.

This is probably because of the escape function....

Is there a way around this? I'd rather not have to hardcode https:// any more than necessary.

not sure if this helps at all, but I have no problem.

using v1.5.7 on Mac, though this has been working almost since I started using Joplin.

I use an external CSS for a few one-off notes that I want to have particular styling.

At the head of the Markdown I have the @import, but wrapped in a style tag


    @import "/Users/fred/.config/mod001.css";
1 Like

a bug in the way the app deals with plugin

Gah! @fedwards01

I swear to god this was not working for me. All I can think of is that I typoed or something. I prefer <link ...> (and that should work according to spec, IMHO) but, goodness, @import is just fine for my purposes. And it does it without weird hoop-leaping or formatting.

Thanks. -t

1 Like

My dude! Thank you so much. Tried it out real quick and export and everything works perfectly fine linking to a remote file now. This is perfectly fine for my use-case, not like I'm doing anything particularly fancy with it. A bit strange that it still doesn't work with a local file, but I think that's because of the wonky manner in which the css file grabs the icon- just gotta self host it I suppose.

Now just to hope this manner of doing it won't be yeeted into the stratosphere come next update...

1 Like

What's more interesting, and "transportable", is to attach your CSS files into notes and get the resource ID for them

then add the CSS from Joplin's own file store

by putting two imports at the top of a note

for desktop, the path may need to be modified to where Joplin desktop has been configured to store files locally.

@import "/Users/fred/.config/joplin-desktop/resources/44153d315e5547e8a24b51eef41dcb3e.css";

this block for iOS... not sure if it works for Android

@import "./44153d315e5547e8a24b51eef41dcb3e.css";

or both together

@import "/Users/fred/.config/joplin-desktop/resources/44153d315e5547e8a24b51eef41dcb3e.css";
@import "./44153d315e5547e8a24b51eef41dcb3e.css";

1 Like