Background SVG

IPySlides 7.0.1 Documentation

Creating slides with IPySlides

Abdul Saboor1

May 20, 2026

1My University is somewhere in the middle of nowhere

Right click (or click on footer) to open context menu for accessing settings, table of contents etc.

IPySlides Documentation

Table of contents

  1. Introduction
  2. Adding Slides and Content
  3. Layout and Theme Settings
  4. Useful Functions for Rich Content
  5. Loading from File/Exporting to HTML
  6. Advanced Functionality
  7. Presentation Code

This is summary of current section

Oh we can use inline columns

Column A

Column B

here and what not!

This is pinned content!

Markdown
section`Introduction` 
```columns .block-green
toc[True]`## Table of contents`
+++
### This is summary of current section
Oh we can use inline columns stack`Column A || Column B` here and what not!
%{btn}
pin[60,50, rotate=15]`::: anim-slide-left block-red | This is pinned content!`
```
        
IPySlides Documentation │ Introduction
●●●●●
1

Main App

Slides(extensions=[], **settings)

Interactive Slides in IPython Notebook. Only one instance can exist. settings are passed to Slides.settings() if you like to set during initialization. You can also edit file .ipyslides-assets/settings.json to make settings persistent across sessions and load/sync them via GUI in sidepanel.

To suppress unwanted print from other libraries/functions, use:

Python
with slides.suppress_stdout():
    some_function_that_prints() # This will not be printed
    print('This will not be printed either')
    display('Something') # This will be printed
        

The traitlets callables under settings returns settings back to enable chaining without extra typing, like Slides.settings.logo().layout()... .

  • Use Slides.instance() class method to keep older settings. Slides() apply default settings every time.
  • Run slides.demo() to see a demo of some features.
  • Run slides.docs() to see documentation.
  • Instructions in left settings panel are always on your fingertips.
  • Creating slides in a batch using Slides.create is much faster than adding them one by one.
  • In JupyterLab, right click on the cell containing slides (outside slides) and select Create New View for Output for optimized display.
  • To jump to source cell and back to slides by clicking buttons, set Windowing mode in Notebook settings to defer or none.
  • See Slides.xmd.syntax for extended markdown syntax, especially variables formatting.
  • Inside python scripts or for encapsulation, use Slides.fmt to pick variables from local scope.
  • Slides can be indexed same way as list for sorted final indices.
  • For indexing slides with given number, use comma as Slides[number,] → Slide
  • Access many via list as Slides[[n1,n2,..]] → SlideGroup or slice as Slides[start:stop:step] → SlideGroup.
  • SlideGroup can be used to apply batch operations on many slides at once, e.g. Slides[[1,3,5]].vars.update(name='Alice').
  • Use indexing with given number to apply persistent effects such as CSS or acess via attributes such as Slides.s0, Slides.s1 etc. for existing slides, so Slides.s10 == Slides[10,] if slide with number 10 exists.
  • Use section[True]`Backup slides` to mark start of supplemental slides. Progress completes before this section and supplemental frames/slides are numbered as S.1, S.2, ... while remaining navigable.
IPySlides Documentation │ Adding Slides and Content
●●●●●
2

Jump between slides

Slides.link(label, back_label=None, icon=None, back_icon=None)

Create a link to jump to another slide. Use label for link text and back_label for the optional text on the target slide if need to jump back.

  • Use link.origin to create a link to jump to target slide where link.target is placed.
  • If back_label was provided, link.target will be able to jump back to the link.origin.
  • In makdown, you can use created link as variables like %{link.origin} and %{link.target} to display links.
  • Use similar links in markdown as <link:[unique id here]:origin label> and <link:[unique id here same as origin]:target [back_label,optional]>.
  • In markdown, icons can be passed in label as "fa`arrow` label text".
Skip to dynamic content
Python
skipper.origin.display() # skipper.target is set later somewhere, can do backward jump too
        
IPySlides Documentation │ Adding Slides and Content
●●●●●
2

Adding Slides

Besides function below, you can add slides with %%slide number [-m] magic as well.

Slides.build(slide_number, content=None, /, **vars)

Build slides with a single unified command in three ways:

  1. slides.build(number, callable) to create a slide from a callable(slide) immediately, e.g. lambda s: slides.write(1,2,3) or as a decorator.
    • Lazy Execution: The slide is created immediately, but the function is executed only when first accessed during navigation. This defers heavy computations until the user reaches that slide. Future navigation does not trigger re-computation.
    • Docstring of callable (if any) is parsed as markdown before calling function.
    • Function must accept a single argument: the slide handle.
  2. with slides.build(number): creates single slide. Equivalent to %%slide number magic.
    • Contents displayed by write function can be split into incremental parts if write is called after pause() adjacently.
  3. slides.build(number, str, **vars) creates many slides with markdown content. Equivalent to %%slide number -m magic in case of one slide.
    • Multiple slides can be built using triple dashes --- as separators. Same applies to Slides.sync_with_file too.
    • Use ++ to separted content into parts for incremental display on ites own line with optionally adding content after one space.
    • Markdown columns/group blocks can be displayed incrementally if ++ is used (alone on line) before these blocks as a trigger.
    • See slides.xmd.syntax for extended markdown usage.
    • To debug markdown content, use EOF on its own line to keep editing and clearing errors. Same applies to Slides.sync_with_file too.
    • Variables such as %{var} can be provided in **vars (or left during build) and later updated in notebook using rebuild method on slide handle or overall slides.
    • If an f-string is provided, variables in f-string are resolved eagerly and never get updated on rebuild including lazy ones provided by Slides.esc.
  • In all cases, number could be used as -1.
  • Use yoffetinteger in percent in markdown or Slides.yoffset(integer) to make all frames align vertically to avoid jumps in increments.
  • You can use build_(...) (with underscore at end) in python file instead of build(-1,...).
  • **vars are ignored silently if build is used as contextmanager or decorator.
Slides.sync_with_file(start_slide_number, /, path, interval=500)

Auto update slides when content of markdown file changes. You can stop syncing using Slides.unsync function. interval is in milliseconds, 500 ms default. Read Slides.build docs about content of file.

The variables inserted in file content are used from top scope.

You can add files inside linked file using include\`file_path.md\` syntax, which are also watched for changes. This helps modularity of content, and even you can link a citation file in markdown format as shown below. Read more in Slides.xmd.syntax about it.

Markdown
```citations
@key1: Saboor et. al., 2025
@key2: A citations can span multiple lines, but key should start on new line
<!--_xmd_cmt_0_-->
```
        

To debug the linked file or included file, use EOF on its own line to keep editing and clearing errors.

IPySlides Documentation │ Adding Slides and Content
●●●●●
2

Important Methods on Slide

  • Use slide handle or Slides[number,] to apply these methods becuase index can change on new builds.
  • Use Slides[start:stop:step] to apply operations on many slides at once such as Slides[2:5].vars.update(...).
Slide.Vars

Container for markdown slide variables, to see and update variables set on a slide or a group of slides.

  • slides.s1.vars.update(name="New") updates variable 'name' on slide 1 only
  • slides.s2.vars.pop('age') removes variable 'age' from slide 2 only, so it is picked from notebook scope
  • slides.s3.vars.clear() clears all variables set on slide 3 only, so they are picked from notebook scope
  • slides[:].vars.update(theme='dark') updates variable 'theme' on all slides
  • slides[1:3].vars.pop('title') removes variable 'title' from slide 1 and 2 only
  • slides[0].vars.scope see variables with scope set on slide 0

If variables are not set on slide, they are picked from notebook scope if Auto Rebuild is enabled in side panel.

Slide.update_display()

Update display of this slides including reloading citations, widgets etc.

Slide.get_source(name=None, height='400px', **kwargs)

Return source code of this slide, markdwon or python or None if no source exists. kwargs are passed to Slides.code.from_string.

Slide.show()

Show this slide in cell.

IPySlides Documentation │ Adding Slides and Content
●●●●●
2

Extended Markdown

Extended syntax on top of Python-Markdown supports almost full presentation from Markdown.

Presentation Structure

Slides and Parts Separators
Triple dashes --- separator is used to split text in slides inside markdown content of Slides.build function or markdown file. --- should be on their own lines in main content (not inside block syntax) to be recognized as slide separators. Double plus ++ (pause in Python) can be used to increment objects in parts on a slide. A ++ on its own line before columns block will make it reveal content incrementally, provided that columns are separated by +++ or single column only with ++ inside. Use ++[isolate] before a ::: columns/::: group blocks to isolate previous content from column reveal. Note that only ++ allows content on same line after it and following lines.
Sections & TOC
section`content` to add a section that will appear in the table of contents. Use section[True]`content` to mark the beginning of supplemental slides with True parameter in section command. Slides in this section remain navigable, use supplemental numbering (S.1, S.2, ...), and do not advance the main progress bar. toc`Table of content header text` to add a table of contents. See Slides.docs() for creating a TOC accompanied by section summary.
Notes
notes`This is slide notes` to add notes to current slide.
Backgrounds
bg`image_src_or_path` to set background for the current slide. If multiple bg calls are used in one slide, the last one wins. Use bg[opacity=0.4, contain=True, filter='blur(2px)']`image_src_or_path` for options. contain must be True or False.
Including Files
include`markdown_file.md[optional list slicing to pick lines from file such as [2:5], [10:]]` to include a file in markdown format. These files are watched for edits if included in synced markdown file via Slides.sync_with_file.
Citations
  • cite`key1,key2` / @key1,@key2 to add citation to current slide. citations are automatically added in suitable place and should be set once using Slides.set_citations function (or see below).
  • You can add refs`ncol_refs` or Slides.refs to add citations anywhere on slide. If `ncol_refs` is not given, it will be picked from layout settings. Using refs`ncol_refs, key1, key2,...` will show only citations for given keys on that place. It is useful on slides with frames to show relevant citations on each frame. Unused citations will be added automatically at end of slide.
  • Force citations to be shown inline by appending a !, such as @key! or cite`key1,key2!`.
  • In the synced markdown file (also its included files) through Slides.sync_with_file, you can add citations with block sytnax:
    ::: citations
    @key1: Saboor et. al., 2025
    @key2: A citations can span multiple lines, but key should start on new line
IPySlides Documentation │ Adding Slides and Content
●●●●●
3

Extended Markdown

Content Blocks

The general block syntax is ::: type-or-classes [args] attributes.

  • You can use / to divide css properties from node attributes such as ::: note-info border="1px solid red" / id="mynote" dir="ltr". Node attributes come after /. 'data-' prefixed attributes can appear anywhere.
  • You can create inline blocks by adding | in header (only takes effect if body is empty), such as ::: block-red | text will create a block with red background and text inside.
  • Both | and / can be escaped in header by backslah to interpret them as literal characters instead of block body and attributes splitters respectively.
  • You can optionally continue block header on next multiple adjacent lines with : at start of each line. This multiline header is not available in ``` blocks.
  • Theme colors such as fg1=red bg2=black upto 3, can be assigned for each block to tweak look and feel of content.
  • Blocks can be escaped by having a space before ::: at start of line, such as ::: block-red will not be parsed as block.
  • Some block levels HTML tags are handled specially, such as p, pre, ul, ol, blockquote, details, summary, table.
  • You can use ::: block nested inside ``` block at same indentation level but otherwise must be correctly indented.
  • Bullet points are hard to stylize, so use ::: ul/ol blocks to create lists with custom styles and in side have ::: li blocks for each item. e.g. a per item marker can be added using ::: li list-style="'👉'" | item text besides all other CSS styles, or a data-marker attribute directly.
This table, itself created with a ::: table block, lists common block types and their usage. Each of these blocks can have additional CSS classes and properties, besides the limited set shown below.
Block Syntax Description
::: raw/pre Raw text or preformatted text, no markdown parsing. Use raw or pre as first word in block.
::: code [focused lines] Code block with syntax highlighting, parameters are passed to highlight function.
::: tag or classes tags are block level elements such as p, details, summary, table, center, etc.
::: columns [widths] / ::: group Create columns with relative widths, e.g. columns 4 6 for 40% and 60% width. group is a single-column display block (no widths or +++ needed). Use ::: group snapshots=True (optionally with header='Header text') to reveal rows exclusively for that block. Use ++[isolate] before the block to isolate previous content from this reveal sequence.
::: md-[before,after,var_name] [focused lines] Parse markdown in the block, with showing source code at before or after or assign a variable name and use as <md-var_name/>.
::: table [col widths] Create a table with optional column widths, e.g. ::: table 1 2 for 33% and 66% width. Use caption-side=top/bottom to place caption on top/bottom.
::: citations Add citations in the block (only in sync_with_file context) instead of Slides.set_citations. Use @key: value syntax on its own line to add citations in block.
::: display css_classes Create a block with specific CSS classes forcing display mode, it can break dom flow, but usefull to embed widget variables under blocks.
Important Notes on md- and code blocks
  • Variable created with md-var_name can be used anywhere in markdown using <md-var_name/> to display source code.
  • md-[position or variable] accepts same parameters as code block for syntax highlighting and get deleted on first use.
  • Both code and md-var blocks support attribute access such as ::: code.collapsed or ::: md-var.inline to show selected view. You can also use ::: code 1 3 to focus on specific lines based on index 1 in markdown unlike Python.
IPySlides Documentation │ Adding Slides and Content
●●●●●
3

Extended Markdown

Layouts

Inline Columns
Inline columns/rows can be added by using stack`Column A || Column B` sytnax. You can escape pipe | with | to use it as text inside stack. See at end how to nest such stacking.
Block Columns
You can create columns using ::: columns syntax, or use ::: group for a single-column display block. Column separator is triple plus +++ for ::: columns when intended in display mode; ::: group does not need +++ or widths. Use ::: group snapshots=True to enable per-row iteration for that block. Use header='Header text' in the same group header to keep a static header visible while rows reveal. Use ++[isolate] before ::: columns to separate previous content from first column reveal.
Markdown
::: columns 6 1 4 block-blue 
: border="1px dashed red"
    ::: block-red
        - `::: columns/muticol` with a +++ separator act like `write` command and reveal content incrementally when `++` is used before block.
        - children inside `columns` picks relative width from parent's `columns` block evem if '+++' is not used.
          In thise children should be visually blocks themselves like headings, paragraphs, lists etc or wrapped in `::: block` to make them obvious blocks like this one.
        - CSS classes and attributes can be used to style columns besides relative widths.

    ::: block-blue border="1px solid red" | alert`inline` color`block` text 

    ::: ul block-yellow border="2px solid orange" list-style=disc
        ::: li list-style="'👉'" 
            Top level `columns` is necessary to create columns or use simple block with `display=flex`.
            and frame speactor is used at end of block.
        <li data-marker=ℹ️> Indentation is important, so use tabs or spaces consistently.</li>
        ::: li | This follows disc marker from parent `ul` block.
        
  • ::: columns/muticol with a +++ separator act like write command and reveal content incrementally when ++ is used before block.
  • children inside columns picks relative width from parent's columns block evem if '+++' is not used. In thise children should be visually blocks themselves like headings, paragraphs, lists etc or wrapped in ::: block to make them obvious blocks like this one.
  • CSS classes and attributes can be used to style columns besides relative widths.

inline block text

  • Top level columns is necessary to create columns or use simple block with display=flex. and frame speactor is used at end of block.
  • Indentation is important, so use tabs or spaces consistently.
  • This follows disc marker from parent ul block.
IPySlides Documentation │ Adding Slides and Content
●●●●●
3

Extended Markdown

Code Display

Inline Code
Inline code can be highlighted using code`code` syntax, e.g. code`print('Hello')` → print('Hello').
Code Blocks
Use standard markdown fenced code blocks or ::: code blocks for syntax highlighting.

Markdown
::: columns
    ::: block-green
        <md-src/>
    +++
    ::: block-red
        ```python
        print('Hello, I was highlighted from a code block!')
        ```
        ::: code 2 language=bash name=Shell lineno=False style=vim
            echo "Hello, I was highlighted from a code block!"
            ls -l | grep ".py" | wc -l
        

Python
print('Hello, I was highlighted from a code block!')
        
Shell
echo "Hello, I was highlighted from a code block!"
ls -l | grep ".py" | wc -l
        
Click to see important notes on code blocks
  • In ::: code block, you need to set parameters that are passed to code function, such as language, name, lineno, css_class, etc.
  • The ``` code block does act like ::: code block and supports same parameters.
  • You can focus on specific lines in code blocks using line numbers (1-based) such as ::: code 2 4 5 to focus on lines 2, 4 and 5 visually.
  • You can also use ::: code.collapsed or ::: code.inline to show collapsed or inline view of code block respectively.
    Show Code
    Markdown
    ::: details
        ::: summary | Click to see important notes on code blocks 
        - In ` ::: code ` block, you need to set parameters that are passed to `code` function, such as `language`, `name`, `lineno`, `css_class`, etc.
        - The \`\`\` code block does act like `::: code ` block and supports same parameters.
        - You can focus on specific lines in code blocks using line numbers (1-based) such as `::: code 2 4 5` to focus on lines 2, 4 and 5 visually. 
        - You can also use `::: code.collapsed` or `::: code.inline` to show collapsed or inline view of code block respectively.
        <md-src/>
            
IPySlides Documentation │ Adding Slides and Content
●●●●●
3

Extended Markdown

Variables Substitution

Variables from Python code can be embedded directly into Markdown.

Basic Usage
  • Syntax: Use %{variable} to display a variable which is lazily resolved and safely escaped from markdown parsing.
  • Formatting: Apply formatting using %{variable:format_spec} or conversions with %{variable!conversion}. This works like Python's str.format method.
  • Notebook Display: To render an object as it would appear in a notebook output cell, use %{variable:nb}. This is useful for complex objects like plots.
  • For custom objects, it's better to use Slides.serializer to define their HTML representation, which allows them to be displayed correctly in place with such as %{fig}. Using %{fig:nb} might show the object at the end of the slide.
Variable Scope & Updates
  • Live Updates: Variables are automatically updated in your slides when their values change in the notebook if not held inside Slide[number,].vars deepest scope.
  • Scope Resolution: Variables are resolved from per-slide variables (set by build or Slide.vars.update), then from the notebook's global scope if a slide is built purely from markdown. In functions which take markdown string such as write, html, variables are taken from notebook's global scope only. Use fmt to encapsulate variables from local scopes.
  • Forcing Updates: You can force a refresh of variables on a specific slide using Slide[number,].vars.update(**kwargs). This is also useful for setting unique variable values on different slides.
  • Attribute/Index Access: When using expressions like %{var.attr} or %{var['key']}, the output will only update if the base variable var itself is reassigned.
Important Notes
  • Use unique variable names for each slide to prevent unintended updates.
  • Widgets and objects using :nb are only displayed correctly in the first level of nested blocks.
  • The %{variable:nb} formatter can sometimes disrupt the document flow if used inside elements like headings. It's safest to use it on its own line or within a paragraph.
  • Widgets behave same with or without :nb format spec.
  • Formatting is done using str.format method, so f-string like literal expressions are not supported.
IPySlides Documentation │ Adding Slides and Content
●●●●●
3

Extended Markdown

Inline Python Functions

Functions (that can also take extra args [python code as strings] as func[arg1,x=2,y=A]`arg0`) include:

  • vspace`number in units of em`
  • hspace`number in units of em`
  • line`length in units of em, [color, width and style]`
  • today`format_spec like %b-%d-%Y`
  • fa`fontawesome icon name, [css_props]`
  • alert`text`
  • color`text`
  • code`inline code highlighter or use ::: code block`
  • textbox`text`
  • image`path/src or clip:filename`
  • bg`path/src or none, [opacity, filter, contain] (last one wins per slide)`
  • raw`text, or use ::: raw block`
  • svg`path/src`
  • iframe`src`
  • details`text or use ::: details block`
  • styled`style objects with CSS classes and inline styles or use block ::: with css classes and props inline`
  • focus`focus on a node of html when clicked or used ::: focus-self/focus-child blocks`
  • center`text or %{variable} or use ::: center, ::: align-center blocks`
  • stack`text separated by || in inline mode, or use ::: columns/::: group block`
  • yoffset`integer in percent, use ['all'] as econd parameter to apply to all slides or list of numbers for specific slides.`
  • transition`slides transition such as zoom, fade etc. Use ['all'] as econd parameter to apply to all slides or list of numbers for specific slides.`
  • css`css properties for current slide, use ['all'] as econd parameter to apply to all slides or list of numbers for specific slides.`
  • pin`pin a markdown text or image file at specific position x,y and width,height. Additional paramters are center,zorder,rotate,blur and other css properties. See Slides.pin for details.`

You can also use Slides.esc/isd.esc class to lazily escape variables/expressions/output of functions from being parsed inside f-strings. This should be rarely used when your markdown contains a lot of $ \LaTeX $ equations to avoid excessively escaping them with curly braces in favor of few escaped variables.

Upto 4 level nesting is parsed in inline functions using (level + 1) number of / (at least two) within backticks in functions given below.

Markdown
::: columns
    <md-src_var/>

    stack[(6,4),css_class="block-blue"]`////
        This always parse markdown in `returns=True` mode. ||
        stack[css_class="info"]`/// B ||
            color["skyblue"]`//alert`Alerted Text` Colored Text //`
        ///` 
    ////`
        

This always parse markdown in returns=True mode.

B

Alerted Text Colored Text

IPySlides Documentation │ Adding Slides and Content
●●●●●
3

Extended Markdown

General Syntax

  • Use include`markdown_file.md[optional list slicing to pick lines from file such as [2:5], [10:]]` to include a file in markdown format.
  • Use fa`icon_name` to add FontAwesome icons, e.g. fa`arrow-right` → , fa["green"]`check` → , fa["blue"]`info-circle` → etc.
  • Use syntax `` and `` to jump between slides. See Slides.link for more details.
  • Cells in markdown table can be spanned to multiple rows/columns by attributes | cell text \{: rowspan="2" colspan="1"}| inside a cell, should be a space bewteen text and attributes.
  • Escape a backtick with backslash, i.e. \` → `, other escape characters include @, %, /, |. In Python >=3.12, you need to make escape strings raw, including the use of $ \LaTeX $ and re module.
  • Use _`sub` and ^`sup` for subscript and superscript respectively, e.g. H2O, E = mc2.
  • See Slides.css_styles for available CSS classes to use in markdown blocks and other places.
  • See Slides.css_animations for available CSS animation classes to use in markdown blocks and other places.
  • Definition list syntax:

::: columns
<md-src/>
+++
Item 1 Header
: Item 1 details ^`1`
Item 1 Header
: Item 1 details _`2`

Item 1 Header
Item 1 details1
Item 1 Header
Item 1 details2

Extending Syntax

  • You can use Slides.xmd.extensions to extend additional syntax using Markdown extensions such as markdown extensions and PyMdown-Extensions.
  • These markdown extensions are inluded by default ['tables', 'footnotes', 'attr_list', 'md_in_html', 'def_list'].
  • You can serialize custom python objects to HTML using Slides.serializer function. Having a __format__ method in your class enables to use {obj} syntax in python formatting and %{obj} in extended Markdown.
IPySlides Documentation │ Adding Slides and Content
●●●●●
3

Adding Content

Besides functions below, you can add content to slides with %%xmd,%xmd as well.

Slides.write(*objs, widths=None, css_class=None, **css_props)

Write objs to slides in columns. To create rows in a column, wrap objects in a list or tuple.
You can optionally specify widths as a list of percentages for each column. css_class can have multiple classes separated by space, use this to do animations with classes. See Slides.css_animations for details. **css_props are additional CSS properties applied to the writer block node, CSS variables names like --origin should be passed as __origin.

Write any object that can be displayed in a cell with some additional features:

  • Strings will be parsed as as extended markdown that can have citations/python code blocks/Javascript etc.
  • Use group([...], snapshots=True) to reveal items one-by-one during frame navigation. You can set a static header with group([...], header='Header'); it remains visible while group rows change. You can also build it with g = group([], snapshots=True); with g.capture(): ... and pass g as a column.
  • Display another function to capture its output in order using Slides.hold(func,...). Only body of the function will be displayed/printed. Return value will be ignored.
  • Dispaly IPython widgets such as ipywidgets or ipyvolume by passing them directly.
  • Display Axes/Figure form libraries such as matplotlib, plotly altair, bokeh etc. by passing them directly.
  • Display source code of functions/classes/modules or other languages by passing them directly or using Slides.code API.
  • Use Slides.alt function to display obj/widget on slides and alternative content/screenshot of widgets in exported slides.
  • ipywidgets.[HTML, Output, Box] and their subclasses will be displayed as Slides.alt(html_converter_func, widget). The value of exported HTML will be most recent.
  • Other options include but not limited to:
    • Output of functions in ipyslides.utils module that are also linked to Slides object.
    • PIL images, SVGs etc.
    • IPython display objects such as Image, SVG, HTML, Audio, Video, YouTubeVideo, IFrame, Latex, Markdown, JSON, Javascript, etc.
    • Any object that has a _repr_html_ method, you can create one for your own objects/third party objects by:
      • Slides.serializer API. IPython's display automatically takes care of such objects on export to html.
      • IPython.core.formatters API for third party libraries.
    • A whole column in write can be multiple captured outputs from a capture_content context manager, which can be used as alternative to Slides.hold.
  • Use Slides.frozen to avoid display formatting and markdown parsing over objects in write and for some kind of objects in display too.
  • write is a robust command that can handle most of the cases. If nothing works, repr(obj) will be displayed.
  • You can avoid repr(obj) by Slides.hold(func, ...) e.g. Slides.hold(plt.show). This can also be used to delay display until it is captured in a column.
  • You can use display(obj, metadata = {'text/html': 'html repr by user'}) for any object to display object as it is and export its HTML representation in metadata.
  • You can add mini columns inside a column by markdown syntax or Slides.stack, but content type is limited in that case.
  • In markdown columns/group block syntax is similar to write command if +++ separartor is used there.
  • Use ::: group snapshots=True (and optional header=...) in markdown to enable snapshots behavior for that group block.

To make a group of rows as single item visually for incremental display purpose, wrap them in a nested list/tuple. A single column is flattened up to 2 levels, so [[obj1], row2, [item1, item2]] will be displayed as 3 rows.

Use group([...], snapshots=True) to reveal rows in isolation for a specific column.

Incremental display is triggered only when you place Slides.pause() delimiter before the write command:

Python
slides.pause()  # Trigger incremental display, equivalent to ++ before `columns` in markdown
slides.write([row1, [item1, item2], row3], column2)  # Shows rows one by one (item1 and item2 together), then column2
slides.pause()  # Another trigger for next write
slides.write([row1, row2]) # Shows both rows incrementally , no additional columns here
slides.write(1,2,3,4, css_class='anim-group anim-slide-up', __distance='400px',display='grid',grid_template_columns='1fr 1fr') # animated group of columns
        
Slides.xmd(content: Union[str, ipyslides.xmd.fmt], returns: bool = False) -> Optional[str]

Extended markdown parser for ipyslides. You can use %%xmd and %xmd cell and line magics in Jupyter Notebook as well.

Besides the base Python-Markdown syntax, it supports additional syntax which you can read about by executing following code a notebook cell:

Python
import ipyslides as isd
display(isd.xmd.syntax)
        

By default, the extensions tables, footnotes, attr_list, md_in_html, def_list are enabled.

You can add extra markdown extensions using Slides.xmd.extensions or ipyslides.xmd.extensions. See markdown extensions for details.

Returns: A direct call or xmd.parse method returns a string with HTML content if returns=True (default), otherwise display rich output objects.

Slides.as_html(obj)

Convert supported (almost any) obj to html format.

Slides.as_html_widget(obj='')

Convert supported (almost any) obj to html format and return widget.

Slides.html(tag, children=None, css_class=None, **node_attrs)

Returns html node with given children and node attributes like style, id etc. If an ttribute needs '-' in its name, replace it with '_'.
tag can be any valid html tag name. A tag that ends with / will be self closing e.g. hr/ will be <hr/>. Empty tag gives unwrapped children. children expects:

  • If None, returns node such as html('image',alt='Image') → <img alt='Image'></img> and html('image/',alt='Image') → <img alt='Image' />
  • str: A string to be added as node's text content.
  • list/tuple of [objects]: A list of objects that will be parsed and added as child nodes. Widgets are not supported.
  • dict if tag is 'style', this will only be exported to HTML if called under slide builder, use slides[number,].set_css otherwise. See Slides.css_syntax to learn about requirements of styles in dict.

Example:

Python
html('img',src='ir_uv.jpg') #Returns IPython.display.HTML("<img src='ir_uv.jpg'></img>") and displas image if last line in notebook's cell.
        

To keep an image persistently embeded, use ipyslides.utils.imge function instead of just an html tag.

IPySlides Documentation │ Adding Slides and Content
●●●●●
4

Dual Usage Functions

Some functions such as Slides.css, Slides.yoffset, and Slides.transition can be used both inside and outside slide context through their applyto parameter. If applyto is None (or omitted), they require an active slide context and apply to the current slide. If applyto is provided (for example, a slide index, list of indices, or 'all'), they can be used outside a slide context and apply to the selected slides. They can also used from markdown with syntax like function[applyto]`content`.

Slides.transition(name: str, applyto=None)

Set transition animation for the current slide or slides selected by applyto. Under a slide builder (including markdown), if applyto is None, it applies to current slide, if 'all', it applies to all slides, otherwise it should be index or list of indices of slides to apply animation to.

Slides.yoffset(value: int, applyto=None)

Set vertical offset for the current slide or slides selected by applyto. Value should be an integer between 0 and 100, representing percentage of slide height.

Under a slide builder (including markdown), if applyto is None, it applies to current slide, if 'all', it applies to all slides, otherwise it should be index or list of indices of slides.

Slides.css(props: dict = None, applyto=None, **css_vars)

Set CSS on current slide being built or slides selected by applyto. Reset by empty props and variables on slides slected by applyto.

Under a slide builder (including markdown), if applyto is None, it applies to current slide, if 'all', it applies to all slides, otherwise it should be index or list of indices of slides.

  • See Slides.css_syntax for information on how to write CSS dictionary.
  • Underscores in CSS property and variable names are replaced with dashes, so font_size becomes font-size and my_var becomes --my-var.
  • You can define global/slide level CSS animation variables like --time, --delay etc. See Slides.css_animations for details of various animations usage.
  • You can define custom @keyframes in CSS and use them with anim-kf class by setting --kf-name and optional --kf-* controls.
  • An empty selector '' is allowed to directly inject CSS string, useful to read a local CSS file while files from web must be downloaded first. Advanced CSS concepts like @import, @layer may not work as expected due to CSS scoping inside slides. Large files should be added to overall CSS only for performance reasons.
  • You can set theme colors per slide. Accepted color keys are fg1, fg2, fg3, bg1, bg2, bg3, accent and pointer. These apply to current selected theme.
  • Avoid gradient colors for other than bg1, as it will be ignored in most places and may lead to bad styling.

CSS is formatted using a props nested dictionary to simplify the process.

There are few special rules in props:

  • All nested selectors are joined with space, so '.A': {'.B': ... } becomes .A .B {...} in CSS.
  • A '^' in start of a selector joins to parent selector without space, so '.A': {'^:hover': ...} becomes .A:hover {...} in CSS. You can also use '.A:hover' directly but it will restrict other nested keys to hover only.
  • A list/tuple of values for a key in dict generates CSS fallback, so '.A': {'font-size': ('20px','2em')} becomes .A {font-size: 20px; font-size: 2em;} in CSS.
  • An empty key with a string/path value injects raw CSS wrapped in nested &, so '.A': {'': 'raw css here'} becomes & { .A { raw css here } } in CSS. This, however, can NOT be used to inject complex CSS like @import, @layer etc. :root is replaced with & to make variables local to the selector at given nesting level.

Read about specificity of CSS selectors here.

Python
props = {
  ".A": {
    "z-index": "2",
    ".B": {
      "font-size": [
        "24px",
        "2em"
      ],
      "^:hover": {
        "opacity": "1"
      }
    },
    "> h1": {
      "padding": "0",
      "@media screen and (min-width: 650px)": {
        "padding": "2em"
      }
    },
    ".C p": {
      "font-size": "14px"
    }
  },
  ".D": {
    "transform": "translate(-2px,1px)",
    "^, h1": {
      "background": "red",
      "span, i": {
        "color": "whitemoke",
        "@keyframes animation-name": {
          "from": {
            "opacity": 0
          },
          "to": {
            "opacity": 1
          }
        }
      }
    }
  }
}
        

Output of Slides.html('style',props), Slides.css(props) etc. functions. Top selector would be different based on where it is called.

CSS
<style>
.SlideArea .A {
    z-index : 2;
}
.SlideArea .A .B {
    font-size : 24px;
    font-size : 2em;
}
.SlideArea .A .B:hover {
    opacity : 1;
}
.SlideArea .A > h1 {
    padding : 0;
}
@media screen and (min-width: 650px) {
    .SlideArea .A > h1 {
        padding : 2em;
    }
}
.SlideArea .A .C p {
    font-size : 14px;
}
.SlideArea .D {
    transform : translate(-2px,1px);
}
.SlideArea .D,
.SlideArea .D  h1 {
    background : red;
}
.SlideArea .D span,
.SlideArea .D  i,
.SlideArea .D h1 span,
.SlideArea .D h1  i {
    color : whitemoke;
}
@keyframes animation-name {
    from {
        opacity : 0;
    }
    to {
        opacity : 1;
    }
}
</style>
        
IPySlides Documentation │ Adding Slides and Content
●●●●●
4

Adding Speaker Notes

You can use alert

notes`notes content`in markdown.'

This is experimental feature, and may not work as expected.

Slides.notes.display()
Slides.notes.insert(content)

Add notes to current slide. Content could be any object except javascript and interactive widgets. Note that notes are not shown inside slides during presentation. They can be viewed in popup window by enabling Notes Popup option in settings panel. Notes can also be printed in PDF (after export too) by enabling Inline Notes option in settings panel, useful for sharing slides with notes or for personal reference.

  • In markdown, you can use notes`notes content`.
  • Place your (extended) projector on top/bottom of laptop screen while presenting in Jupyter Notebook to allow right/left edges click navigation work smoothly.
IPySlides Documentation │ Adding Slides and Content
●●●●●
4

Displaying Source Code

In markdown, the block md-[before,after,var_name] parses and displays source as well.

Slides.code(obj, language='python', name=None, css_class=None, style='default', color=None, background=None, hover_color='var(--bg3-color)', lineno=True, height='400px')

Create highlighted source code object from text, file or callable.

Use code(obj) or code.cast(obj) to get source code from any object that has a source or str of code.

Explicitly use:

  • code.from_file(filename) to get a source object from a file or file-like object.
  • code.from_string(string) to get a source object from a string.
  • code.from_source(obj) to get a source object from a python object (class, function, module, method etc.).

Returns: SourceCode object with show and focus methods to show selective lines, as well as .inline and .collapsed properties.

Slides.code.context(returns=False, **kwargs)

Execute and displays source code in the context manager. kwargs are passed to Slides.code function. Useful when source is written inside context manager itself. If returns is False (by default), then source is displayed before the output of code. Otherwise you can assign the source to a variable and display it later anywhere.

Usage:

Python
with source.context(returns = True) as s: 
    do_something()
    write(s) # or s.display(), write(s)

#s.raw, s.value are accesible attributes.
#s.focus, s.show are methods that are used to focus/show selective lines.
        
Slides.code.from_file(file, language=None, name=None, **kwargs)

Returns source object with show and focus methods. name is alternate used name for language.
kwargs are passed to Slides.code.

It tries to auto detect lanaguage from filename extension, if language is not given.

Slides.code.from_source(obj, **kwargs)

Returns source code from a given obj [class,function,module,method etc.] with show and focus methods. kwargs are passed to Slides.code

Slides.code.from_string(text, language='python', name=None, **kwargs)

Creates source object from string. name is alternate used name for language. kwargs are passed to Slides.code.

IPySlides Documentation │ Adding Slides and Content
●●●●●
4

Contents

  1. Introduction
  2. Adding Slides and Content
  3. Layout and Theme Settings
  4. Useful Functions for Rich Content
  5. Loading from File/Exporting to HTML
  6. Advanced Functionality
  7. Presentation Code
IPySlides Documentation │ Layout and Theme Settings
●●●●●
5

Layout and Theme Settings

Slides.Settings

Apply settings to slides programatically. Fewer settings are available as widgets.

Settings can be nested or individual attributes as set as well. For example:

Python
Slides.settings(layout = {"aspect": 16/10}) # Top 
Slides.settings.layout(aspect = 16/10) # Individual
Slides.settings.layout.aspect = 16/10  # Attribute
        

All settings calls including top level returns settings instance to apply method chaining. e.g. Slides.settings.layout(aspect = 16/10).footer(text="ABC").logo(...).

Slides.Settings.Code

Set code block styles. background and color may be needed for some styles.

Slides.Settings.dump(path)

Dump the settings state to a json file. Use it once you have finalized a settings setup of slides.

Slides.Settings.Fonts

Set fonts of text and code and size.

Slides.Settings.Footer

Set footer attributes of slides.

Slides.Settings.Layout

Set overall layout of slides.

Slides.Settings.load(path)

Load settings from a json file. You may need to dump settings and then edit for correct usage.

Slides.Settings.Logo

Set logo for all slides. left and bottom take precedence over right and top respectively.

Slides.Settings.Toggle

Toggle ON/OFF checks in settings panel.

IPySlides Documentation │ Layout and Theme Settings
●●●●●
6

Useful Functions for Rich Content

Slides.alt(exportable_data, obj)

Display obj for slides and output of exportable_data will be and displayed only in exported formats as HTML.

  • exportable_data should be an html str or a callable to receive obj as its only argument.
    • A callable will give the latest representation of widget in exported slides and runtime representation of any other obj.
    • An html str, it will export the runtime representation of obj.
Python
import ipywidgets as ipw
slides.alt(lambda w: f'<input type="range" min="{w.min}" max="{w.max}" value="{w.value}">', ipw.IntSlider()).display()
        
  • If you happen to be using alt many times for same type, you can use Slides.serializer.register and then pass that type of widget without alt.
  • ipywidgets's HTML, Box and Output widgets and their subclasses directly give html representation if used inside write command.
Slides.AnimationSlider(*, continuous_update=<traitlets.traitlets.Bool object at 0x000001A2D17D31F0>, cyclic=<traitlets.traitlets.Bool object at 0x000001A2D17D3220>, description=<traitlets.traitlets.Unicode object at 0x000001A2D17D3100>, interval=<traitlets.traitlets.Float object at 0x000001A2D17D3190>, loop=<traitlets.traitlets.Bool object at 0x000001A2D17D3130>, nframes=<traitlets.traitlets.CInt object at 0x000001A2D17D3160>, playing=<traitlets.traitlets.Bool object at 0x000001A2D17D31C0>, value=<traitlets.traitlets.CInt object at 0x000001A2D17CDFA0>, **kwargs)

This is a simple slider widget that can be used to control the animation with an observer function.

You need to provide parameters like nframes and interval (milliseconds) to control the animation. The value trait can be observed to get the current frame index. The cyclic trait can be set to True to make the animation cyclic and only works when loop mode is ON.

Python
from plotly.graph_objects import FigureWidget
from dashlab.widgets import AnimationSlider

fig = FigureWidget()
fig.add_scatter(y=[1, 2, 3, 4, 5])
widget = AnimationSlider() 

def on_change(change):
    value = change['new']
    fig.data[0].color = f'rgb({int(value/widget.nframes*100)}, 100, 100)' # change color based on frame index

widget.observe(on_change, names='value')
display(widget, fig) # display it in the notebook
        

This widget can be passed to ipywidgets.interactive as keyword argument to create a dynamic control for the animation.

Python
from ipywidgets import interact

@interact(frame=widget)
def show_frame(frame):
    print(frame)
        
Slides.alert(text, bold=False, italic=False, **css_props)

Alerts text in red color. css_props are applied to span element.

Slides.bokeh2html(bokeh_fig, title='')

Write bokeh figure as HTML string to use in ipyslide.utils.write. Parameters

  • bokeh_fig : Bokeh figure instance.
  • title : Title for figure.
Slides.bullets(iterable, ordered=False, marker=None, css_class=None, **css_props)

A powerful bullet list. iterable could be list of anything that you can pass to write command. Use group for revealing points step by step in write, which also supports widgets.

  • If an item in iterable is a tuple/list of 2 elements and first element is a str, it will be used as per item marker.
  • ordered: bool, to create ordered or unordered list.
  • marker: str, CSS list-style-marker property for overall list, e.g. '✅' or '🔴' etc.

You can also use CSS list-style property in css_props for overall list, e.g. disc, circle, square, upper-roman etc. but it will be overridden by marker parameter if given. See list-style for marker types details.

Markdown Equivalent:

Markdown
::: ul .hrules list-style="'✅'" 
    ::: li list-style="'❌'" | First item
    ::: li data-marker=🔴 | Second item 
    ::: li
        Third item takes default marker and is large, so made block
        
  • First item
  • Second item
  • Third item takes default marker and is large, so made block
Slides.code(obj, language='python', name=None, css_class=None, style='default', color=None, background=None, hover_color='var(--bg3-color)', lineno=True, height='400px')

Create highlighted source code object from text, file or callable.

Use code(obj) or code.cast(obj) to get source code from any object that has a source or str of code.

Explicitly use:

  • code.from_file(filename) to get a source object from a file or file-like object.
  • code.from_string(string) to get a source object from a string.
  • code.from_source(obj) to get a source object from a python object (class, function, module, method etc.).

Returns: SourceCode object with show and focus methods to show selective lines, as well as .inline and .collapsed properties.

Slides.color(text, fg='var(--accent-color, blue)', bg=None, **css_props)

Colors text, fg and bg should be valid CSS colors. css_props are applied to span element.

Slides.details(obj, summary='Click to show content')

Show/Hide Content in collapsed html.

Slides.doc(obj, prepend_str=None, members=None, itself=True)

Returns documentation of an obj. You can prepend a class/module name. members is True/List of attributes to show doc of.

Slides.error(name, msg)

Add error without breaking execution.

Slides.esc(obj, display=False)

Lazy escape of variables in markdown using python formatted strings, to be resolved later and safe from markdown parsing. Use as xmd(f"This is an escaped variable: {esc(var or expression)} or xmd("This is an escaped variable: {}".format(esc(var or expression)). This is in par with %{var} syntax, but more flexible as it can take any expression. You are advised to use formatting strings rarely, instead use fmt class to pick variables and avoid clashes with $ \LaTeX $ syntax.

Slides.fmt(*args, **kwargs)

Markdown string wrapper that will be parsed with given kwargs lazily. If markdown contains variables not in kwargs, it will try to resolve them from local/global namespace and raise error if name is nowhere. Use inside python scripts when creating slides. In notebook, variables are automatically resolved, although you can still use it there.

Being as last expression of notebook cell or using self.parse() will parse markdown content. If you intend to use formatting strings, use esc class to lazily escape variables/expressions from being parsed.

Slides.focus(obj)

Wraps a given obj in a parent with 'focus-child' class or add 'focus-self' to widget, whether a widget or html/IPYthon object, to focus/exit on double click.

Slides.frozen(obj, metadata=None)

Display object as it it and export metadata if not str. A frozen object may not appear in exported html if metadata is not given.

Returned object has a display method, or can be directly passed to display/write commands.

Slides.html(tag, children=None, css_class=None, **node_attrs)

Returns html node with given children and node attributes like style, id etc. If an ttribute needs '-' in its name, replace it with '_'.
tag can be any valid html tag name. A tag that ends with / will be self closing e.g. hr/ will be <hr/>. Empty tag gives unwrapped children. children expects:

  • If None, returns node such as html('image',alt='Image') → <img alt='Image'></img> and html('image/',alt='Image') → <img alt='Image' />
  • str: A string to be added as node's text content.
  • list/tuple of [objects]: A list of objects that will be parsed and added as child nodes. Widgets are not supported.
  • dict if tag is 'style', this will only be exported to HTML if called under slide builder, use slides[number,].set_css otherwise. See Slides.css_syntax to learn about requirements of styles in dict.

Example:

Python
html('img',src='ir_uv.jpg') #Returns IPython.display.HTML("<img src='ir_uv.jpg'></img>") and displas image if last line in notebook's cell.
        

To keep an image persistently embeded, use ipyslides.utils.imge function instead of just an html tag.

Slides.iframe(src, width='100%', height='auto', **kwargs)

Display src in an iframe. kwrags are passed to IPython.display.IFrame

Slides.image(data=None, width='95%', caption=None, crop=None, css_props={}, css_class=None, **kwargs)

Displays PNG/JPEG files or image data etc, kwrags are passed to IPython.display.Image. crop is a tuple of (left, top, right, bottom) in percentage of image size to crop the image. css_props are applied to figure element, so you can control top layout and nested img tag. You can provide following to data parameter:

  • An opened PIL image. Useful for image operations and then direct writing to slides.
  • A file path to image file.
  • A url to image file.
  • A str/bytes object containing image data.
  • A str like "clip:image.png" will load an image saved in clips directory.
  • A filename like "image.png" will look for the file in current directory and then in Slides.clips_dir if not found. Use 'clip:image.png' to pick image from Slides.clips_dir directly if another file 'image.png' also exists in current directory.

Returns an IMG object which can be exported to other formats (if possible):

  • IMG.to_pil() returns PIL.Image or None.
  • IMG.to_numpy() returns image data as numpy array for use in plotting libraries or None.
Slides.notify(content, timeout=5)

Send inside notifications for user to know whats happened on some button click. Send 'x' in content to clear previous notification immediately.

Slides.pin(obj, x=None, y=None, width=None, height=None, center=False, zorder=0, rotate=0, blur=0, css_class=None, **css_props)

Pin an object at a specific position on the slide. Position is given in percentage of slide dimensions if int/float, otherwise any valid CSS unit. center will align the center of object to given coordinates instead of top left corner. zorder controls layering of pinned objects, higher zorder means on top. rotate and blur applies CSS transform and filter to object.

css_class and css_props are applied to pinned object for further customizations.

  • Beaware that pinning is contained relative to columns and containers with animation classes, use outside of any of those context to align to whole slide.
  • Use animation classes inside the pinned content, otherwise it will conflict with pin's CSS properties and may not work as expected.
Slides.plt2html(plt_fig=None, transparent=True, width=None, caption=None, crop=None)

Write matplotib figure as HTML string to use in ipyslide.utils.write. Parameters

  • plt_fig : Matplotlib's figure instance, auto picks as well.
  • transparent: True of False for fig background.
  • width : CSS style width. Default is figsize.
  • caption : Caption for figure.
  • crop : Crop SVG to given box in fraction 0-1 as tuple of (left, top, right, bottom).
Slides.raw(text, css_class=None)

Keep shape of text as it is (but apply dedent), preserving whitespaces as well.

Slides.set_dir(path)

Context manager to set working directory to given path and return to previous working directory when done.

Slides.sig(callable, prepend_str=None)

Returns signature of a callable. You can prepend a class/module name.

Slides.stack(objs, sizes=None, vertical=False, css_class=None, **css_props)

Stacks given objects in a column or row with given sizes.

  • objs: list/tuple of objects or a markdown string with '||' as separator.
  • sizes: list/tuple of sizes(int, float) for each object, if not given, all objects will have equal size.
  • vertical: bool, to stack objects vertically or horizontally, default is horizontal.
  • css_class: str, to add a class to the container div.
  • css_props: dict, applied to the container div, so you can control top layout.
Slides.styled(obj, css_class=None, **css_props)

Add a class to a given object, whether a widget or html/IPYthon object. CSS inline style properties should be given with names including '-' replaced with '_' but values should not. A widget will be wrapped in a Box to apply class and styles which otherwise may not work properly for some widgets. If you need a styled, yet not a block level widget, use display="inline-grid" in css_props.

Objects other than widgets will be wrapped in a 'div' tag. Use html function if you need more flexibility.

Slides.suppress_output(stdout=True)

Suppress output of a block of code. If stdout is False, only display data is suppressed.

Slides.suppress_stdout()

Suppress stdout in a block of code, especially unwanted print from functions in other modules.

Slides.svg(data=None, width=None, caption=None, crop=None, css_props={}, css_class=None, **kwargs)

Display svg file or svg string/bytes with additional customizations. crop is a tuple of (left, top, right, bottom) in percentage of image size to crop the image. css_props are applied to figure element, so you can control top layout and nested svg tag. kwrags are passed to IPython.display.SVG. You can provide url/string/bytes/filepath for svg.

Slides.table(data, headers=None, widths=None, css_class=None, **css_props)

Creates a table of given data like DataFrame, but with rich elements. data should be a 2D matrix-like. headers is a list of column names. widths is a list of widths for each column.

Example:

Python
import pandas as pd
df = pd.DataFrame({'A': [1,2,3], 'B': [4,5,6]})
slides.table(df.values, headers=df.columns, widths=[1,2])

slides.table([[1,2,3],[4,5,6]], headers=['A','B','C'], widths=[1,2,3])
        
Slides.textbox(text, **css_props)

Formats text in a box for writing e.g. inline refrences. css_props are applied to box and - should be _ like font-size → font_size. text is not parsed to general markdown i.e. only bold italic etc. applied, so if need markdown, parse it to html before. You can have common CSS for all textboxes using class text-box.

Slides.today(fmt='%b %d, %Y', fg='inherit')

Returns today's date in given format.

Slides.vspace(em=1)

Returns html node with given height in em.

IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
7

Citations and Sections

Use syntax cite`key` / @key to add citations which should be already set by Slides.set_citations(data) method. Any key that ends with ! is displayed inplace. Number of columns in displayed citations are determined by Slides.settings.layout(..., ncol_refs = int) or locally by Slides.refs(ncol). 1

Add sections in slides to separate content by section`text`. Corresponding table of contents can be added with toc`title`.

Slides.set_citations(data)

Set citations from dictionary or string with content like @key: citation value on their own lines, key should be cited in markdown as cite`key` / @key, optionally comma separated keys. Number of columns in displayed citations are determined by Slides.settings.layout(..., ncol_refs=N) or markdown refs`N`/Slides.refs(N).

Python
set_citations({"key1":"value1","key2":"value2"})

set_citations('''
@key1: citation for key1
@key2: citation for key2
''')

with open("citations_file.md","r") as f:
    set_citations(f.read()) # same content as string above

with open("citations_file.json","r") as f:
    set_citations(json.load(f))
        
  • You should set citations in start if using voila or python script. Setting in start in notebook is useful as well.
  • Citations are replaced with new ones, so latest use of this function represents available citations.
  • Makrdown equivalent of this function is a citation block only supported in Slides.sync_with_file's context.
1.

Citation A

IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
8
Back to link info

Dynamic Content

ipyslides.dashlab.interact(*funcs: list[callable], post_init: <built-in function callable> = None, **kwargs) -> None

Enhanced interactive widget with multiple callbacks, grid layout and fullscreen support.

This function is used for quick dashboards. Subclass DashboardBase for complex applications.

Features:

  • Multiple function support with selective updates
  • CSS Grid layout system
  • Extended widget trait observation
  • Dynamic widget property updates
  • Built-in fullscreen support

Basic Usage:

Python
from dashlab import interactive, callback, monitor
import ipywidgets as ipw
import plotly.graph_objects as go

fig = go.FigureWidget()

@callback('out-plot', timeit=True)  # check execution time
def update_plot(x, y, fig):
    fig.data = []
    fig.add_scatter(x=[0, x], y=[0, y])

def resize_fig(fig, fs):
    fig.layout.autosize = False # double trigger
    fig.layout.autosize = True # plotly's figurewidget always make trouble with sizing

# Above two functions can be merged since we can use changed detection
@monitor  # check execution time
def respond(x, y, fig , fs, changed):
    if 'fs' in changed: # or changed('fs')
        fig.layout.autosize = False # double trigger
        fig.layout.autosize = True
    else:
        fig.data = []
        fig.add_scatter(x=[0, x], y=[0, y])

dashboard = interactive(
    update_plot,
    resize_fig, # responds to fullscreen change
    # respond, instead of two functions
    x = ipw.IntSlider(0, 0, 100),
    y = ipw.FloatSlider(0, 1),
    fig = ipw.fixed(fig),
    changed = '.changed', # detect a change in parameter
    fs = '.isfullscreen', # detect fullscreen change on instance itself
)
        

Parameters:

  • *funcs: One or more callback functions
  • post_init: Optional function to run after all widgets are created as lambda self: (self.set_css(), self.set_layout(),...). You can annotate the type in function argument with DashboardBase to enable IDE hints and auto-completion e.g. def post_init(self:DashboardBase): ...
  • **kwargs: Widget parameters

Widget Parameters:

  • Regular ipywidgets with value trait
  • Fixed widgets using ipw.fixed(widget)
  • String pattern 'widget.trait' for trait observation, 'widget' must be in kwargs or e.g. '.trait' to observe traits on this instance.
  • Tuple pattern (widget, 'trait') for trait observation where widget is accessible via params and trait value goes to callback. This is useful to have widget and trait in a single parameter, such as x = (fig, 'selected') for plotly FigureWidget. Other traits of same widget can be observed by separate parameters with y = 'x.trait' pattern.
  • You can use '.fullscreen' to detect fullscreen change and do actions based on that.
  • Use P = '.params' to access all parameters in a callback, e.g. P.x.value = 10 will set x's value to 10 and trigger dependent callbacks.
  • Any DOM widget that needs display (inside fixed too). A widget and its observed trait in a single function are not allowed, such as f(fig, v) where v='fig.selected'.
  • Wrap any object in param = var(obj, match) to use it as a parameter with custom equality check like match(a, b) -> bool for dataframes or other objects. Assigning param.value = new_value will update the widget and trigger callbacks
  • Plotly FigureWidgets (use patched_plotly)
  • dashlab.button/ipywidgets.Button for manual updates on heavy callbacks besides. Add tooltip for info on button when not synced.
    • You can have multiple buttons in a single callback and check btn.clicked attribute to run code based on which button was clicked.
    • The manual button offered by ipywidgets.interactive is not suitable to hold a GUI with multiple callbacks, so that functionality is replaced by more flexible dashlab.button.
  • Plotly FigureWidgets (use patched_plotly for selection support)

Callbacks:

  • Methods decorated with @callback. Run in the order of definition.
  • Optional CSS class via @callback('out-myclass')
  • Decorate with @monitor to check execution time, kwargs etc.
  • CSS class must start with 'out-' excpet reserved 'out-main'
  • Each callback gets only needed parameters and updates happen only when relevant parameters change
  • Callbacks cannot call themselves recursively to prevent infinite loops
  • Output Widget Behavior:
    • An output widget is created only if a CSS class is provided via @callback.
    • If no CSS class is provided, the callback will use the main output widget, labeled as 'out-main'.

Attributes and Traits:

  • changed: Read-only trait to detect which parameters of a callback changed:
    • By providing changed = '.changed' in parameters and later in callback by checking changed('param') -> Bool.
    • Directly access self.changed in a subclass and use changed('param') -> Bool / 'param' in self.changed. Useful to merge callback.
  • isfullscreen: Read-only trait to detect fullscreen change on python side. Can be observed as '.isfullscreen' in params.
  • params: Read-only trait for all parameters used in this interact in widget form. Can be accessed inside callbacks by observing as P = '.params' alongwith some x = True -> Checkbox, and then inside a callback P.x.value = False will uncheck the Checkbox and trigger depnendent callbacks.
  • groups: NamedTuple(controls, outputs, others) - Widget names by type
  • outputs: tuple[Output] - Output widgets from callbacks

Notes:

  • Avoid modifying global slide state
  • Use widget descriptions to prevent name clashes
  • See set_css() method for styling options
  • interactive(no_args_func,) is perfectly valid and run on button click to do something like fetch latest data from somewhere.

Python dictionary to CSS

CSS is formatted using a props nested dictionary to simplify the process.

There are few special rules in props:

  • All nested selectors are joined with space, so '.A': {'.B': ... } becomes .A .B {...} in CSS.
  • A '^' in start of a selector joins to parent selector without space, so '.A': {'^:hover': ...} becomes .A:hover {...} in CSS. You can also use '.A:hover' directly but it will restrict other nested keys to hover only.
  • A list/tuple of values for a key in dict generates CSS fallback, so '.A': {'font-size': ('20px','2em')} becomes .A {font-size: 20px; font-size: 2em;} in CSS.
  • An empty key with a string/path value injects raw CSS wrapped in nested &, so '.A': {'': 'raw css here'} becomes & { .A { raw css here } } in CSS. This, however, can NOT be used to inject complex CSS like @import, @layer etc. :root is replaced with & to make variables local to the selector at given nesting level.

Read about specificity of CSS selectors here.

Tips:

  • You can use this inside columns using delayed display trick, like write('First column', C2) where C2 = Slides.hold(Slides.ei.interact, f, x = 5) or Slides.ei.interactive(f, x = 5).
  • You can also use this under Slides.capture_content to display later in a specific place.
Python
import time

@self.dl.interact(post_init = lambda self: self.set_css(dict({'.out-main': dict(height='2em')},background='var(--bg2-color)')), date = False, btn = self.dl.button())  # self is Slides here
def update_time(date, btn): 
    local_time = time.localtime()
    objs = ['Time: {3}:{4}:{5}'.format(*local_time)] # Print time in HH:MM:SS format
    if date:
        objs.append('Date: {0}/{1}/{2}'.format(*local_time))
    self.stack(objs).display()
        
Python
import datetime

@self.on_load  # self is Slides here
def push_toast(slide):
    t = datetime.datetime.now()
    time = t.strftime('%H:%M:%S')
    self.notify(f'Notification at {time} form slide {slide.index} and frame {slide.indexf}', timeout=5)
    return lambda s: self.notify('x') # clear notification immediately on exit by sending 'x'
        
Slides.on_load(func)

Decorator for running a func(slide) when slide is loaded into view. Use this to e.g. notify during running presentation. func accepts single arguemnet, slide. Return value could a cleanup function (which also accepts slide as single argument) executed when slide exits.

See Slides.docs() for few examples.

  • If you use this to change global state of slides, return a clean up function which accepts slide as argument.
  • This can be used only single time per slide, overwriting previous function.
IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
9

Content Styling

You can style or colorize your content and text. Provide CSS for that using Slides.html("style",...) or use some of the available styles. See these styles with Slides.css_styles property as shown on right.

Use any or combination of these styles in markdown blocks or css_class argument of writing functions:

css_class Formatting Style
text-[value] [value] should be one of tiny, small, big, large, huge.
align-[value] [value] should be one of center, left, right.
rtl اردو، فارسی، عربی، ۔۔۔
info Blue text. Icon ℹ️ for note-info class.
tip Blue text. Icon💡 for note-tip class.
warning Orange text. Icon ⚠️ for note-warning class.
success Green text. Icon ✅ for note-success class.
error Red text. Icon⚡ for note-error class.
note Text with note icon, can combine other classes as shown above.
export-only Hidden on main slides, but will appear in exported slides.
jupyter-only Hidden on exported slides, but will appear on main slides.
block Block of text/objects
block-[color] Block of text/objects with specific background color from
red, green, blue, yellow, cyan, magenta and gray.
[h,v]rules Horizontal and vertical rules between children of a node. Combined with ul or ol for lists gives nice effect and can be used to create tabular grids.
raw-text Text will be shown as printed style.
focus-self Double-click on element to zoom into popup view. Double-click again or navigate slides to exit.
focus-child Focus on child objects of node with this class. Same double-click to zoom in/out behavior.

Besides these CSS classes, you always have Slide.set_css, Slides.html('style',...) functions at your disposal.

Show Code
Markdown
stack[(3,7)]`//
## Content Styling
You can **style**{.error} or **color["teal"]`colorize`** your *content*{: style="color:hotpink;"} and *color["hotpink","yellow"]`text`*.
Provide **CSS**{.info} for that using code`Slides.html("style",...)` or use some of the available styles. 
See these **styles**{.success} with `Slides.css_styles` property as shown on right.
|| %{self.css_styles}
//`
        

IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
10

🎬 IPySlides Content Animations

All animations are fully composable - combine multiple animation classes to create complex effects! Use anim-group on a parent container to apply staggered animations to all children.

  • Python functions accepting css_class parameter can use these animation classes directly, such as Slide.write(..., css_class='anim-slide-left anim-zoom') and tweak variables if **css_props parameter is available.
  • You can used Slides.run_animation on demand with optional selector to target specific elements on slide after they are built. dashlab integration automatically runs animations after content inside changes.
Animation Class Description Effective Variables (--time: 0.6s, --delay: 0s` for all)
anim-appear Simple fade-in effect. None (only --time, --delay)
anim-slide-[direction] Slide in from specified direction: left, right, up, down, tl, tr, bl, br. --distance: CSS length (default: 120px)
anim-wipe-[direction] Wipe/reveal from edge: left, right, up, down. Linear clip-path reveal. None (only --time)
anim-iris Circular reveal (camera iris/aperture effect). Center customizable via --origin. --origin: Position as "X Y" (default: "50% 50%").
anim-zoom / anim-zoom-[x,y] Zoom in effect, optionally specify axis: x or y. Respects --origin. --scale: Number (default: 0.5)
anim-rotate Rotate in effect. Respects --origin. --angle: CSS angle (default: 180deg)
anim-spin Spin in with 2x rotation + scale. Respects --origin. --scale, --angle
anim-skew-[left,right] Skew in to left or right. --distance, --skew: angle (default: 20deg)
anim-blur Blur in effect. --blur: CSS length (default: 10px)
anim-brighten Brighten from dark + blur. --blur: CSS length (default: 10px)
anim-flip-x / anim-flip-x-reverse 3D flip on horizontal axis. Respects --origin. --perspective: CSS length (default: 800px)
anim-flip-y / anim-flip-y-reverse 3D flip on vertical axis. Respects --origin. --perspective: CSS length (default: 800px)
anim-perspective-[direction] 3D perspective from: up, down, left, right. --perspective, --distance
anim-bounce Bouncy entrance with slide + scale. --distance, --scale
anim-swing Swing from anchor. Respects --origin. --scale, --origin (e.g., "top center")
anim-elastic Elastic bounce timing. --scale
anim-kf Run user-defined @keyframes with animation lifecycle/stagger support. --kf-name (required), --kf-time, --kf-delay, --kf-ease, --kf-fill, --kf-count, --kf-direction
anim-group Power mode! Applies staggered animations to all children. All variables + auto stagger (sine curve)

🎨 Global Variables (Customizable)

  • Add on children of anim-group or individual animated elements to tweak animation effects.
  • You can set these via calculating in python systimatically for multiple elements and pass through variables embeding.
Variable Default Description
--time 0.6s Animation duration
--distance 120px Translation distance for slides
--angle 180deg Rotation angle
--scale 0.5 Scale factor (0-1)
--blur 10px Blur intensity
--perspective 800px 3D perspective depth
--skew 20deg Skew angle
--origin 50% 50% Universal origin for transform-origin and iris center. Can add per item in anim-group like any other CSS property.
--delay 0s Individual delay automatically calculated from sine curve (use on specific elements)
--kf-name none Name of user-defined @keyframes used by .anim-kf.
--kf-time var(--time) Duration for .anim-kf.
--kf-delay var(--delay) Delay for .anim-kf.
--kf-ease ease Timing function for .anim-kf.
--kf-fill both Fill mode for .anim-kf.
--kf-count 1 Iteration count for .anim-kf.
--kf-direction normal Animation direction for .anim-kf.
KeyError: Set value for cited key 'keyframes' and build slide again!
IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
11

🎬 IPySlides Content Animations

💡 Usage Examples

Basic Animations

Slides up from bottom

Opens like camera iris from center

Wipes in from right edge

Markdown
::: block anim-slide-up
    Slides up from bottom

::: block anim-iris
    Opens like camera iris from center

::: block anim-wipe-left
    Wipes in from right edge
        

Composable Animations (Stack Multiple!)

Slides, rotates, and zooms at once!

Fades in with blur from dark

Iris opens from top-left corner while zooming!

Markdown
::: block anim-slide-left anim-rotate anim-zoom
    Slides, rotates, and zooms at once!

::: block anim-blur anim-brighten anim-slide-up
    Fades in with blur from dark

::: block anim-iris anim-zoom --origin="0% 0%"
    Iris opens from top-left corner while zooming!
        
KeyError: Set value for cited key 'keyframes' and build slide again!
IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
11

🎬 IPySlides Content Animations

Custom Variables

Custom distance, scale, and timing!

Iris opens from bottom-right corner

Rotates 360° around left edge

Markdown
::: block anim-slide-up anim-zoom --distance=200px --scale=0.2 --time=1s
    Custom distance, scale, and timing!

::: block anim-iris --origin="100% 100%"
    Iris opens from bottom-right corner

::: block anim-rotate --origin="left center" --angle=360deg
    Rotates 360° around left edge
        

Custom Keyframes

// Define 1 in Slides.css(...) or in a notebook cell.

Plays user-defined 1 pulsePop with nav/parts animation lifecycle.

Markdown
// Define @keyframes in Slides.css(...) or in a notebook cell.
::: block anim-kf --kf-name=pulsePop --kf-time=900ms --kf-ease=ease-out
    Plays user-defined @keyframes pulsePop with nav/parts animation lifecycle.
        

🌟 Power Mode: anim-group (Staggered Animations)

  • Item 1 (0ms delay)
  • Item 2 (~84ms delay)
  • Item 3 (~188ms delay)
  • Item 4 (~295ms delay)
  • // Delays follow smooth sine curve: 100ms per 10 items

Markdown
::: ul anim-group anim-slide-left anim-zoom
    ::: li | Item 1 (0ms delay)
    ::: li | Item 2 (~84ms delay)
    ::: li | Item 3 (~188ms delay)
    ::: li | Item 4 (~295ms delay)
    // Delays follow smooth sine curve: 100ms per 10 items
        
KeyError: Set value for cited key 'keyframes' and build slide again!
IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
11

🎬 IPySlides Content Animations

Per Item Origins (Dynamic Effects)

  • Each item opens from different origin
  • With rotation
  • Staggered naturally
Markdown
::: ul anim-group anim-iris anim-rotate
    ::: li --origin="33% 50%" | Each item opens from different origin
    ::: li --origin="50% 50%" | With rotation
    ::: li --origin="67% 50%" | Staggered naturally
        

Advanced Combinations

Slide in from left

Zoom in

Rotate 60°

Slide up + Zoom

Elastic bounce with heavy blur!

Flips up from bottom while zooming!

Show Code
Markdown
::: columns anim-group
    ::: block anim-slide-left border="1px solid red" padding="10px"
        Slide in from left
    ::: block anim-zoom border="1px solid green" padding="10px"
        Zoom in
    ::: block anim-rotate --angle=60deg border="1px solid blue" padding="10px"
        Rotate 60°
    ::: block anim-slide-up anim-zoom border="1px solid orange" padding="10px"
        Slide up + Zoom

::: block-red anim-elastic anim-blur --blur=20px
    Elastic bounce with heavy blur!

::: block anim-flip-x anim-zoom --origin="center bottom"
    Flips up from bottom while zooming!
        
KeyError: Set value for cited key 'keyframes' and build slide again!
IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
11

🎬 IPySlides Content Animations

✨ Key Features

  • ✅ Fully Composable - Mix any animations by stacking classes
  • ✅ Universal --origin - Controls transform-origin AND iris center position
  • ✅ No order dependency - anim-zoom anim-rotate = anim-rotate anim-zoom
  • ✅ Smart stagger - anim-group auto-calculates delays with sine curve (100ms/10 items)
  • ✅ Per item positioning - Use --origin per item on children of anim-group for dynamic effects
  • ✅ Print-friendly - All animations visible in print/PDF mode
  • ✅ No reverse animation - Instantly visible on backward navigation
  • ✅ Easy customization - Override any variable inline or globally

🎯 Pro Tips

  1. Combine wisely: anim-slide-up anim-zoom anim-rotate creates dramatic entrances
  2. Use anim-group for lists: Automatically staggers children for smooth reveals
  3. Control origin: Set --origin to change rotation/zoom/iris center point
  4. Test combinations: 27+ base animations = 1000+ possible combinations!
  5. Timing matters: Adjust --time for slower/faster effects
  6. Iris from corners: Use --origin: 0% 0% or 100% 100% for dramatic reveals

The power is in composition! 🚀

KeyError: Set value for cited key 'keyframes' and build slide again!
IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
11

🎬 IPySlides Content Animations

✨ Key Features

  • ✅ Fully Composable - Mix any animations by stacking classes
  • ✅ Universal --origin - Controls transform-origin AND iris center position
  • ✅ No order dependency - anim-zoom anim-rotate = anim-rotate anim-zoom
  • ✅ Smart stagger - anim-group auto-calculates delays with sine curve (100ms/10 items)
  • ✅ Per item positioning - Use --origin per item on children of anim-group for dynamic effects
  • ✅ Print-friendly - All animations visible in print/PDF mode
  • ✅ No reverse animation - Instantly visible on backward navigation
  • ✅ Easy customization - Override any variable inline or globally

🎯 Pro Tips

  1. Combine wisely: anim-slide-up anim-zoom anim-rotate creates dramatic entrances
  2. Use anim-group for lists: Automatically staggers children for smooth reveals
  3. Control origin: Set --origin to change rotation/zoom/iris center point
  4. Test combinations: 27+ base animations = 1000+ possible combinations!
  5. Timing matters: Adjust --time for slower/faster effects
  6. Iris from corners: Use --origin: 0% 0% or 100% 100% for dramatic reveals

The power is in composition! 🚀

KeyError: Set value for cited key 'keyframes' and build slide again!
IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
11

Highlighting Code

pygments is used for syntax highlighting 1. You can highlight code using Slides.code 2 or within markdown using named code blocks:

Python
import ipyslides as isd
        
Javascript
import React, { Component } from "react";
        

Source code of slide can be embeded via variable too:

Markdown
## Highlighting Code
[pygments](https://pygments.org/) is used for syntax highlighting cite`A`.
You can **highlight**{.error} code using `Slides.code` cite`B` or within markdown using named code blocks:
```python
import ipyslides as isd
```
```javascript
import React, { Component } from "react";
```
Source code of slide can be embeded via variable too: %{self.this.source}
        

1.

Citation A

2.

Citation B

IPySlides Documentation │ Useful Functions for Rich Content
●●●●●
12

Loading from File/Exporting to HTML

You can parse and view a markdown file. The output you can save by exporting notebook in other formats.

Slides.sync_with_file(start_slide_number, /, path, interval=500)

Auto update slides when content of markdown file changes. You can stop syncing using Slides.unsync function. interval is in milliseconds, 500 ms default. Read Slides.build docs about content of file.

The variables inserted in file content are used from top scope.

You can add files inside linked file using include\`file_path.md\` syntax, which are also watched for changes. This helps modularity of content, and even you can link a citation file in markdown format as shown below. Read more in Slides.xmd.syntax about it.

Markdown
```citations
@key1: Saboor et. al., 2025
@key2: A citations can span multiple lines, but key should start on new line
<!--_xmd_cmt_0_-->
```
        

To debug the linked file or included file, use EOF on its own line to keep editing and clearing errors.

Slides.demo()

Demo slides with a variety of content.

Slides.docs()

Create presentation from docs of IPySlides. Using 1 excessively speeds up initial loading.

Slides.export_html(path='Slides.html', overwrite=False)

Build html slides that you can print.

  • Use 'overrides.css' file in same folder to override CSS styles.
  • If a slide has only widgets or does not have single object with HTML representation, it will be skipped.
  • You can take screenshot (using system's tool) of a widget, save it using Clips GUI in side panel and laod as image to keep PNG view of a widget.
  • PDF printing of slide width is 210mm (8.25in). Height is determined by aspect ratio provided.
  • Use Save as PDF option instead of Print PDF in browser to make links work in output PDF. Alsp enable background graphics in print dialog.
KeyError: Set value for cited key 'build' and build slide again!
IPySlides Documentation │ Loading from File/Exporting to HTML
●●●●●
13

Contents

  1. Introduction
  2. Adding Slides and Content
  3. Layout and Theme Settings
  4. Useful Functions for Rich Content
  5. Loading from File/Exporting to HTML
  6. Advanced Functionality
  7. Presentation Code
IPySlides Documentation │ Advanced Functionality
●●●●●
14

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding content on frames incrementally

Python
@self.build_
def _(s):
    self.write("## Adding content on frames incrementally")
    self.frozen(widget := (code := s.get_source()).as_widget()).display()
    # frozen in above line get oldest metadata for export
    def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
    self.on_load(highlight_code)

    for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
        cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
        self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')
        

0

1

2

3

4

5

6

7

IPySlides Documentation │ Advanced Functionality
●●●●●
15

Adding User defined Objects/Markdown Extensions

I will be on exported slides

Python
@self.build_
def _(s):
    self.write('## Adding User defined Objects/Markdown Extensions')
    self.write(
        self.hold(display, self.html('h3','I will be on main slides',css_class='warning'),
            metadata = {'text/html': '<h3 class="warning">I will be on exported slides</h3>'}
        ), # Can also do 'Slides.serilaizer.get_metadata(obj)' if registered
        s.get_source(), widths = [1,3]
    )
    self.write(r'If you need to serialize your own or third party objects not serialized by this module, you can use `\@Slides.serializer.register` to serialize them to html.\n{.note .info}')
    self.doc(self.serializer,'Slides.serializer', members = True, itself = False).display()
    self.write('**You can also extend markdown syntax** using `markdown extensions`, ([See here](https://python-markdown.github.io/extensions/) and others to install, then use as below):')
    self.doc(self.xmd.extensions,'Slides.xmd.extensions', members = True, itself = False).display()
        

If you need to serialize your own or third party objects not serialized by this module, you can use @Slides.serializer.register to serialize them to html.\n{.note .info}

Slides.serializer.get_func(obj_type)

Get serializer function for a type. Returns None if not found.

Slides.serializer.get_html(obj_type)

Get html str of a registerd obj_type.

Slides.serializer.get_metadata(obj_type)

Get metadata for a type to use in display(obj, metadata) for export purpose. This take precedence over object's own html representation. Returns {} if not found.

Slides.serializer.register(obj_type, verbose=True)

Decorator to register html serializer for an object type.

  • Decoracted function accepts one argument that will take obj_type and should return HTML string.
  • This definition will take precedence over any other in the module.
  • All regeisted serializers only exist for the lifetime of the module in a namespace.
  • Only a single serializer can be registered for an object type.

Usage

Python
class MyObject:
    def __repr__(self):
        return 'My object is awesome'

slides = ipyslides.Slides()
@slides.serializer.register(MyObject)
def make_h1(obj):
    return f'<h1>{obj!r}</h1>'

my_object = MyObject()
slides.write(my_object) #This will write "My object is awesome" as main heading
make_h1(my_object) #This will return "<h1>My object is awesome</h1>"

#This is equivalent to above for custom objects(builtin objects can't be modified)
class MyObject:
    def _repr_html_(self):
        return '<h1>My object is awesome</h1>'

my_object = MyObject()
slides.write(my_object)
        
  • Serializer function should return html string. It is not validated for correct code on registration time.
  • Serializer is useful for buitin types mostly, for custom objects, you can always define a _repr_html_ method which works as expected.
  • Serialzers for widgets are equivalent to Slides.alt(func, widget) inside write command for export purpose. Other commands such as Slides.[cols,rows,...] will pick oldest value only.
  • IPython's display function automatically take care of serialized objects.
Slides.serializer.unregister(obj_type)

Unregister all serializer handlers for a type.

Slides.serializer.unregisterall()

Unregister all serializer handlers.

You can also extend markdown syntax using markdown extensions, (See here and others to install, then use as below):

Slides.xmd.extensions.clear()

Clear all extensions and their configurations added by user.

Slides.xmd.extensions.config(configs_dict)

Add configurations to the Markdown extensions. configs_dict is a dictionary like {'extension_name': config_dict}

Slides.xmd.extensions.extend(extensions_list)

Add list of extensions to the Markdown parser.

IPySlides Documentation │ Advanced Functionality
●●●●●
16

Focus on what matters

  • Most of supported elements can be focused by default like images, matplotlib, bokeh, PIL image, altair plotly, dataframe, etc.
  • You can also enable focus on an object/widget by wrapping it inside `Slide.focus` function conveniently.
  • You can also enable focus by manually adding focus-self, focus-child classes to an element.

Focus on Me 😎

Double click to focus on this block. Click at top right button or double click to exit.

IPySlides Documentation │ Advanced Functionality
●●●●●
17

SVG Icons

Icons that apprear on buttons inslides (and their rotations) available to use in your slides as well besides standard ipywidgets icons.

Python
import ipywidgets as ipw
btn = ipw.Button(description='Chevron-Down Icon',icon='chevrond')    
self.write(btn)
        

Source code of this slide

Python
@self.build_
def _(s):
    with self.capture_content() as c:
        with self.code.context():
            import ipywidgets as ipw
            btn = ipw.Button(description='Chevron-Down Icon',icon='chevrond')    
            self.write(btn)

    group = zip(self.icon.available[::2], self.icon.available[1::2]) # make 4 columns table
    self.write(['''
        ## SVG Icons
        Icons that apprear on buttons inslides (and their rotations) available to use in your slides as well
        besides standard ipywidgets icons.
        ''', *c.outputs, 'line`200`**Source code of this slide**',self.this.get_source()], 
        self.table([(f'`{j}`', self.icon(j,color='crimson').svg,f'`{k}`', self.icon(k,color='crimson').svg) for j, k in group],headers=['Name','Icon','Name','Icon']),
    widths=[3,2])
        

Name

Icon

Name

Icon

arrow

arrowb

arrowbd

arrowbl

arrowbr

arrowbu

arrowd

arrowl

arrowr

arrowu

bars

camera

chevron

chevrond

chevronl

chevronr

chevronu

circle

close

code

columns

compress

dots

edit

expand

info

keyboard

laser

loading

panel

pause

pencil

play

refresh

rows

search

settings

stop

swipe-off

swipe-on

win-maximize

win-restore

zoom-in

zoom-out

IPySlides Documentation │ Advanced Functionality
●●●●●
18

Auto Slide Numbering

Use -1 as placeholder to update slide number automatically.

  • In Jupyter notebook, this will be updated to current slide number.
  • In python file, it stays same.
  • You need to run cell twice if creating slides inside a for loop while using -1.
  • Additionally, in python file, you can use Slides.build_ instead of using -1.

Some kernels may not support auto slide numbering inside notebook.

IPySlides Documentation │ Advanced Functionality
●●●●●
19

Presentation Code

Python
def docs(self):
    "Create presentation from docs of IPySlides. Using @build excessively speeds up initial loading."
    self.clear(keep = 20) # Clear previous slides except first 19
    self.create(range(20)) # Create slides if missing for first 18 slides
    # Using clear, create and @build lazy execution cuts down initial loading time by ~85% of eager loading

    from ..core import Slides

    self.set_citations({'A': 'Citation A', 'B': 'Citation B'})
    self.settings.footer(text=self.get_logo("1em") + "IPySlides Documentation", date=None)

    with self.build(0): # Title page
        self.bg(self.get_logo(),0.25, filter='blur(10px)', contain=True)
        self.write(f'## IPySlides {self.version} Documentation\n### Creating slides with IPySlides')
        self.center(self.fmt('''
            alert`Abdul Saboor` ^`1`

            today``
            {.text-small}

            %{logo}

            ::: text-box
                ^`1`My University is somewhere in the middle of nowhere

            ::: info
                Right click (or click on footer) to open context menu for accessing settings, table of contents etc.  
            ''', logo = self.get_logo("4em"))).display()

    self.build(-1, '''
        ```md-after
            section`Introduction` 
            ```columns .block-green
            toc[True]`## Table of contents`
            +++
            ### This is summary of current section
            Oh we can use inline columns stack`Column A || Column B` here and what not!
            %{btn}
            pin[60,50, rotate=15]`::: anim-slide-left block-red | This is pinned content!`
            ```
        ```''', btn = self.draw_button)

    skipper = self.link('Skip to dynamic content', 'Back to link info', icon='arrow', back_icon='arrowl')

    @self.build(-1)
    def _(s):
        grp = self.group(snapshots=True) # display separately as snaphots
        grp.append(['# Main App', self.doc(Slides)])

        with grp.capture(): # displayed stuff need to be captured
            self.write('# Jump between slides')
            self.doc(self.link, 'Slides').display()
            with self.code.context(returns=True) as c:
                skipper.origin.display() # skipper.target is set later somewhere, can do backward jump too
            c.display()

        grp.append([
            '## Adding Slides section`Adding Slides and Content`',
            'Besides function below, you can add slides with `%%slide number [-m]` magic as well.\n{.note .info}',
            self.doc(self.build,'Slides'), 
            self.doc(self.sync_with_file,'Slides'),
        ])

        with grp.capture():
            self.write('''
                ## Important Methods on Slide
                ::: note-warning
                    - Use slide handle or `Slides[number,]` to apply these methods becuase index can change on new builds.
                    - Use `Slides[start:stop:step]` to apply operations on many slides at once such as code`Slides[2:5].vars.update(...)`.
            ''')
            self.doc(self[0], members='vars update_display get_source show'.split(), itself = False).display()

        self.pause() # incremental display on
        self.write(grp)

    with self.build(-1): 
        self.xmd.syntax.display()

    @self.build(-1)
    def _(s):
        grp = self.group(snapshots=True) # display separately as snaphots
        with grp.capture():
            self.xmd('''
                ## Adding Content
                Besides functions below, you can add content to slides with `%%xmd`,`%xmd` as well.
                {.note .info}
            ''')
            self.write(
                self.doc(self.write,'Slides'), 
                [
                    self.doc(self.xmd,'Slides'),
                    self.doc(self.as_html,'Slides'),
                    self.doc(self.as_html_widget,'Slides'),
                    self.doc(self.html,'Slides')
                ]
            )

        grp.append(['''
            ## Dual Usage Functions
            Some functions such as `Slides.css`, `Slides.yoffset`, and `Slides.transition` can be used
            both inside and outside slide context through their `applyto` parameter.
            If `applyto` is `None` (or omitted), they require an active slide context and apply to the current slide.
            If `applyto` is provided (for example, a slide index, list of indices, or `'all'`), they can be used outside
            a slide context and apply to the selected slides. They can also used from markdown with syntax like `function[applyto]\`content\``.
            ''',
            self.doc(self.transition,'Slides'),
            self.doc(self.yoffset,'Slides'),
            self.doc(self.css,'Slides'),
             self.css_syntax # need to show docs after CSS function above
        ])

        grp.append(['''
            ## Adding Speaker Notes
            styled["note success"]`You can use alert`notes\`notes content\`` in markdown.`'
            ::: note-error error | This is experimental feature, and may not work as expected.
            ''', # multiple objects appneded togther are shown togther in incremental display
            self.doc(self.notes,'Slides.notes', members = True, itself = False)
        ])

        grp.append([
            '## Displaying Source Code',
            'In markdown, the block `md-[before,after,var_name]` parses and displays source as well.',
            self.doc(self.code,'Slides', members = True, itself = True)
        ])

        self.pause() # incremental display on
        self.write(grp)

    self.build(-1, r'section`//Layout and color["yellow","black"]`Theme` Settings//` toc`### Contents`')

    @self.build_
    def _(s):
        self.css({ # does not need explicit `applyto` parameter under slide context
            '.highlight': {'background':'#8984'}
        }, bg1 = 'linear-gradient(45deg, var(--bg3-color), var(--bg2-color), var(--bg3-color))')
        self.styled('## Layout and Theme Settings', 'info', border='1px solid red').display()
        self.doc(self.settings,'Slides', members=True,itself = True).display()

    @self.build(-1)
    def _(s):
        self.write('## Useful Functions for Rich Content section`//Useful Functions for alert`Rich Content`//`')
        self.doc(self.alt,'Slides').display()

        members = sorted((
            'AnimationSlider alert bokeh2html bullets esc styled fmt code color details doc '
            'today error focus html iframe image frozen notify plt2html pin '
            'raw set_dir sig stack table textbox suppress_output suppress_stdout svg vspace'
        ).split())
        self.doc(self, 'Slides', members = members, itself = False).display()

    @self.build(-1)
    def _(s):
        self.write(r'''
            ## Citations and Sections
            Use syntax alert`cite\`key\`` / alert`\@key` to add citations which should be already set by code`Slides.set_citations(data)` method.
            Any key that ends with `!` is displayed inplace. Number of columns in displayed citations are determined by 
            code`Slides.settings.layout(..., ncol_refs = int)` or locally by code`Slides.refs(ncol)`. @A

            Add sections in slides to separate content by alert`section\`text\``. Corresponding table of contents
            can be added with alert`toc\`title\``.
        ''')
        self.doc(self, 'Slides', members = ['set_citations'], itself = False).display()

    @self.build(-1)
    def _(s):
        skipper.target.display() # Set target for skip button
        self.write('## Dynamic Content')

        with self.capture_content() as cap, self.code.context():
            import time

            @self.dl.interact(post_init = lambda self: self.set_css(dict({'.out-main': dict(height='2em')},background='var(--bg2-color)')), date = False, btn = self.dl.button())  # self is Slides here
            def update_time(date, btn): 
                local_time = time.localtime()
                objs = ['Time: {3}:{4}:{5}'.format(*local_time)] # Print time in HH:MM:SS format
                if date:
                    objs.append('Date: {0}/{1}/{2}'.format(*local_time))
                self.stack(objs).display()

        with self.code.context(returns=True) as c:
            import datetime

            @self.on_load  # self is Slides here
            def push_toast(slide):
                t = datetime.datetime.now()
                time = t.strftime('%H:%M:%S')
                self.notify(f'Notification at {time} form slide {slide.index} and frame {slide.indexf}', timeout=5)
                return lambda s: self.notify('x') # clear notification immediately on exit by sending 'x'

        self.write(
            [self.doc(self.dl.interact,'ipyslides.dashlab')], 
            [*cap.outputs, c, self.doc(self.on_load,'Slides')],
        )

    self.build(-1, """
    ```md-src.collapsed
    stack[(3,7)]`//
    ## Content Styling
    You can **style**{.error} or **color["teal"]`colorize`** your *content*{: style="color:hotpink;"} and *color["hotpink","yellow"]`text`*.
    Provide **CSS**{.info} for that using code`Slides.html("style",...)` or use some of the available styles. 
    See these **styles**{.success} with `Slides.css_styles` property as shown on right.
    || %{self.css_styles}
    //`     
    ```
    <md-src/>
    """, self=self)

    self.build(-1, lambda s: self.css_animations.display())

    self.build(-1, '''
    ## Highlighting Code
    [pygments](https://pygments.org/) is used for syntax highlighting cite`A`.
    You can **highlight**{.error} code using `Slides.code` cite`B` or within markdown using named code blocks:
    ```python
    import ipyslides as isd
    ```
    ```javascript
    import React, { Component } from "react";
    ```
    Source code of slide can be embeded via variable too: %{self.this.source}
    ''', self=self)


    with self.build(-1):
        self.write('## Loading from File/Exporting to HTML section`Loading from File/Exporting to HTML`')
        self.write('You can parse and view a markdown file. The output you can save by exporting notebook in other formats.\n{.note .info}')
        self.write([self.doc(attr,'Slides') for attr in (self.sync_with_file,self.demo,self.docs,self.export_html)])

    self.build(-1, 'section`Advanced Functionality` toc`### Contents`')

    @self.build_
    def _(s):
        self.write("## Adding content on frames incrementally")
        self.frozen(widget := (code := s.get_source()).as_widget()).display()
        # frozen in above line get oldest metadata for export
        def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
        self.on_load(highlight_code)

        for ws, cols in self.pause.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)]), isolate=True): # isolate to split from previous content
            cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
            self.write(*cols, widths=ws, css_class='anim-group anim-wipe-right')

    @self.build_
    def _(s):
        self.write('## Adding User defined Objects/Markdown Extensions')
        self.write(
            self.hold(display, self.html('h3','I will be on main slides',css_class='warning'),
                metadata = {'text/html': '<h3 class="warning">I will be on exported slides</h3>'}
            ), # Can also do 'Slides.serilaizer.get_metadata(obj)' if registered
            s.get_source(), widths = [1,3]
        )
        self.write(r'If you need to serialize your own or third party objects not serialized by this module, you can use `\@Slides.serializer.register` to serialize them to html.\n{.note .info}')
        self.doc(self.serializer,'Slides.serializer', members = True, itself = False).display()
        self.write('**You can also extend markdown syntax** using `markdown extensions`, ([See here](https://python-markdown.github.io/extensions/) and others to install, then use as below):')
        self.doc(self.xmd.extensions,'Slides.xmd.extensions', members = True, itself = False).display()

    with self.build(-1):
        self.write(r'''
        ## Focus on what matters
        - Most of supported elements can be focused by default like images, matplotlib, bokeh, PIL image, altair plotly, dataframe, etc.
        - You can also enable focus on an object/widget by wrapping it inside \`Slide.focus\` function conveniently.
        - You can also enable focus by manually adding `focus-self`, `focus-child` classes to an element. 

        ::: focus-self block-red
            ### Focus on Me 😎
            Double click to focus on this block. Click at top right button or double click to exit.
        ''')

    @self.build_
    def _(s):
        with self.capture_content() as c:
            with self.code.context():
                import ipywidgets as ipw
                btn = ipw.Button(description='Chevron-Down Icon',icon='chevrond')    
                self.write(btn)

        group = zip(self.icon.available[::2], self.icon.available[1::2]) # make 4 columns table
        self.write(['''
            ## SVG Icons
            Icons that apprear on buttons inslides (and their rotations) available to use in your slides as well
            besides standard ipywidgets icons.
            ''', *c.outputs, 'line`200`**Source code of this slide**',self.this.get_source()], 
            self.table([(f'`{j}`', self.icon(j,color='crimson').svg,f'`{k}`', self.icon(k,color='crimson').svg) for j, k in group],headers=['Name','Icon','Name','Icon']),
        widths=[3,2])


    with self.build_():
        self.write("""
            # Auto Slide Numbering
            Use alert`-1` as placeholder to update slide number automatically. 

            - In Jupyter notebook, this will be updated to current slide number. 
            - In python file, it stays same.
            - You need to run cell twice if creating slides inside a for loop while using `-1`.
            - Additionally, in python file, you can use ` Slides.build_ ` instead of using `-1`.

            ::: note-warning
                Some kernels may not support auto slide numbering inside notebook.
        """)

    self.build(-1, lambda s: self.write(['## Presentation Code section[True]`Presentation Code`',self.docs]))
    self.navigate_to(0) # Go to title, do not return to avoid display shift to this cell
        
IPySlides Documentation │ Presentation Code
●●●●●
S.1