Skip to content

Theme-dependent image variants #1991

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions guide/src/format/images/rust-logo-blk-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions guide/src/format/markdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,28 @@ Which, of course displays the image like so:

![The Rust Logo](images/rust-logo-blk.svg)

## Theme-dependent images

Image variants for different themes can be used via CSS classes.

Here is an example for different images for light vs. dark themes:

```markdown
<img src="images/rust-logo-blk.svg" class="no-dark-themes" />
<img src="images/rust-logo-blk-dark.svg" class="no-light-themes" />
Comment on lines +127 to +128
Copy link

@not-my-profile not-my-profile Feb 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer only-light-themes and only-dark-themes for the class names ... since the negation is a bit unintuitive.

There is also some precedence for that, see e.g. the mkdocs material documentation.

Copy link
Author

@mlange-42 mlange-42 Feb 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, you are probably right here. Will try to rework this accordingly.

Copy link

@2bndy5 2bndy5 Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, this fenced block is only html syntax.

Some MD linters prohibit the use of raw HTML, so maybe change this to

```markdown
![rust logo standard edition](images/rust-logo-blk.svg#only-light)
![rust logo dark mode](images/rust-logo-blk-dark.svg#only-dark)
```

as hayesall reported it working.

```

Try switching the theme to see the effect below (brush icon at the top left of the page):

<img src="images/rust-logo-blk.svg" class="no-dark-themes" />
<img src="images/rust-logo-blk-dark.svg" class="no-light-themes" />

To exclude an image (or any HTML element) for all dark or all light themes
(incl. the Rust theme), use the classes `no-dark-themes` and `no-light-themes`.

For even more control, elements can be hidden on an individual theme basis using the classes
`no-light`, `no-rust`, `no-coal`, `no-navy` and `no-ayu`.

## Extensions

mdBook has several extensions beyond the standard CommonMark specification.
Expand Down
1 change: 1 addition & 0 deletions guide/src/format/theme/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Here are the files you can override:
- **_css/chrome.css_** is for UI elements.
- **_css/general.css_** is the base styles.
- **_css/print.css_** is the style for printer output.
- **_css/exclude.css_** is for [theme-dependent images](../markdown.md#theme-dependent-images).
- **_css/variables.css_** contains variables used in other CSS files.
- **_book.js_** is mostly used to add client side functionality, like hiding /
un-hiding the sidebar, changing the theme, ...
Expand Down
3 changes: 3 additions & 0 deletions src/book/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ impl BookBuilder {
let mut variables_css = File::create(cssdir.join("variables.css"))?;
variables_css.write_all(theme::VARIABLES_CSS)?;

let mut excludes_css = File::create(cssdir.join("exclude.css"))?;
excludes_css.write_all(theme::EXCLUDES_CSS)?;

let mut favicon = File::create(themedir.join("favicon.png"))?;
favicon.write_all(theme::FAVICON_PNG)?;

Expand Down
1 change: 1 addition & 0 deletions src/renderer/html_handlebars/hbs_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ impl HtmlHandlebars {
write_file(destination, "css/print.css", &theme.print_css)?;
}
write_file(destination, "css/variables.css", &theme.variables_css)?;
write_file(destination, "css/exclude.css", &theme.excludes_css)?;
if let Some(contents) = &theme.favicon_png {
write_file(destination, "favicon.png", contents)?;
}
Expand Down
18 changes: 18 additions & 0 deletions src/theme/css/exclude.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.light .no-light,
.rust .no-rust,
.navy .no-navy,
.ayu .no-ayu,
.coal .no-coal {
display: none;
}

.light .no-light-themes,
.rust .no-light-themes {
display: none;
}

.navy .no-dark-themes,
.ayu .no-dark-themes,
.coal .no-dark-themes {
display: none;
}
1 change: 1 addition & 0 deletions src/theme/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
<link rel="stylesheet" href="{{ path_to_root }}css/general.css">
<link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
<link rel="stylesheet" href="{{ path_to_root }}css/exclude.css">
{{#if print_enable}}
<link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
{{/if}}
Expand Down
6 changes: 6 additions & 0 deletions src/theme/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub static CHROME_CSS: &[u8] = include_bytes!("css/chrome.css");
pub static GENERAL_CSS: &[u8] = include_bytes!("css/general.css");
pub static PRINT_CSS: &[u8] = include_bytes!("css/print.css");
pub static VARIABLES_CSS: &[u8] = include_bytes!("css/variables.css");
pub static EXCLUDES_CSS: &[u8] = include_bytes!("css/exclude.css");
pub static FAVICON_PNG: &[u8] = include_bytes!("favicon.png");
pub static FAVICON_SVG: &[u8] = include_bytes!("favicon.svg");
pub static JS: &[u8] = include_bytes!("book.js");
Expand Down Expand Up @@ -54,6 +55,7 @@ pub struct Theme {
pub general_css: Vec<u8>,
pub print_css: Vec<u8>,
pub variables_css: Vec<u8>,
pub excludes_css: Vec<u8>,
pub favicon_png: Option<Vec<u8>>,
pub favicon_svg: Option<Vec<u8>>,
pub js: Vec<u8>,
Expand Down Expand Up @@ -91,6 +93,7 @@ impl Theme {
theme_dir.join("css/variables.css"),
&mut theme.variables_css,
),
(theme_dir.join("css/exclude.css"), &mut theme.excludes_css),
(theme_dir.join("highlight.js"), &mut theme.highlight_js),
(theme_dir.join("clipboard.min.js"), &mut theme.clipboard_js),
(theme_dir.join("highlight.css"), &mut theme.highlight_css),
Expand Down Expand Up @@ -153,6 +156,7 @@ impl Default for Theme {
general_css: GENERAL_CSS.to_owned(),
print_css: PRINT_CSS.to_owned(),
variables_css: VARIABLES_CSS.to_owned(),
excludes_css: EXCLUDES_CSS.to_owned(),
favicon_png: Some(FAVICON_PNG.to_owned()),
favicon_svg: Some(FAVICON_SVG.to_owned()),
js: JS.to_owned(),
Expand Down Expand Up @@ -213,6 +217,7 @@ mod tests {
"css/general.css",
"css/print.css",
"css/variables.css",
"css/exclude.css",
"book.js",
"highlight.js",
"tomorrow-night.css",
Expand Down Expand Up @@ -240,6 +245,7 @@ mod tests {
general_css: Vec::new(),
print_css: Vec::new(),
variables_css: Vec::new(),
excludes_css: Vec::new(),
favicon_png: Some(Vec::new()),
favicon_svg: Some(Vec::new()),
js: Vec::new(),
Expand Down
1 change: 1 addition & 0 deletions tests/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ fn copy_theme() {
let expected = vec![
"book.js",
"css/chrome.css",
"css/exclude.css",
"css/general.css",
"css/print.css",
"css/variables.css",
Expand Down