CSS for Roam (4. lesson): Pseudo-classes

And more magic with #tags

We made it together to the 4th lesson focusing on CSS for Roam and we still have so much to cover. And while programming JavaScript is rather a difficult task, CSS is a safe playground where anybody can experiment with almost non-existent danger to their precious treasure of ideas called the Roam graph. If this is your first story on CSS for Roam you read from me, please, check out the whole series.

On this little journey, we have already learnt so many things! We can select any element in CSS based on their type, class, ID or attribute, we can select elements also based on their position, we can then change their color or make them disappear! All of that with just a couple of magic words written in a code-block under roam/css. This time, we will move to something that does and does not exist at the same time! Let us learn about pseudo-classes!

This may sound weird, I know! Does it mean that they do not exist? Actually, yes. And no! — They do not exist from the point of view of the HTML code. There are nowhere to find there, yet, they do exist for the web browser and their effects are visible to our eyes. In this lesson, we will learn about them and look at some practical uses for our magic with #tags.

What are they?

Normally, classes are a specific attribute of HTML elements. Do you remember this old example where we looked at the HTML code of the page title in Roam?

Roam — code of the page title
Roam — code of the page title
Roam — code of the page title

The element <h1> means the main headline. Its class attribute is rm-title-display . And as you can see on the right, it has some specific properties, like the height of the line or the weight of the font. If we want to select this class in CSS and change its styling, we can simply write:

.rm-title-display {
display:none;
}

And now all titles of our web pages disappeared! Great…

Haven’t I said that there is no risk involved in creating custom CSS? Well, this is true in 99% cases, but please: don’t make disappear the essential parts of Roam like the title of your page. If that happens to you and you cannot find your way into roam/css to deactivate that piece of … code, you can always use the safe start: Add this little piece of code after the URL of your database: ?disablecss=true and everything will be okay. Your URL then should look like this:

https://roamresearch.com/#/app/DATABASENAME?disablecss=true

Back to the class(es): .rm-title-display and many others are normal classes in Roam. They are written in the code. What are thus the pseudo-classes? They are similar but as their name suggest, they are not written anywhere. Basically speaking, they allow us to select an element in a specific state. What do I mean by the “state”? A typical example is a link to another web page: a link could have been visited before or it has not been visited by the user yet — these are both specific states. There are quite a lot of pseudo-classes and their number is growing.

I believe that the most interesting ones for customizers of Roam are those that relate to the position of elements because they give us the possibility to access them in a way that is otherwise not possible.

Pseudo-classes by position

Basically, we are dealing with the position of selected elements regarding their parent. There are two similar groups of pseudo-classes: one that selects only specific children, and one that takes also their type into account.

What do I mean by that? Let’s look at the :first-child pseudo-class and its friend :first-of-type .

Roam block with bold and emphasized text.
Roam block with bold and emphasized text.

And this is what we can see in the code:

Code of the Roam block with bold and emphasized text.
Code of the Roam block with bold and emphasized text.
Code of the Roam block with bold and emphasized text

Here, we have the bold text as the <strong> HTML element and emphasized as the <em> HTML element. Now let’s try to change the color of the emphasized text. We can do it quite easily:

em {color: red;}

And it works perfectly!

CSS code changing the color of <em>.
CSS code changing the color of <em>.

Now, let’s try to add :first-child .

CSS code showing that em:first-child does not change the color of the emphasized text because it is not the first child.
CSS code showing that em:first-child does not change the color of the emphasized text because it is not the first child.

This does not work because the emphasized text is actually the second child of the parenting <span> tag that is the only child of the parenting <div> — that encompasses the whole block. The first child is the bold text.

What if we use :first-of-type instead?

CSS code showing that em:first-of-type works because it is the first of that type.
CSS code showing that em:first-of-type works because it is the first of that type.

This works as intended. Now we select <em> that is the first child of <span> of its type. This means that if we put more different emphasized pieces of text into our block, only the very first one will be red.

Roam block with two pieces of emphasized text — only the first one is colored red.
Roam block with two pieces of emphasized text — only the first one is colored red.

There are multiple different pseudo-classes working in a similar way. I think you can guess this relationship:

:first-child, :first-of-type:last-child, :last-of-type

Similarly, we can select nth-child of any element, like its second, third, or fourth child, and we can again specify whether we are concerned with its type or not.

:nth-child(NUMBER) , :nth-of-type(NUMBER)

And we can also count from the back:

:nth-last-child(NUMBER) , :nth-last-of-type(NUMBER)

As you may guess, :first-child is actually the very same thing as :nth-child(1) and :last-of-type is the same thing as :nth-last-of-type(1) :

CSS code showing the use of :nth-last-of-type
CSS code showing the use of :nth-last-of-type

The NUMBER can be also a range or you can select even or odd-numbered children! You can find everything about ranges here.

We can also select an element if it is the only child or the only child of its type:

  • :only-child , :only-of-type

There are also two special pseudo-classes in this category:

  • :empty — This one selects the element if it does not have any children or any content! This is pretty unique in CSS that otherwise does not care about the text content.

How could we use this element? Let’s say we want to add a special icon to any empty block we create in order to draw attention to it:

CSS code showing the use of :empty pseudo-class
CSS code showing the use of :empty pseudo-class

There is no counter-part to this that would select an element based on its content. However, there is a plan to introduce the pseudo-class :has() that would allow selecting elements based on their children! Let’s hope it will be soon realized.

Finally, there is a :root pseudo-class that selects the root of the document. You can use it, if you want to style the whole page.

One more pseudo-class today: the most useful of all

There are so many more pseudo-classes, however, their usefulness for us — customizers of Roam — is rather limited in my opinion. Nevertheless, there is one of the immense power, it is :hover . As its name suggests, it allows you to select an element by hovering above it.

Consider the following case: you want to highlight the block your mouse is hovering over. You can do it by this simple code:

.roam-block:hover {
color:red;
}
CSS code showing the use of :hover pseudo-class
CSS code showing the use of :hover pseudo-class

👉 Note that you can actually use pseudo-classes without attaching them to any element. Remember, they work as classes (therefore they are “pseudo-”). However, it is common to use them in the compound selectors as shown above and bellow.👈

Now, let’s see some practical use of :hover. A typical example is to use it for revealing a hidden piece of text. Imagine, e.g., that you are learning some specific terminology and you want to test yourself. Perhaps, your blocks could look like this:

Sample blocks in Roam with Question and Answer
Sample blocks in Roam with Question and Answer

Now we want to hide the answer to our question. Probably the easiest way is to highlight the answer with ^^TEXT^^ . We can easily select the .roam-highlight class and black it out.

CSS code blacking out the highlighted text.
CSS code blacking out the highlighted text.

Great. But how to make it appear again? Simply create a new rule-set with .roam-highlight:hover and change the values back to default.

CSS code showing the blacked out text being displayed on hover.
CSS code showing the blacked out text being displayed on hover.

However, we are not done yet. As you can imagine, now we have a new issue: all highlights behave like this! We can’t see the content of any of them without hovering over them.

Roam block showing that all highlighted text is now blacked out
Roam block showing that all highlighted text is now blacked out

Here we can employ what we learnt the last time about #tags affecting other elements. We have seen this fancy example of using #tags for custom highlighting colors:

CSS code for coloring highlights based on preceding #tags
CSS code for coloring highlights based on preceding #tags

What we want to do now, is actually very similar! Let’s convert “Answer” to #answer and modify the code appropriately.

CSS code showing the use of #tag to blackout and display again on hover the following highlighted text
CSS code showing the use of #tag to blackout and display again on hover the following highlighted text

Now it should work perfectly. You can use this trick to hide and display many different elements as you wish. And that is all for today.

Next time we will look at companions to pseudo-classes: pseudo-elements! So stay tuned!

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