quarto-dev / quarto-cli

Open-source scientific and technical publishing system built on Pandoc.
https://quarto.org
Other
3.87k stars 317 forks source link

Custom theme sass file for light mode unexpectedly applied to dark mode #3705

Open sun123zxy opened 1 year ago

sun123zxy commented 1 year ago

Bug description

I'm running quarto 1.2.269 on Windows, using sass files to customize HTML output. It seems that custom theme files for light mode are unexpectedly applied to dark mode.

For example, consider this qmd file:

---
title: Test
format:
  html:
    theme:
      light: [flatly, "custom.scss"]
      dark: [darkly]
---

and in custom.scss:

/*-- scss:rules --*/
body::after{
    content: "foo";
}

I expected to get "foo" in light mode only. However, after rendering, "foo" can be seen in both light and dark mode.

I guess this might have something to do with bootstrap.min.css and bootstrap-dark.min.css included in <head>, since both of them are applied in dark mode.

Apologize if I've missed something obvious. Thanks!

Checklist

dragonstyle commented 1 year ago

You are correct- when the alternate mode is applied, we retain the light stylesheet as well, applying the dark stylesheet as well. This means that situations like this issue are true. We would ultimately like to take a different approach with dark / light toggling which also does a better job minimizing any flash as users navigate between pages. I'm not 100% sure when we'll get to that, so leaving this open for the time being.

kv9898 commented 5 days ago

I notice the discussion on flickering for the dark mode (#5900) is relocated here. I noted that this problem has not been addressed for a year. Currently I'm using the following as a fix for my own website. If needed, I can transform this into a pull request, but I think maybe some discussion is good since I'm not entire sure the consequences of my fix. Currently I don't see any visible flickers in my website: https://rubuky.com/

Basically, the gist is to "hide" the content until the dark mode is fully loaded. To do this, we need to adjust _quarto.yml for the project to include:

format: 
  html:
    include-before-body: 
      - text: |
          <style>
            body {
              visibility: hidden; /* initially hidden until DOM ready to prevent flicker */
            }
          </style>

The change above "hides" the page content.

We then need to change

https://github.com/quarto-dev/quarto-cli/blob/252bc958e17384c5c473eca50090ee653995d361/src/resources/formats/html/templates/quarto-html.ejs#L190-L194

to

  // Switch to dark mode if need be
  if (hasAlternateSentinel()) {
    toggleColorMode(true);
  } else {
    toggleColorMode(false);
  }

  async function loadBodyWhenReady() {
      while (!document.body.classList.contains('quarto-light') && !document.body.classList.contains('quarto-dark')) {
        await new Promise(resolve => setTimeout(resolve, 50));
      }
      setTimeout(() => {
      document.body.style.visibility = "visible";
      }, 50); // Adjust the delay to allow for the dark mode to be loaded
  }
  loadBodyWhenReady();

This allows the content to be displayed only after the "invisible flicker" has occured, so that we "bypass" the flicker.