hotdoc / hotdoc_bootstrap_theme

1 stars 6 forks source link

StyleSwitcher performance/compatibility issues #19

Open ferdnyc opened 1 year ago

ferdnyc commented 1 year ago

The current implementation of style switching is kind of a janky mess, to be honest. It also relies on switching active styles via an esoteric "alternate" stylesheet feature only officially supported in Firefox, and even then it isn't being used entirely correctly (emphasis in original document):

Any stylesheet in a document falls into one of the following categories:

  • Persistent (has rel="stylesheet", no title=""): always applies to the document.
  • Preferred (has rel="stylesheet", with title="…" specified): applied by default, but disabled if an alternate stylesheet is selected. There can only be one preferred stylesheet, so providing stylesheets with different title attributes will cause some of them to be ignored.
  • Alternate (rel="alternate stylesheet", with title="…" specified): disabled by default, can be selected.

I recognize, however, that it may be difficult to change the style switcher without an overhaul of the entire theming system. hotdoc_bootstrap_theme is based on Bootstrap 3, and like bs3 uses LESS as its style backend. bs4 and bs5 made the switch from LESS to SASS, in part because it offers better support for modern CSS techniques.

The state of the art for style-selection today is to include all styles for all themes directly in the CSS sent to the client, style content using CSS variables, and allow the definitions for those variables to be modified locally by theme selection.

SASS makes this simple, with support for @mixin style definitions and downstream @include reuse of those definitions, including CSS variables. For example, a site might use the following SASS to implement a simple, switchable white-on-black vs. black-on-white theme set that includes automatic support for browser prefers-color-scheme preferences as well as manual switching:

@mixin light-theme {
  --body-text: #000;
  --page-bg: #fff;
}

@mixin dark-theme {
  --body-text: #fff;
  --page-bg: #000;
}

.dark {
  @include dark-theme;
}

.light {
  @include light-theme;
}

:root:not(.light):not(.dark) {
  @media (prefers-color-scheme: light) {
    @include light-theme;
  }

  @media (prefers-color-scheme: dark) {
    @include dark-theme;
  }
}

body {
  color: var(--body-text);
  background-color: var(--page-bg);
}

Selecting one theme or the other explicitly is a simple matter of setting a dark or light CSS class on the document <html> element. The "cascading" part of CSS does the rest.

LESS uses a very different model of variable-driven CSS, generating a separate style sheet for each theme, which complicates matters.

ferdnyc commented 1 year ago

an esoteric "alternate" stylesheet feature only officially supported in Firefox, and even then it isn't being used entirely correctly

Actually, maybe I'm wrong about that.

The MDN docs say "There can only be one preferred stylesheet", seeming to imply that only a single <link rel="stylesheet" title="…"> document can be preferred.

But they don't actually say that, nor do they say anything about multiple stylesheets with the same title.

So, perhaps what they really mean is, "Only one stylesheet title can be selected as preferred". That would actually fit better with the remainder of the sentence, "so providing stylesheets with different title attributes will cause some of them to be ignored."

ferdnyc commented 1 year ago

(Regardless, class-driven variable redefinition still beats the pants off swapping among multiple distinct stylesheet documents. From both the performance and UX perspective.)

MathieuDuponchelle commented 1 year ago

@ferdnyc to be honest this project is pretty much in maintenance mode on my end, I will add features here and there but I don't expect to do any major overhaul of the theming system, which is janky in its own right.

Re alternate stylesheets, I'm pretty sure I used them correctly, I liked that I used a "standard" solution though chrome not actually supporting it kind of ruins the party :)

In any case if you are looking to perform such an overhaul yourself be my guest, but you will probably find that integration with hotdoc is a tad complex and also worth refactoring, and at that point you might as well start a new documentation system from scratch.