2

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

wes
  • 113
  • 6
  • 1
    Try li::marker {display: none}, this may remove the original bullet. Then, you can either customise ::marker or just use one of the default styles i.e. list-stye: circle – Akash Feb 24 '21 at 07:32
  • Do tell me if this worked, I'll add an answer. I have not added an asnwer not as I'm not sure it will work – Akash Feb 24 '21 at 07:35
  • Thank you, @Akash, for your help. Your suggestion to add `li::marker {display: none;}` is a good idea, but also did not remove the autogenerated bullets either. I've added code for the CSS & Rmd files to hopefully help – wes Feb 26 '21 at 07:25

3 Answers3

1

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;
}
  • Replacing content: '\00B7'; with list-style-type: circle; in ul > li:before { replaces the first-order bullets with circles.

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

  • Replacing content: '-'; with list-style-type: circle;inul li ul li:before {` replaces the second-order dashes with circles.

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.

wes
  • 113
  • 6
1

What seems to work, and may be a bit more simple than editing the actual slideshow.html is the following:

Firstly, include a style.css file in your .Rmd:

output:
  ioslides_presentation:
    css: styles.css

Secondly, create the styles.css file (same folder as your .Rmd) and add the following to it:

ul li ul li:before {
  content: "\25CB";
}

ul li:before {
  content: "\25CF";
}

This changes the bullet style type for first level (using the hex code 25CF for a filled circle) and the second level (25CB, empty circle).

user3283722
  • 123
  • 7
  • Addendum: I have zero experience with css and ioslides, so this solution is the result of looking at the previous answer by wes and some painful trial and error. Frankly, I have only a very vague idea why this does what it does. – user3283722 Feb 15 '22 at 13:36
1

I'm trying to avoid learning too much about css, but having tried it, I guess user3283722's answer (and maybe wes's too) is somewhat fragile. In particular I found that if I had an ordered list nested within an unordered list, the style.css inserted unwanted bullets (or circles) between the numbers and the item text. The hack below fixes that problem, but I suspect that other problems could still arise.

ul li:before {          /* Bullet for top level unordered list */
  content: "\25CF";
}

ul li ul li:before {    /* Bullet for 2nd level unordered list */
  content: "\25CB";
}

/*
I was getting bullets after the numbers an ordered list nested in an
unordered list. This seems to fix that problem.
*/

ul li ol li:before {
  content: "";
}
CS Fuu
  • 11
  • 2