CSS for Roam (1st lesson): Roam with Style

Last update: 26th Dember 2020

Give your Roam a little bit of make-up, based on an image from undraw.com.

Create your first CSS for your second brain

Last week, I have discussed the holy technological trinity in Roam that enables us to basically create our own little internet: We can use basic building block of websites, so-called HTML (with :hiccup syntax), custom styles using CSS, and add interactivity thanks to JavaScript. The big addition to this is the recently announced API that will allow for even greater possibilities.

In this blog post, I will describe generally what CSS is, including some of its limitations. Additionally, we will create our very first little custom CSS code for our beloved second brain in Roam.

What do you need to know before you start with CSS?

Frankly, very little. However, remember that CSS modifies the appearance of webpages and webpages are built from HTML elements. You should therefore have an idea what HTML is and how HTML elements work.

Don’t worry, it’s nothing complicated. HTML stands for “Hypertext Markup Language” — The key part for us is the “Markup”. In comparison with typical programming languages like C#, Python or JavaScript, we don’t have to work with variables, functions or loops in HTML. Instead, we only “mark up”, i.e., label chunks of text. To give you an example: If we want to say that a specific text is a headline, we put it into <h1> tag like this: <h1>Roam with Style</h1> . Moreover, tags can have specific attributes. E.g., an image can have a specific height or width, a font can have a certain colour. Today, much of the styling is done not directly in HTML but rather using CSS which we will learn. The opening and closing tags together with the wrapped text constitute an HTML element.

Structure of an HTML Element
Structure of an HTML Element
Structure of an HTML Element. Created by the uploader, Aapo Laitinen, https://en.wikipedia.org/wiki/File:HTML_element_structure.png#filelinks

The last important thing to know about HTML is the structure of the document. One element is always contained by another one. This structure is described usually as a tree that has one single<html> element at its root and then various branches. Frankly, I find this description a little weird because the <html> element has as its “children” <head> and <body> (and they themselves have other children …). So I guess it is quite an unusual tree. But well, I guess nobody and notree is perfect.

Document Object Model of an HTML document. By Birger Eriksson — Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=18034500

Remember the existence of this tree with a head and body and children because we will come back to it shortly.

What does CSS actually mean?

CSS stands for “cascading style sheets”. Style sheets are probably easy to understand. They are collections of style rules, kind of templates that tell the browser how to display various HTML elements. Let’s say we have a link to another webpage. Usually, it is displayed as underlined blue text. However, maybe we prefer to display all links as buttons or we want to have all links in amazing rainbow colour. All of this is possible with style sheets. But why are they called “cascading”?

It happens often that there are many different and multiple rules set up for the same thing. Imagine again a simple link: There is a default style in the browser for it (like a blue underlined link), then there is the style provided by the authors of the website (like a button style), then our custom CSS (🌈). “Cascading” means that the priority order of these rules is specified and fixed. This is very important. Moreover, the more specific rule is stronger than the less precisely targeted rule. It may therefore often happen that our nice little code does not work even though it seems it should: this may be because it has a lower priority than existing formatting we want to change.

What can we change with custom CSS?

Typically, CSS is used to change the appearance of text or HTML elements, such as tables. However, its usage goes much further: CSS is used for complex page layouts. With a simple CSS rule, we can change the position or order of the elements on the webpage (even in Roam!). Modern CSS allows also for image filters, transformations, and animations. And there are even people creating complex graphics in CSS alone — but this is more for fun than practical reasons. Importantly, CSS can be even used to add little pieces of content — mainly text and images. This functionality is limited but it will be very useful for us Roaman nerds.

Every language has its vocabulary and grammar. Programming languages are not different. Luckily, they are much neater and simpler than natural languages. The basic grammar of CSS looks like this:

SELECTOR { /* i.e. what we want to select */
/* Declaration */
CSS_PROPERTY_1: VALUE;
CSS_PROPERTY_2: VALUE;
CSS_PROPERTY_3: VALUE;
....
}

So if we would like to give the red color to the main headline (which in HTML is <h1>, element), we can simply write:

h1 {
color: red;
}

In comparison to other programming languages, in CSS we don’t have to care about if-conditions, complicated loops, or functions. The most challenging part is usually to figure out the right way to select the element we want to change.

Which parts of the webpage can we change with CSS?

Basically, we can change the appearance of any element that we can select. We can select elements based on their:

  • tag (like a link, headline, emphasised text)
  • attributes (like the address of the link)
  • class (a special attribute that is being used for assignment of CSS styles)
  • ID (a unique identifier of an element that cannot be repeated on the webpage).

In other words, we can select elements in many different ways with one important exception: We CANNOT select elements based on their content.*

(* We will learn later that there are some rare exceptions to this rule, e.g. it is possible to select empty elements.)

We can also select elements based on the number of their states, e.g.:

  • was the link clicked?
  • is the element hover over?

Moreover, we can select elements by their position. E.g., we can select all links that are part of a list, but not other links elsewhere in the document. Also, we can select elements that follow on the same level or a specific child of an element. However: We CANNOT select any ancestors or parents to a specific element. In other words, we cannot go back or up in the tree.

These are the two main limitations of CSS. Sometimes we might find a way around it: For example, in Roam, if we want the #tag to affect the highlighted text we can put it in front of the highlighted text instead of behind it. In other cases, unfortunately, we have to use JavaScript, e.g., if we want to change the highlighted text based on the preceding checkbox. However, the great Roam Research development team tries to make as many parts of Roam stylable in an unprecedented scale.

Let’s now look more closely on how to use custom CSS in Roam.

Where to put custom CSS?

There are four main places where to put the custom CSS:

  • [[roam/css]] page in Roam itself
  • using :hiccup on any page
  • injection using JavaScript
  • external CSS running in a browser extension like Stylus

All of these have their advantages and disadvantages. However, without a doubt, the easiest way is to use roam/css and this we will discuss today. Now, open the [[roam/css]] page in Roam, create a new outline with H1 style (this will be important later ;)) with a title like Our first code.

After having done this, create a new child outline under your headline, type / and select “code block” from the pop-up menu. A code block will be inserted. As its name suggests, this will be the place where we will put our code. At this moment, it will do nothing. First, we have to tell Roam that the code we wrote is in fact CSS and not JavaScript or something else. To do that change the programming language in the upper right corner to CSS. Great! However, how to find out the element we want to change?

Web inspector to rescue!

Luckily, every modern browser has Developer Tools that have a great feature for inspecting the code of the webpage. It can be activated either from the menu bar, with a keyboard shortcut, or even easier by the right click of the mouse and selecting inspect, inspect element or similar from the context menu. The essential function of the web inspector is that we can point and click on any element of the webpage and we will get its code.

Now, let’s say we want to change the appearance of the page title. Open the web inspector and click on the arrow and then point to the title of [[roam/css]]. You should get something like this:

You can see that the web inspector highlighted for us both the element of the website and the corresponding code. In our case, the code is rather simple:

So, let’s make it red. Make sure that you have selected “css” as the language of your code box. Now write the following code into your code block:

h1 {
color: red;
}

Aaaand the result is…

Nothing! Nothing has happened! Why? Do you remember? We are working with CSS — Cascading Style Sheets. The rule that we created is just simply not high enough on the priority list and it gets overwritten by a more specific selector.

Actually, we can even find it in the Web Inspector. Select again the title of the page and write into the right textfield under “styles” tab the property “color”.

Oh, our style is being overridden by this:

The reason is that this selector is much more specific than our selector and thus it gets priority. We just say: “Select all h1 elements”. But the existing definition says: “Select all h1 elements that are children of the element belonging to the class roam-app that are children of the element belonging to the class roam-body.”

So what can we do with that? The most brutal, not really recommended but admittedly effective solution is to use a magic word “!important”. If we add it to our declaration, we override everything else. Let’s try it:

Hey, it works! Now our rule is the most important from all rules. You may, however, ask, why isn’t it a so good practice to use the amazing power of “!important”? Well, as we add more and more rules, it can make our style sheets quite confusing: suddenly it becomes less and less clear what the priority of the different styles is. So if you can, try to make your selector more specific, e.g. we can simply copy the existing selector:

This works perfectly, but you might notice one weird issue: not only [[roam/css]] is red but also “Our first code” because they both fulfil the criteria.

However, we can try a different solution. Let’s look again at the code.

There is defined a class called “.rm-title-display”. This is a unique class only for page titles — so this allows us to select these titles while skipping headlines that are part of the outline.

The dirty !important solution:

The elegant (although verbose) solution:

And here we are. We have made our first, very little piece of CSS for our second brain (or the third one, or the fourth one, or the fifth one… ). It is not perfect. If you click on the page title, the colour disappears and reappears when you click elsewhere. But it works now. Next time, we will dive deeper into the territory of CSS and we will look at powerful #tags and [[pages]]. You will be surprised what we can do with them!

If you like my work, follow me on Twitter, check the public Roam database Roam-tricks, my personal public collection of my hacks, and yes, you can support me on Patreon or through PayPal . I would really appreciate it and you would help to make future articles happen. And remember: If it looks like a duck, if it writes like a duck, it’s probably me. [[QUACK]]!

Just a humble Roaman duck.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store