Responsive Presentation Slides With Working Links And More - CSS Hack

Introduction

When I started using the built-in Slides plugin, I hoped it would be a great way to synthesize my notes in a visual working order, on top of the other awesome tools obsidian has to offer. While the basic functionality of the plugin is great, internal links do not work:

  • No note preview is displayed when hovering cursor over link
  • No note is displayed when clicking the link; computer prompts to open link in new app

Here, I present my solution to this by designing a new type of slide presentation using tables, embedded notes, and css. I also introduce some useful functionality that allows for more customization, such as including background images and colors, changing text properties, and changing the size of the slides.


Four Basic Steps

1. Copy and paste each slide’s text in separate notes

  • e.g. [[Slide 1]], [[Slide 2]], [[Slide 3]], etc.

2. In another note, add the following YAML front-matter:

---
cssclass: presentation
---

3. Now, embed your desired slide notes in a column of cells in a markdown table along with the following html:

|                                        | 
|----------------------------------------|
| <div class="anchor">![[Slide 1]]</div> |
| <div class="anchor">![[Slide 2]]</div> |
| <div class="anchor">![[Slide 3]]</div> |

Changes since initial post: (if you want, you may skip directly to step 4 instead)

  1. I initially placed Slide 1 in the table header, but since that resulted in unwanted behavior when exporting to PDF, I shifted it down.
  2. <div class="slide"> was changed to <div class="anchor">
  3. The </div> was moved to after the embedded slide note, not before:
  • i.e.
    • <div class="anchor"></div>![[Slide 1]] was changed to:
    • <div class="anchor">![[Slide 1]]</div>

Why did I make these changes?

  1. To get rid of unwanted export to PDF behavior (apparently table headers appear on every page of an exported PDF, which is not what I wanted for a first/title slide).
  2. To give the css class a more apt name, since it serves as a sort of “anchor point” which can be navigated to directly when scrolling, and does not contain properties of the slides themselves. Hence, anchor, not slide. I’ve reserved the slide class to defining the slides themselves.
  3. Having the </div> after the embedded slide notes allows for some more flexibility in terms of where exactly I can place the anchor point. As you will see with the css below, I’ve decided to anchor to the center instead of the start of the slides, with the slides now tending to stay centered on the page.

Any downsides to these changes?

  • The only downside comes with change #3, when I moved </div> to after the embedded slide notes:
    • Using the ↓PageDown button while scrolling may frequently stop working or not work entirely (not sure why), especially with smaller sized slides.
      • ALTERNATIVE:
        • Use the Space Bar to scroll DOWN through slides.
        • Use the ↑ PageUp to scroll UP through slides.
          (Note: unlike ↓PageDown, the ↑PageUp button still seems to be working fine).
        • IF you’d like to keep the original functionality, you may change </div> back to its previous position, but keep in mind that you would be limiting yourself to scrolling between the start of the slides instead of their center, and would need to make the appropriate change in your css (see below).

4. In your CSS snippets (or obsidian.css file), add the following CSS to allow for scrolling between slides:

.presentation {
/*Set the presentation to snap directly to the slides upon scrolling up 
  and down along the y-axis*/
   scroll-snap-type: y mandatory; 
}

.anchor {
/*Snap to the center of the slides upon scrolling. Other options include
  snapping to the "start" or the "end" of the slides.
  NOTE: If you decide to change the positioning of </div> to before
  the embedded slide notes, change this to "start"*/
   scroll-snap-align: center; 
}

The result should be something like this (using Space Bar to scroll down and ↑ Page Up to scroll up on the active pane):


Post-Processing

As you can see, the above works well in terms of scrolling between slides, but it calls for some more tweaking with CSS. The CSS I’ve attached below is meant to make the slides more aesthetically pleasing and to give them increased functionality. Note that the attached CSS already includes the CSS I’ve previously mentioned above. Also, the html in the table should be changed to follow this more complete format:

|                                              | 
|----------------------------------------------|
| <div class="anchor slide {more css classes}">![[Slide 1]]</div> |
| <div class="anchor slide {more css classes}">![[Slide 2]]</div> |
| <div class="anchor slide {more css classes}">![[Slide 3]]</div> |

I’ve also attached four demo slide notes (.md files) and the associated Presentation.md file that works straight away with the CSS I provided. In the Presentation.md file, this is how the above html looks:

|                                                    |
| -------------------------------------------------- |
| <div class="anchor slide cover">![[Slide 1]]</div> |
| <div class="anchor slide body">![[Slide 2]]</div>  |
| <div class="anchor slide">![[Slide 3]]</div>       |
| <div class="anchor slide end">![[Slide 4]]</div>   | 

Below you’ll find my css in two files (with and without comments), the four demo slide notes, and the Presentation.md file. Download and peruse to your heart’s content. For the sake of brevity, I will not be physically including the CSS lines in this post.

Slides Presentation.css (11.4 KB)
Slides Presentation (without comments).css (4.7 KB)
Presentation.md (368 Bytes) Slide 1.md (63 Bytes) Slide 2.md (541 Bytes) Slide 3.md (508 Bytes) Slide 4.md (91 Bytes)


Features of Presentation Slides

There are five main features of the slides (in addition to working links) which I want to highlight, made possible through obsidian’s design and through CSS:

  1. Previewing Your Slides Before Adding Them to Your Presentation
  2. Sizing and Resizing Your Slides
  3. Changing the Text Properties of Your Slides
  4. Adding a Background Color or Background Image to a Slide
  5. Exporting Slides to PDF

1. Previewing Your Slides Before Adding to Presentation

To see how a slide would look like before adding it to your presentation, add the following to the slide note header and view in preview mode:

---
cssclass: slide {more css classes}
---

Example: You will find that for the first demo slide, the YAML Header includes both the slide class and the cover class, since there are css styles that the first slide took from the cover class as well:

---
cssclass: slide cover
---

2. Sizing and Resizing Your Slides

To set your own custom default size for your slides, change the number in the following line in the css. At a default slide height of 400px, the line reads:

 --height-number: 400;

Example: You can change the default slide height to be 500px as follows:

 --height-number: 500;

Now, just because the default slide height is 500px, it doesn’t mean you can’t have bigger or smaller slides for presentation purposes. You can define different CSS classes for different slide sizes to suit your presentation needs depending on context.

You’ll see in the attached CSS, there are two classes, one named .small-slides and the other named .large-slides. You can use either class by adding it to the YAML header of the presentation file:

  • To display large slides:
---
cssclass: presentation large-slides
---
  • To display small slides:
---
cssclass: presentation small-slides
---
  • To display normal slides:
---
cssclass: presentation
---

To make your own slide size class, simply follow the same format as the large-slides or small-slides classes, with the only line needing to be tweaked being the following:

--screen-zoom: 0.5;

In the line above, 0.5 means the slides will appear half their default size. To make this factor bigger or smaller, simply tweak the number.


3. Changing the Text Properties of Your Slides

Obsidian’s native mode (with no themes) comes with a pretty convenient way of changing the overall size of text, provided you did not already set definitions for font-size in your css. Unlike when I first posted, I avoided defining font-size for the different headers and the like in my CSS this time around, partly so I can make use of this nifty feature.

Go to Settings → Appearance → Font size. You’ll see a slider that you can smoothly adjust to increase or decrease the font size in pixels that affects the editor and preview. By extension, this has the effect of quickly changing your overall font size in your slides if you are not happy with the current appearance. A plus is that these changes carry over when you export your slides to PDF.

Of course, if there are particular textual elements (such as certain headings or text inside a table) whose size you don’t want changing in this manner, or if you want to be in control over the size of all your text, you can always set font sizes in css that will then be fixed and won’t change with obsidian’s Font size slider. For example, for slide 1 (which used the cover css class), I set the heading to be a large custom size, and I changed the bottom margin:

.cover h1 {
  font-size: 45px;
  margin-bottom: -15px;
}

It is also useful to change the text properties of an individual slide if that slide has a background that makes the text hard to see in its original color. For example, the color of the text in slides 1 and 2 were changed to black using the following css (slide 1 applied the cover css class, and slide 2 applied the body css class):

.cover h1, .body h1, 
.cover h2, .body h2, 
.cover h3, .body h3, 
.cover h4, .body h4, 
.cover h5, .body h5,
.cover h6, .body h6,
.cover p,  .body p,
.cover li, .body li,
.cover th, .body th,
.cover .markdown-embed th, .body .markdown-embed th,
.cover td, .body td,
.cover .markdown-embed td, .body .markdown-embed td{
   color: black !important;
}

4. Adding a Background Color or Image to a Slide

If you would like to add a background color or image to a slide, do the following:


→ To add background color, you can change the html of the desired slide’s cell as follows:

| <div class="anchor slide" style="background-color: darkgrey;">![[Slide 2]]</div> |

You can also instead define a new css class with background-color: darkgrey and assign the div element that class:

.body {
    background-color: darkgrey;
}
| <div class="anchor slide body">![[Slide 2]]</div> |

→ To add a background image, you can define a new class and assign it to the corresponding div element:

.cover {
    background: url('app://local/C://file/path/image.png'); /*set the local file path of the desired background image or an internet link.*/
    background-size: 100% 100%; /*fill background with 100% of image*/
    background-repeat: no-repeat; /*do not repeat background image*/
}
| <div class="anchor slide cover">![[Slide 1]]</div> |

5. Exporting Slides to PDF

Simply Export to PDF in Landscape mode with Letter sizing and Default margins, and a pdf with one slide per page will be generated, scaled to size from how they appeared in obsidian.

(Originally, to export slides to PDF, some tweaks were needed for the html in order to correctly adjust the margins. But now, I am happy to report that no tweaks are needed to the html and no additional CSS besides what I’ve already attached is required for exporting to PDF. If any issues arise, please let me know).


Putting it all together:

Here is how everything can come together to give a beautiful result (these are older gifs from before I implemented the most recent changes, but they serve the point of illustration; will update them soon):

Also, given how this presentation was made, internal links will work. I’ve incorporated some internal links into the presentation notes for illustration purposes. I’ve pinned the panel containing the presentation so that the links can be visualized in a separate panel to minimally interrupt the presentation flow:


Hope for the Future

Given the simple step-by-step manner we can take to make a decent slide presentation by following the above approach, it would be nice to have a plugin that automates the above steps for the user.

That said, I do not currently possess the skill set to make a third-party plugin, although I can always learn. It would be awesome, however, if someone can take up this project. I would be glad to support however I can.

Let me know your thoughts!

13 Likes

This is very impressive. I have been struggling with export to PDF, the results of which I am not happy with. I have not looked into slides plug-in, but this seems even more useful.

Do you know what this looks like if a series of slides is exported? Does the background export well? Could export of an entire presentation serve as a book(let)?

Thank you for the feedback @Klaas. I actually didn’t think much about exporting the slides to PDF until you mentioned it. But I looked into it and it can be done. Just follow these steps:

  1. Keep the header of the table empty*, and add some more html to make the top margins of the final pdf pages consistent in size and color:
|                                                                     |
|---------------------------------------------------------------------|
| <div class="slide"></div>![[Slide 1]]                               |
| <div class="spacer"><br></div><div class="slide"></div>![[Slide 2]] |
| <div class="spacer"><br></div><div class="slide"></div>![[Slide 3]] |
  • *Note: Apparently, the content of the header appears at the top of every page on the pdf, and that’s not how a title slide should behave, so we might as well not have a header.
  1. Add the following css:
@media print {
  th{
    display: none; /*do not show the header*/
  }
  tr{
    /*display each row of the table (i.e. each slide) on a separate page*/
    display: block;
    page-break-before: always;
  }
  td{
    background-color: var(--background-primary); /*set the default background color 
                               of each slide as the background color of your vault*/
    width:100vw; /*set each cell (slide) to fill 100% of the pdf width*/
    height:94vh; /*set each cell (slide) to fill 94% of the pdf height (to make 
                   some room for pdf margins)*/
    padding:0px !important; /*set each cell's padding to 0 so whatever uniquely added
                             background images or colors fully cover the default background
                             color*/
  }

  h1, 
  h2, 
  h3, 
  h4, 
  h5, 
  h6, 
  p, 
  li{
    color: var(--text-normal); /*set the color of all text as the normal color you use in
                               your vault. Any text colors assigned elsewhere with greater css priority/specificity
                               will take precedence, which includes any new text colors you add to 
                               the slides.*/
  }

  .spacer{
    background-color: white; /*define a spacer class with a white background color to
                              be used in making consistent top margins on the pdf pages*/
  }
}
  1. Export to PDF in landscape mode. Any of the margin options are fine (we already did some margin manipulation with html). The PDF will show one slide per page. You should end up with something like this:

As you can see, the slides can now be exported into a pdf with the appropriate background and text color for each slide.

I hope this helps! Let me know if any other questions come up.

3 Likes

@Salamander23 : wow, that is incredible. I am going to try it out.

@Salamander23 : I just tried it out, and I can report it works perfectly !!
Many thanks.

2 Likes

Glad to help!

2 Likes

Brilliant. Thank you very much for sharing this.

It looks great, but is this still working?
i added the css and the md files provided, but i have a weird behavior, the presentation is not fullscreen, and i cannot switch slides (see below). Note that the export to pdf works correctly.
i tried with a new vault and the latest obsidian version, no plugins.


thanks.
edit: i think i understand the issue, i was trying to use the “start presentation” function, but i only need to use “preview” for it to work. My bad :slight_smile: