cssr-markdownbulletioslides

Changing Bullet Type in ioslides via CSS


I would like to be able to change the style of R-Markdown-generated bullets in ioslides document-wide through the CSS file.

I understand that I can use HTML to change the format of unordered bulleted lists within the body of an ioslides file in R Markdown, as is discussed here to change the color. Doing this for every bulleted list seems kludgy.

I tried adding this to the CSS file:

ul {list-style-type: circle;}

which adds a, e.g., circular bullet in addition to the default bullet placed by ioslides.

It therefore appears the crux may be to find a way to remove bullets from unordered lists in ioslides (after which styled bullets can be added in their stead), but adding this to the CSS file:

ul {list-style: none;}

(with our without the previous attribute) does not remove the bullets.

Although the ioslides reference manual is quite useful, neither it nor other searches provided further insights.

Reproducible code for an ioslides presentation in RStudio is:

CSS

(Saved as style.html into the same directory as the .Rmd snippet, below. The code to tweak the bullets is on lines 65 -- 68. This style sheet comes from the ioslides default given here.)

<!DOCTYPE html>
<html$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$>
<head>
  <title>$if(title-prefix)$$title-prefix$ - $endif$$pagetitle$</title>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="chrome=1">
  <meta name="generator" content="pandoc" />



$if(date-meta)$
  <meta name="date" content="$date-meta$" />
$endif$

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="apple-mobile-web-app-capable" content="yes">

  <base target="_blank">

  <script type="text/javascript">
    var SLIDE_CONFIG = {
      // Slide settings
      settings: {
        $if(title)$
        title: '$title$',
        $endif$
        $if(subtitle)$
        subtitle: '$subtitle$',
        $endif$
        useBuilds: true,
        usePrettify: true,
        enableSlideAreas: true,
        enableTouch: true,
        $if(analytics)$
        analytics: '$analytics$',
        $endif$
        $if(logo)$
        favIcon: '$logo$',
        $endif$
      },

      // Author information
      presenters: [
      $for(author)$
      {
        name: $if(author.name)$ '$author.name$' $else$ '$author$' $endif$,
        company: '$author.company$',
        gplus: '$author.gplus$',
        twitter: '$author.twitter$',
        www: '$author.www$',
        github: '$author.github$'
      },
      $endfor$
      ]
    };
  </script>

$for(header-includes)$
  $header-includes$
$endfor$

  <style type="text/css">

ul {list-style: none;}      /* Does not repress ioslides-generated bullets */
li::marker {display: none;} /* Does not repress ioslides-generated bullets */

li {list-style-type: circle;} /* Creates bullest *in addition to* those created by ioslides */

    b, strong {
      font-weight: bold;
    }

    em {
      font-style: italic;
    }

    summary {
      display: list-item;
    }

    slides > slide {
      -webkit-transition: all $transition$s ease-in-out;
      -moz-transition: all $transition$s ease-in-out;
      -o-transition: all $transition$s ease-in-out;
      transition: all $transition$s ease-in-out;
    }

    .auto-fadein {
      -webkit-transition: opacity 0.6s ease-in;
      -webkit-transition-delay: $transition$s;
      -moz-transition: opacity 0.6s ease-in $transition$s;
      -o-transition: opacity 0.6s ease-in $transition$s;
      transition: opacity 0.6s ease-in $transition$s;
      opacity: 0;
    }
/* https://github.com/ropensci/plotly/pull/524#issuecomment-468142578 */
slide:not(.current) .plotly.html-widget{
  display: block;
}

    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    $if(quotes)$
    q { quotes: "“" "”" "‘" "’"; }
    $endif$
    $if(highlighting-css)$
    $highlighting-css$
    $endif$
    $if(displaymath-css)$
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    $endif$

$if(logo)$
    slides > slide:not(.nobackground):before {
      font-size: 12pt;
      content: "";
      position: absolute;
      bottom: 20px;
      left: 60px;
      background: url($logo$) no-repeat 0 50%;
      -webkit-background-size: 30px 30px;
      -moz-background-size: 30px 30px;
      -o-background-size: 30px 30px;
      background-size: 30px 30px;
      padding-left: 40px;
      height: 30px;
      line-height: 1.9;
    }
$endif$
  </style>

$for(css)$
  <link rel="stylesheet" href="$css$" $if(html5)$$else$type="text/css" $endif$/>
$endfor$

</head>

<body style="opacity: 0">

$if(widescreen)$
<slides class="layout-widescreen">
$else$
<slides>
$endif$

$if(include-before)$
  $for(include-before)$
    $include-before$
  $endfor$
$else$
  <slide class="title-slide segue nobackground">
    $if(logo)$
    <aside class="gdbar"><img src="$logo$"></aside>
    $endif$
    <!-- The content of this hgroup is replaced programmatically through the slide_config.json. -->
    <hgroup class="auto-fadein">
      <h1 data-config-title><!-- populated from slide_config.json --></h1>
      $if(subtitle)$<h2 data-config-subtitle><!-- populated from slide_config.json --></h2>$endif$
      <p data-config-presenter><!-- populated from slide_config.json --></p>
      $if(date)$
      <p style="margin-top: 6px; margin-left: -2px;">$date$</p>
      $endif$
    </hgroup>
  </slide>
$endif$

RENDERED_SLIDES

$for(include-after)$
  $include-after$
$endfor$

  <slide class="backdrop"></slide>

</slides>

$if(mathjax-url)$
<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
  (function () {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src  = "$mathjax-url$";
    document.getElementsByTagName("head")[0].appendChild(script);
  })();
</script>
$endif$

<!-- map slide visiblity events into shiny -->
<script>
  (function() {
    if (window.jQuery) {
       window.jQuery(document).on('slideleave', function(e) {
         window.jQuery(e.target).trigger('hidden');
      });
       window.jQuery(document).on('slideenter', function(e) {
         window.jQuery(e.target).trigger('shown');
      });
    }
  })();
</script>

</body>
</html>

.Rmd ioslides code

(Saved as, e.g., test.Rmd into the same directory as style.html, above. This code comes from the ioslides manual.)

---
title: "Habits"
author: John Doe
output:
  ioslides_presentation:
    template: style.html
---

# In the morning
    
## Getting up
    
- Turn off alarm
- Get out of bed

## Breakfast

- Eat eggs
- Drink coffee

# In the evening

## Dinner

- Eat spaghetti
- Drink wine

TYIA


Solution

  • TL;DR:

    To the best of my knowledge, bullets (and many other stylistic elements) can only be changed in the header of the slideshow that is knit from the "CSS" and .Rmd ioslides files.

    Overall Explanation

    (N.b.: for ease, I'll refer to the "CSS" file as style.html, the .Rmd file first created in RStudio as draft.Rmd, and the final slideshow knit from those two files as slideshow.html. Not that the names of all of these files can be changed by the user.)

    My first clue (noted early on and then more or less ignore) was that the "CSS" file is not a cascading style sheet per se. Although by default named "style," the extension is correctly ".html"---not ".css": It's in fact an .html file---although one that contains elements relegated to headers.

    ioslides takes the information in the style.html file and integrates it into different parts of the final slideshow file that is creates from the style.html and draft.Rmd file. The formatting elements for the slideshow.html are all in the header of that file. I.e., there is no separate .css file that slideshow.html accesses for styles.

    This means that some (arguably many) stylistic elements can be modified within the style.html file but any other elements must be modified within the final slideshow.html.

    Of course, changing elements in style.html is easy and allows for quick re-knits to test those changes. It also means that that style.html file can be reused with other .Rmd files for consistent formatting.

    Any other stylistic elements must be changed in the slideshow.html that is (re)knit after any changes to either the style.html or 'draft.Rmd` file. This can be a simple search/replace operation, so far from impossible---just less obvious or automated.

    Answering My Particular Question

    Searching through the header generated in the slideshow.html file, I found:

    ul li ul li:before {
    content: '-';
    font-weight: 600;
    }
    
    ul > li:before {
    content: '\00B7';
    margin-left: -1em;
    position: absolute;
    font-weight: 600;
    }
    

    The second- (etc.) order bullets will still be dashes, so:

    Common regex could expedite this with, viz., searching for content: '.*'; and replacing that with something/nothing else. Of course, one could choose different bullets for the two levels as ioslides does by default with dots and dashes.