# External CSS (per note) is being ignored

**URL:** <https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016>\
**Category:** Support\
**Created:** [9 December 2020 23:04 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016 "2020-12-09T23:04:29Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![t0dd](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/t0dd/32/743_2.png) [@t0dd](https://discourse.joplinapp.org/u/t0dd)\
**Post date:** [9 December 2020 23:04 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/1 "2020-12-09T23:04:30Z")

</div>

joplin-1.4.19-1.fc32.taw.x86\_64

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?

-todd

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [10 December 2020 10:38 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/2 "2020-12-10T10:38:51Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![t0dd](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/t0dd/32/743_2.png) [@t0dd](https://discourse.joplinapp.org/u/t0dd)\
**Post date:** [10 December 2020 12:44 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/3 "2020-12-10T12:44:22Z")

</div>

Ugh. Significant regression.

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [10 December 2020 13:09 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/4 "2020-12-10T13:09:57Z")

</div>

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 🙂 ), 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?

---

<div class="post-metadata">

**Author:** ![t0dd](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/t0dd/32/743_2.png) [@t0dd](https://discourse.joplinapp.org/u/t0dd)\
**Post date:** [10 December 2020 15:28 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/5 "2020-12-10T15:28:28Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [10 December 2020 16:42 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/6 "2020-12-10T16:42:54Z")

</div>

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:

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

joplin.plugins.register({
	onStart: async function() {
		await joplin.plugins.registerContentScript(
			'markdownItPlugin',
			'externalCss',
			'./_markdownItExternalCss.js'
		);
	},
});

```

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

```javascript
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:

* * *

```external\_css  
/path/to/file.css  
```

---

<div class="post-metadata">

**Author:** ![t0dd](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/t0dd/32/743_2.png) [@t0dd](https://discourse.joplinapp.org/u/t0dd)\
**Post date:** [10 December 2020 17:18 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/7 "2020-12-10T17:18:29Z")

</div>

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).  
-todd

UPDATE: Works! Thanks! 🙂

---

<div class="post-metadata">

**Author:** ![MuliptisiousCandyBan](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/muliptisiouscandyban/32/6115_2.png) [@MuliptisiousCandyBan](https://discourse.joplinapp.org/u/MuliptisiousCandyBan)\
**Post date:** [14 December 2020 17:45 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/8 "2020-12-14T17:45:03Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![MuliptisiousCandyBan](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/muliptisiouscandyban/32/6115_2.png) [@MuliptisiousCandyBan](https://discourse.joplinapp.org/u/MuliptisiousCandyBan)\
**Post date:** [14 December 2020 17:47 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/9 "2020-12-14T17:47:11Z")

</div>

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](https://github.com/laurent22/joplin/issues/4222#issuecomment-744486282).

---

<div class="post-metadata">

**Author:** ![t0dd](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/t0dd/32/743_2.png) [@t0dd](https://discourse.joplinapp.org/u/t0dd)\
**Post date:** [14 December 2020 22:39 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/10 "2020-12-14T22:39:12Z")

</div>

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

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

```external\_css  
/home/todd/css/toddwarner-common.css  
```

```external\_css  
/home/todd/css/toddwarner-joplin.css  
```

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.

---

<div class="post-metadata">

**Author:** ![MuliptisiousCandyBan](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/muliptisiouscandyban/32/6115_2.png) [@MuliptisiousCandyBan](https://discourse.joplinapp.org/u/MuliptisiousCandyBan)\
**Post date:** [15 December 2020 08:32 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/11 "2020-12-15T08:32:14Z")

</div>

Hmm, that is strange.

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

```auto
'''external_css
/Users/user/Downloads/JoplinProfile/test.css
'''

<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.  
 ![image](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/2X/0/0c9ba6304af6410c4cd20150a37010956b7e1f1d.png)

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?

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [15 December 2020 08:42 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/12 "2020-12-15T08:42:07Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![MuliptisiousCandyBan](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/muliptisiouscandyban/32/6115_2.png) [@MuliptisiousCandyBan](https://discourse.joplinapp.org/u/MuliptisiousCandyBan)\
**Post date:** [15 December 2020 08:53 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/13 "2020-12-15T08:53:13Z")

</div>

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.

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

```

Hardcoded version:

```auto
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.

---

<div class="post-metadata">

**Author:** ![tessus](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/tessus/32/13_2.png) [@tessus](https://discourse.joplinapp.org/u/tessus)\
**Post date:** [15 December 2020 16:16 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/14 "2020-12-15T16:16:40Z")

</div>

> [@MuliptisiousCandyBan](#):
>
> I don't know if this is because of something Joplin does

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

---

<div class="post-metadata">

**Author:** ![MuliptisiousCandyBan](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/muliptisiouscandyban/32/6115_2.png) [@MuliptisiousCandyBan](https://discourse.joplinapp.org/u/MuliptisiousCandyBan)\
**Post date:** [16 December 2020 13:57 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/15 "2020-12-16T13:57:46Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![fedwards01](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/fedwards01/32/5103_2.png) [@fedwards01](https://discourse.joplinapp.org/u/fedwards01)\
**Post date:** [16 December 2020 15:10 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/16 "2020-12-16T15:10:35Z")

</div>

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

eg.

> ```
> <style>
> @import "/Users/fred/.config/mod001.css";
> </style>
> 
> ```

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [16 December 2020 16:22 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/17 "2020-12-16T16:22:07Z")

</div>

> [@MuliptisiousCandyBan](#):
>
> A bug in the way the application deals with plugins or with the plugin itself?

a bug in the way the app deals with plugin

---

<div class="post-metadata">

**Author:** ![t0dd](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/t0dd/32/743_2.png) [@t0dd](https://discourse.joplinapp.org/u/t0dd)\
**Post date:** [16 December 2020 16:50 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/18 "2020-12-16T16:50:57Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![MuliptisiousCandyBan](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/muliptisiouscandyban/32/6115_2.png) [@MuliptisiousCandyBan](https://discourse.joplinapp.org/u/MuliptisiousCandyBan)\
**Post date:** [16 December 2020 19:43 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/19 "2020-12-16T19:43:47Z")

</div>

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...

---

<div class="post-metadata">

**Author:** ![fedwards01](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/fedwards01/32/5103_2.png) [@fedwards01](https://discourse.joplinapp.org/u/fedwards01)\
**Post date:** [16 December 2020 20:42 UTC](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/20 "2020-12-16T20:42:41Z")

</div>

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.

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

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

> \<style\>  
> @import "./44153d315e5547e8a24b51eef41dcb3e.css";  
> \</style\>

or both together

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

[Next page](https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016.md?page=2)
