ids theme: align list markers flush with the slide title
Native ::marker glyphs are anchored by the browser with engine- and
font-dependent offsets, so the bullet column never lined up exactly with
the heading text. Draw the markers as CSS boxes in absolutely positioned
li::before rules instead: dot/square/ring per nesting level, vertically
centered on the first line, with the first-level marker's left edge
deterministically flush with the title in every browser and at every
window size. Nested offsets scale with the 0.8em per-level font-size
cascade. Ordered lists use the CSS list-item counter (honours start/
value), right-aligned into the indent; pandoc task lists keep their
checkboxes.
Change-Id: Ie514c11fd9cc4911c4a1811c4c316cb217547a4a
diff --git a/NEWS.md b/NEWS.md
index c7a875b..76f8bd5 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -4,6 +4,8 @@
- `ids` theme: second- and higher-level list items are now rendered progressively smaller (each nesting level at 80% of its parent), emphasising list hierarchy as in the IDS reference decks.
+- `ids` theme: list markers are now drawn as CSS boxes via `li::before` (dot/square/ring per level; ordered lists use the `list-item` counter honoring `start`/`value`), so the bullet column is deterministically flush with the slide title's left edge in every browser and at every window size, instead of relying on engine-dependent native `::marker` anchoring.
+
## REVEAL JS LIBRARY UPDATE
This version of the package comes with reveal.js v4 which is a major update from previous reveal.js v3. Built-in plugins (`zoom`, `search` and `notes`) have been updated, as well as third party plugin included in this package (`menu` and `chalkboard`). A lot of bugfixes and improvements have been made in the upstream library and now the R package can benefit from it. However, this cause also some breaking changes for **revealjs** R package that we described below.
diff --git a/inst/reveal.js-5.1.0/css/theme/source/ids.scss b/inst/reveal.js-5.1.0/css/theme/source/ids.scss
index b069d58..20e9416 100644
--- a/inst/reveal.js-5.1.0/css/theme/source/ids.scss
+++ b/inst/reveal.js-5.1.0/css/theme/source/ids.scss
@@ -113,14 +113,88 @@
}
// reveal.js centers lists by making them inline-block; make them ordinary
-// blocks so they line up with the headings, with the markers hanging in the
-// padding so the marker column itself aligns with the heading text.
+// blocks so they line up with the headings.
+//
+// The markers are NOT native ::marker glyphs: browsers anchor outside-position
+// markers at slightly different offsets per engine (and per scale), and even
+// ::before font glyphs carry font-specific side bearings, so a padding(text)-
+// based alignment of the bullet column with the heading text can never be
+// pixel-exact everywhere. Instead we DRAW the markers as CSS boxes in
+// absolutely positioned li::before rules. Geometry (all values in the item's
+// own font size, so the hierarchy scales with the 0.8em per-level sizing from
+// the NESTED LISTS section below):
+//
+// - item text starts at (list left edge) + 0.65em
+// - the marker box starts exactly at the list's left edge; on content
+// slides that edge coincides with the heading text's left edge, i.e. the
+// bullet column is flush with the slide title, deterministically in every
+// browser and at every window size
+//
+// For nested lists the ::before offset has to be divided by the 0.8 font-size
+// factor, because the list's padding is computed in the PARENT item's font
+// size while the ::before offset is computed in the (smaller) child size.
+$idsListIndent: 0.65em;
+$idsListShrink: 0.8;
+$idsMarkerSize: 0.22em;
+$idsMarkerTop: calc((1.3em - #{$idsMarkerSize}) / 2);
+
.reveal .slides section:not(.title-frame) ul,
.reveal .slides section:not(.title-frame) ol {
display: block !important;
text-align: left !important;
margin-left: 0 !important;
- padding-left: 0.7em !important;
+ padding-left: $idsListIndent !important;
+ list-style: none !important;
+}
+
+.reveal .slides section:not(.title-frame) li {
+ position: relative !important;
+}
+
+.reveal .slides section:not(.title-frame) li::before {
+ position: absolute !important;
+ left: calc(-1 * #{$idsListIndent}) !important;
+ color: var(--r-list-bullet-color) !important;
+}
+
+.reveal .slides section:not(.title-frame) li li::before {
+ left: calc(-1 * #{$idsListIndent} / #{$idsListShrink}) !important;
+}
+
+// Unordered-list markers: drawn boxes (round dot, square, ring for deeper
+// levels), vertically centered on the item's first line.
+.reveal .slides section:not(.title-frame) ul > li::before {
+ content: "" !important;
+ top: $idsMarkerTop !important;
+ width: $idsMarkerSize !important;
+ height: $idsMarkerSize !important;
+ box-sizing: border-box !important;
+ border-radius: 50% !important;
+ background: var(--r-list-bullet-color) !important;
+}
+
+.reveal .slides section:not(.title-frame) ul ul > li::before {
+ border-radius: 0 !important; // square
+}
+
+.reveal .slides section:not(.title-frame) ul ul ul > li::before {
+ background: transparent !important; // ring
+ border: 0.055em solid var(--r-list-bullet-color) !important;
+ border-radius: 50% !important;
+}
+
+// Ordered lists: the CSS list-item counter honours the HTML start/value
+// attributes, so pandoc's `start`/`value` lists keep their numbers. Numbers
+// are right-aligned into the indent, ending just before the item text.
+.reveal .slides section:not(.title-frame) ol > li::before {
+ content: counter(list-item, decimal) "." !important;
+ width: calc(#{$idsListIndent} - 0.12em) !important;
+ text-align: right !important;
+}
+
+// Checkbox (pandoc task) lists keep their checkboxes, no markers on top.
+.reveal .slides section:not(.title-frame) ul.task-list li::before {
+ content: none !important;
}
// reveal.js centres code blocks (width: 90%; margin: auto); make them fill the
diff --git a/inst/reveal.js-5.1.0/dist/theme/ids.css b/inst/reveal.js-5.1.0/dist/theme/ids.css
index 3a5dcb0..b8c44f3 100644
--- a/inst/reveal.js-5.1.0/dist/theme/ids.css
+++ b/inst/reveal.js-5.1.0/dist/theme/ids.css
@@ -371,12 +371,80 @@
text-align: left !important;
}
+/* The markers are NOT native ::marker glyphs: browsers anchor outside-position
+ markers at slightly different offsets per engine (and per scale), and even
+ ::before font glyphs carry font-specific side bearings, so a padding(text)-
+ based alignment of the bullet column with the heading text can never be
+ pixel-exact everywhere. Instead we DRAW the markers as CSS boxes in
+ absolutely positioned li::before rules. Geometry (all values in the item's
+ own font size, so the hierarchy scales with the 0.8em per-level sizing):
+
+ - item text starts at (list left edge) + 0.65em
+ - the marker box starts exactly at the list's left edge; on content
+ slides that edge coincides with the heading text's left edge, i.e. the
+ bullet column is flush with the slide title, deterministically in every
+ browser and at every window size
+
+ For nested lists the ::before offset is divided by the 0.8 font-size factor,
+ because the list's padding is computed in the PARENT item's font size while
+ the ::before offset is computed in the (smaller) child size. */
.reveal .slides section:not(.title-frame) ul,
.reveal .slides section:not(.title-frame) ol {
display: block !important;
text-align: left !important;
margin-left: 0 !important;
- padding-left: 0.7em !important;
+ padding-left: 0.65em !important;
+ list-style: none !important;
+}
+
+.reveal .slides section:not(.title-frame) li {
+ position: relative !important;
+}
+
+.reveal .slides section:not(.title-frame) li::before {
+ position: absolute !important;
+ left: -0.65em !important;
+ color: var(--r-list-bullet-color) !important;
+}
+
+.reveal .slides section:not(.title-frame) li li::before {
+ left: -0.8125em !important;
+}
+
+/* Unordered-list markers: drawn boxes (round dot, square, ring for deeper
+ levels), vertically centered on the item's first line. */
+.reveal .slides section:not(.title-frame) ul > li::before {
+ content: "" !important;
+ top: calc((1.3em - 0.22em) / 2) !important;
+ width: 0.22em !important;
+ height: 0.22em !important;
+ box-sizing: border-box !important;
+ border-radius: 50% !important;
+ background: var(--r-list-bullet-color) !important;
+}
+
+.reveal .slides section:not(.title-frame) ul ul > li::before {
+ border-radius: 0 !important; /* square */
+}
+
+.reveal .slides section:not(.title-frame) ul ul ul > li::before {
+ background: transparent !important; /* ring */
+ border: 0.055em solid var(--r-list-bullet-color) !important;
+ border-radius: 50% !important;
+}
+
+/* Ordered lists: the CSS list-item counter honours the HTML start/value
+ attributes, so pandoc's start/value lists keep their numbers. Numbers are
+ right-aligned into the indent, ending just before the item text. */
+.reveal .slides section:not(.title-frame) ol > li::before {
+ content: counter(list-item, decimal) "." !important;
+ width: 0.53em !important;
+ text-align: right !important;
+}
+
+/* Checkbox (pandoc task) lists keep their checkboxes, no bullets on top. */
+.reveal .slides section:not(.title-frame) ul.task-list li::before {
+ content: none !important;
}
.reveal .slides section:not(.title-frame) pre {