Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Obsidian scss

Obsidian SASS theme switching tools

I was building up a small library of css snippets, and mixing and matching via copy-paste was getting tiresome.
So, I knocked myself up a little solution using https://sass-lang.com/
To use this solution, you need to follow the instructions on the website to install the SASS command line utility.

Instructions

For my purposes, I created a subfolder in my Obsidian vault called ./.themes where my obsidian.scss file lives. I also created a subfolder for mixins (./.themes/mixins) containing small snippets like "Andy Matuschak" mode and collapsing sidebars (and my preferred custom colours for my Base2Tone theme)

For themes I want to switch between which have git repositories, I check them out into the .themes folder, and can reference them from my obsidian.scss with the @add directive, alongside @adding any of the mixin tweaks I want (I've included an example of my obsidian.scss below)

Once I'm happy with the theme and mixins I want, I run the following command from the root of my obsidian vault: sass .\.themes\obsidian.scss .\obsidian.css
This will compile the obsidian.css file and place it in my vault. A few moments later, Obsidian is looking different!

Bonus: Syntax highlighting themes

The syntax highlighting uses Prism.js and there are plenty of themes available.
Obsidian does wrap them in .theme-dark or .theme-light classes though, so you can't just drop in a theme and expect it to work.

This is exactly the kind of thing SASS is good at. Just wrap the whole theme in a .theme-dark { or .theme-light { block, and SASS will generate the appropriate css.
I've included the theme I'm using (originally from here) as an example.

/* .themes/mixins/_andy-matuschak.css */
/* Andy Matuschak mode! */
.workspace-split.mod-vertical { overflow-x:auto; }
.workspace-leaf, .workspace-split > .workspace-split { min-width: 500px; min-height: 500px; }
.workspace-split.mod-horizontal { overflow-y: auto; }
/* .themes/mixins/_Base2Tone-sfs.css */
:root {
/* change these hues for an entirely new look */
--uno: 231;
--duo: 9;
/* this is a hack workaround for now */
/* go to https://convertacolor.com/ to convert the --baseD0 hsl to rgb */
/* i.e. hsl(--duo, 58%, 55%) */
--D0-rgb: 207,94,74;
}
/* .themes/mixins/_collapsing-sidebars.css */
/* Collapsing sidedocks, courtesy of kmaasrud#1732 (https://github.com/kmaasrud/clean-theme-obsidian) */
.app-container.is-left-sidedock-collapsed .side-dock.mod-left:not(:hover), .app-container.is-right-sidedock-collapsed .side-dock.mod-right:not(:hover) {
width: 5px !important; /* 5px so there's still something to hover on if not fullscreen */
}
/* .themes/mixins/_font-mixins.scss */
@mixin preview($font) {
.cm-s-obsidian, .markdown-preview-view{
font-family: $font;
}
}
@mixin editor($font) {
.markdown-source-view,
.cm-s-obsidian .cm-url {
font-family: $font;
}
@include operators($font);
}
@mixin operators($font) {
.cm-s-obsidian .hmd-fold-html-stub,
.cm-s-obsidian .hmd-fold-code-stub,
.cm-s-obsidian.CodeMirror .HyperMD-hover > .HyperMD-hover-content code,
.cm-s-obsidian .cm-formatting-hashtag,
.cm-s-obsidian .cm-inline-code,
.cm-s-obsidian .HyperMD-codeblock,
.cm-s-obsidian .cm-formatting-task,
.cm-s-obsidian .cm-hmd-indent-in-quote,
.cm-s-obsidian .HyperMD-hr,
.cm-s-obsidian .cm-hmd-frontmatter,
.cm-s-obsidian .cm-hmd-orgmode-markup,
.cm-s-obsidian .cm-formatting-em,
.cm-s-obsidian .cm-formatting-strong,
.cm-s-obsidian .cm-formatting-strikethrough,
.cm-s-obsidian .cm-formatting-code,
.cm-s-obsidian .cm-formatting-link,
.cm-s-obsidian .cm-formatting-image,
.cm-s-obsidian .cm-math,
.cm-s-obsidian span.hmd-fold-math-placeholder,
.cm-s-obsidian .CodeMirror-linewidget kbd,
.cm-s-obsidian .hmd-fold-html kbd {
font-family: $font;
}
}
@mixin urls($font) {
.cm-s-obsidian .cm-url {
font-family: $font;
}
}
@mixin code($font) {
body {
--font-monospace: $font;
}
}
/* .themes/obsidian.scss */
/* Stuff I'm using right now */
@use 'Base2Tone-For-Obsidian.md/obsidian.css'; // the theme I'm using
@use 'mixins/Base2Tone-sfs'; // my cutom 2tone colours
@use 'mixins/andy-matuschak'; // Andy Matuschak mode
@use 'mixins/collapsing-sidebars'; // collapsible sidebars
@use 'mixins/font-mixins' as fonts; // some helper mixins I made for fonts
@use 'prism-vdc-dark-plus'; // a prism theme I found for changing the syntax highlighting theme
// These are the fonts I prefer (overrides anything defined in the theme above)
body {
--font-editor: 'Inter', sans-serif;
--font-preview: 'Inter', sans-serif;
--font-monospace: 'Fira Code', monospace; // for code blocks
}
// run the mixins to change the fonts
@include fonts.preview(var(--font-preview));
@include fonts.editor(var(--font-editor));
/* These are some of the themes I have checked out
* I'll comment out the code above and uncomment the one I want to use
*/
// 'Ursa' (Bear) theme by @ezs
// @use 'obsidian-ursa/obsidian.css';
// Roam theme by me
// @use 'Obsidian-Roam-theme/obsidian.css';
// 80's Neon theme by me
//@use '80s-Neon-for-Obsidian.md/obsidian.css';
/* .themes/prism-vdc-dark-plus.scss */
.theme-dark {
pre[class*="language-"],
code[class*="language-"] {
color: #d4d4d4;
font-size: 13px;
text-shadow: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
background: #1e1e1e;
}
:not(pre) > code[class*="language-"] {
padding: .1em .3em;
border-radius: .3em;
color: #db4c69;
background: #f9f2f4;
}
/*********************************************************
* Tokens
*/
.namespace {
opacity: .7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #6a9955;
}
.token.punctuation {
color: #d4d4d4;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #b5cea8;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #ce9178;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #d4d4d4;
background: #1e1e1e;
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #c586c0;
}
.token.function {
color: #dcdcaa;
}
.token.regex,
.token.important,
.token.variable {
color: #d16969;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.constant {
color: #9CDCFE;
}
.token.class-name {
color: #4EC9B0;
}
.token.parameter {
color: #9CDCFE;
}
.token.interpolation {
color: #9CDCFE;
}
.token.punctuation.interpolation-punctuation {
color: #569cd6;
}
.token.boolean {
color: #569cd6;
}
.token.property {
color: #9cdcfe;
}
.token.selector {
color: #d7ba7d;
}
.token.tag {
color: #569cd6;
}
.token.attr-name {
color: #9cdcfe;
}
.token.attr-value {
color: #ce9178;
}
.token.entity {
color: #4ec9b0;
cursor: unset;
}
.token.namespace {
color: #4ec9b0;
}
/*********************************************************
* Language Specific
*/
pre[class*="language-javascript"],
code[class*="language-javascript"] {
color: #4ec9b0;
}
pre[class*="language-css"],
code[class*="language-css"] {
color: #CE9178;
}
pre[class*="language-html"],
code[class*="language-html"] {
color: #d4d4d4;
}
.language-html .token.punctuation {
color: #808080;
}
/*********************************************************
* Line highlighting
*/
pre[data-line] {
position: relative;
}
pre[class*="language-"] > code[class*="language-"] {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: #f7ebc6;
box-shadow: inset 5px 0 0 #f7d87c;
z-index: 0;
pointer-events: none;
line-height: inherit;
white-space: pre;
}
}
@mrkuramoto
Copy link

mrkuramoto commented Jan 29, 2021

Thank you for sharing your knowledge about CSS - it is not easy to get information about it and count on contributors like you is it very nice. I don't want to bother you but I will take my chance and make a question: do you know how to add extra spaces between blocks in preview mode? I had success in the edit mode but never in preview mode.

@v2keener
Copy link

v2keener commented Oct 4, 2021

Thanks so much @deathau for providing this resource! Using your instructions and the *scss you provided, I've been able to take parts of any Obsidian theme and modify them in specific ways with mixins (provided the theme uses the same naming convention as app.css). Namely, if I see something I like in a theme and if it's not too difficult to isolate the CSS, I try it first in my main SCSS file and then pull that code out to a well-named mixin. I'll credit this gist when I get what I've done checked in. It's based on Obsidian Nord, but without your code it would have been more challenging for me to identify design elements that I could make somewhat modular with mixins.

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