DOM 背景颜色传播闪烁继承 Google 中的初始背景颜色 Chrome 使用主题切换来重载主体背景颜色

DOM Background color propagation flickering inheriting initial bg color in Google Chrome using theme toggle to overload body bg color

我目前正在为我的网站开发一个主题切换器,它使用 Javascript / jQuery 来使用 lightmode()/ darkmode() 函数来操纵 Body.bg 颜色由一个按钮切换。我想要做的是在具有淡入和淡出的主体背景色之间创建无缝 t运行 定位。我已经制作并创建了它,但问题是当主题读取存储类型时,它将在 Chrome 和 Chrome Canary 中快速 blink 但在 Safari 和 Safari Tech Preview 中Catalina 它可以无缝运行。

但是,当用户切换到白色然后单击导航 link 然后导致黑暗模式的黑色 blink 时,我一直 运行 遇到问题主题。我的网站开始时启用了暗模式,body bg = #0a0a0a,但是当它切换到白色并更新存储时,它仍然继承了黑色 body - bg 最初在我的主题的 style.less 中设置。

如果我删除背景颜色,那么在深色模式主题上会出现白色闪烁,理想情况下,我的最终目标是创建无缝页面导航,而无需页面 blinking 快速阅读正文加载前的初始背景颜色 - 白色背景上的白色,黑色背景上的黑色没有 blink 导致视觉中断。

我已经尝试了所有我能想到的解决方法,但找不到解决方案。它在没有页面 blinking 的 Safari 中工作,但在 Chrome 中它仍然是 blinks。我已经包含了视频 links,展示了我想用 Google chrome 的 Safari 渲染器和 main.js 代码文件完成什么。

Safari - 无缝 运行sitioning

Chrome 和 Chrome Canary - 关注白色 t运行 上的 blink。它很快但非常令人沮丧。

所以这是怎么回事?!问题是主题现在设置为白色,但 style.less 主题中的初始 body - bg 颜色是黑色,它会在快速返回白色主题之前快速选择它。

当我在 Canary 中审核站点时,运行 它在慢速 3G 模拟没有 blink,但是当它 运行 正常或在审核中以快速 3G blink 发生。我的假设是在加载正文之前在正文上设置超时,但我尝试将其作为解决方法并仍然得到 blinking。

我已经尝试创建存储在本地存储中的密钥用于我的存储,并暂停正文加载,但到目前为止我找不到解决这个问题的方法:/

所以我想做的是在没有 blinking 的情况下,根据主题颜色基色阻止主体背景颜色闪烁白色或黑色。

感谢您花时间阅读我的问题!

document.addEventListener("DOMContentLoaded", function() {
document.body.style.backgroundColor = "inherit";

if (document.readyState === 'complete') {

if(lightmodeON == true) {
  $('body').css({background: "#FFF"});
  console.log('loading white bg');
}

if(lightmodeON == false) {
  $('body').css({background: "#0a0a0a"});
  console.log('loading black bg');
}
}


if (typeof (Storage) !=="undefined") {
if (localStorage.themepref == 1 ) {
  lightmode();
}
else {
  darkmode();
  localStorage.themepref = 2;
}

if(lightmodeON == true) {
  $('body').css({background: "#FFF"});
  console.log('loading fffwhite bg');
}

if(lightmodeON == false) {
  $('body').css({background: "#0a0a0a"});
  console.log('loading black bg');
}
}

这是我尝试变通的版本。

var clickDelay = false;
var themeType = -1;
var lightmodeON = false;


window.onload = function() {
  console.log('First');

  if (event.target.readyState === 'interactive') {

      $('body').css({ background: ''});
      document.body.style.backgroundColor = "inherit";

   if(lightmodeON == true) {
     $('body').css({background: "#FFF"});
       document.body.style.backgroundColor = "#FFF";
   }

   if(lightmodeON == false) {
     $('body').css({background: "#0a0a0a"});
       document.body.style.backgroundColor = "#0a0a0a";
   }
}
    overloadBG();
};


document.addEventListener("DOMContentLoaded", function() {
  document.body.style.backgroundColor = "inherit";

  if (document.readyState === 'complete') {

    if(lightmodeON == true) {
      $('body').css({background: "#FFF"});
      console.log('loading white bg');
    }

    if(lightmodeON == false) {
      $('body').css({background: "#0a0a0a"});
      console.log('loading black bg');
    }
  }


  if (typeof (Storage) !=="undefined") {
    if (localStorage.themepref == 1 ) {
      lightmode();
    }
    else {
      darkmode();
      localStorage.themepref = 2;
    }

    if(lightmodeON == true) {
      $('body').css({background: "#FFF"});
      console.log('loading fffwhite bg');
    }

    if(lightmodeON == false) {
      $('body').css({background: "#0a0a0a"});
      console.log('loading black bg');
    }
  }



});

window.addEventListener('beforeunload', function (e) {
  $('body').css({ background: ''});

  if(lightmodeON == true) {
    $('body').css({background: "#FFF"});
      document.body.style.backgroundColor = "#FFF";
  }

  if(lightmodeON == false) {
    $('body').css({background: "#0a0a0a"});
      document.body.style.backgroundColor = "#0a0a0a";
  }

  document.body.style.backgroundColor = "inherit";
  overloadBG();
  
});

window.onbeforeunload = function () {
  //FUCK YOU BLINK
  //$('body').css({ background: 'none'});
  $('body').css({ background: ''});
    document.body.style.backgroundColor = "";

  if (typeof (Storage) !=="undefined") {
    if (localStorage.themepref == 1 ) {
        localStorage.themepref = 1;
        lightmode();
    }
    else {
      darkmode();
      localStorage.themepref = 2;
    }
  }

}

document.onreadystatechange = function() {


    $('body').css({ background: ''});
    document.body.style.backgroundColor = "transparent";

    if (event.target.readyState === 'interactive') {
        console.log('interactive');

             if(lightmodeON === true) {
               $('body').css({background: "#FFF"});
             }

             if(lightmodeON === false) {
               $('body').css({background: "#0a0a0a"});
             }
      }

      if (event.target.readyState === 'loading') {

          $('body').css({ background: ''});

       if(lightmodeON == true) {
         $('body').css({background: "#FFF"});
         $("body").css("cssText", "background: #FFF !important;");
       }

       if(lightmodeON == false) {
         $('body').css({background: "#0a0a0a"});
         $("body").css("cssText", "background: #0a0a0a !important;");
       }
    }

当 DOMContentLoaded 触发时,浏览器可能已经绘制了您页面的背景。

这是一个无限期重新加载页面的演示,一定要在看完后点击"hide results",它可能会使您的计算机使用一些CPU资源(但没有网络资源)。

/* 
  We use an iframe to avoid making real network requests 
  Below is the HTML content of this iframe
*/

const content = `<!DOCTYPE html>
<html>
  <head>
    <style>
      /* default bg color */
      body { background: red; }
    </style>
    <script>
      document.addEventListener('DOMContentLoaded', e => {
        document.body.style.backgroundColor = 'green';
        location.reload() // infinite reload...
      });
    <\/script>
  </head>
  <body>
    <div>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi blandit cursus orci ut maximus. Phasellus pharetra lobortis pellentesque. Pellentesque et lacus et lorem facilisis ultrices. Maecenas sed ultricies nisi. Suspendisse feugiat finibus justo, id consectetur turpis aliquam ac. Proin sit amet laoreet velit. Nullam felis lectus, commodo imperdiet mollis in, ullamcorper eget tortor. Nullam at metus non diam faucibus aliquam. Vestibulum eu maximus risus, vitae elementum justo. Fusce commodo lacus a augue lobortis, quis ornare odio gravida. Quisque ultrices tempus tellus, vitae pulvinar est rutrum in. Duis ante erat, placerat sit amet imperdiet vitae, facilisis non mauris. Integer eu ex sapien.</p>
      <p>Morbi porttitor justo eu sodales efficitur. Integer ut suscipit libero, sed dapibus velit. Vestibulum laoreet neque ac odio consequat, a suscipit arcu tristique. Curabitur tempor, nisl eu porttitor feugiat, nibh lorem laoreet massa, ut porta tellus augue accumsan metus. Suspendisse sed venenatis neque. Aliquam non justo in tortor dictum suscipit. Duis eu lectus eu dui placerat luctus. Etiam et volutpat diam, nec ullamcorper tellus. Nullam nibh dui, bibendum a ipsum et, elementum tempor mi. Maecenas ut eros eu sem malesuada tincidunt. Aenean fermentum sit amet augue quis vulputate. Vivamus commodo pellentesque purus rhoncus suscipit. Proin et enim vel ipsum vulputate mollis venenatis ut enim. Curabitur eget velit mollis, luctus sem at, aliquam est. Donec quis elit erat. Nullam facilisis lorem nisl, a luctus purus tristique vel.</p>
      <p>Donec in magna at ante mollis sodales ac vitae mauris. Aliquam condimentum ligula nulla, scelerisque cursus neque consequat quis. Fusce vestibulum nisi vitae ipsum venenatis, a pharetra diam tempus. Aenean maximus enim orci, quis mollis neque sollicitudin et. Quisque viverra ipsum vitae magna varius, id ornare justo dictum. Quisque eleifend magna ac congue dignissim. Duis eu volutpat quam, quis placerat tellus. Pellentesque felis mi, imperdiet eu semper vel, hendrerit sit amet ex.</p>
    </div>
  </body>
</html>
`;
frame.src = URL.createObjectURL(new Blob([content], {type: 'text/html'}));
<iframe id="frame" widht="500" height="500"></iframe>

要解决此问题,请将您的脚本移动到 <body> 的顶部,并尽快从存储 中设置初始 <body> 颜色
在附加其他事件之前,您仍然可以等待文档准备就绪。

/* 
  We use an iframe to avoid making real network requests 
  Below is the HTML content of this iframe
*/

const content = `<!DOCTYPE html>
<html>
  <head>
    <style>
      /* default bg color */
      body { background: red; }
    </style>
  </head>
  <body>
    <!-- move inside <body> -->
    <script>
      // first retrieve from Storage
      // const lightModeOn = locaStorage.getItem('lightmode') === "1";
      // StackSnippets don't allow Storage...
      const lightModeOn = true;
      // set directly the body's style, we're in so we don't need to wait, it's already available
      document.body.style.backgroundColor = 'green';
      // then wait for DOMContentLoaded if you wish to add listeners to other events
      document.addEventListener('DOMContentLoaded', e => {
      // $('.toggle').on('input', switchLight);

      // just to demonstrate it works
      location.reload();
   });
      
    <\/script>

    <div>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi blandit cursus orci ut maximus. Phasellus pharetra lobortis pellentesque. Pellentesque et lacus et lorem facilisis ultrices. Maecenas sed ultricies nisi. Suspendisse feugiat finibus justo, id consectetur turpis aliquam ac. Proin sit amet laoreet velit. Nullam felis lectus, commodo imperdiet mollis in, ullamcorper eget tortor. Nullam at metus non diam faucibus aliquam. Vestibulum eu maximus risus, vitae elementum justo. Fusce commodo lacus a augue lobortis, quis ornare odio gravida. Quisque ultrices tempus tellus, vitae pulvinar est rutrum in. Duis ante erat, placerat sit amet imperdiet vitae, facilisis non mauris. Integer eu ex sapien.</p>
      <p>Morbi porttitor justo eu sodales efficitur. Integer ut suscipit libero, sed dapibus velit. Vestibulum laoreet neque ac odio consequat, a suscipit arcu tristique. Curabitur tempor, nisl eu porttitor feugiat, nibh lorem laoreet massa, ut porta tellus augue accumsan metus. Suspendisse sed venenatis neque. Aliquam non justo in tortor dictum suscipit. Duis eu lectus eu dui placerat luctus. Etiam et volutpat diam, nec ullamcorper tellus. Nullam nibh dui, bibendum a ipsum et, elementum tempor mi. Maecenas ut eros eu sem malesuada tincidunt. Aenean fermentum sit amet augue quis vulputate. Vivamus commodo pellentesque purus rhoncus suscipit. Proin et enim vel ipsum vulputate mollis venenatis ut enim. Curabitur eget velit mollis, luctus sem at, aliquam est. Donec quis elit erat. Nullam facilisis lorem nisl, a luctus purus tristique vel.</p>
      <p>Donec in magna at ante mollis sodales ac vitae mauris. Aliquam condimentum ligula nulla, scelerisque cursus neque consequat quis. Fusce vestibulum nisi vitae ipsum venenatis, a pharetra diam tempus. Aenean maximus enim orci, quis mollis neque sollicitudin et. Quisque viverra ipsum vitae magna varius, id ornare justo dictum. Quisque eleifend magna ac congue dignissim. Duis eu volutpat quam, quis placerat tellus. Pellentesque felis mi, imperdiet eu semper vel, hendrerit sit amet ex.</p>
    </div>
  </body>
</html>
`;
frame.src = URL.createObjectURL(new Blob([content], {type: 'text/html'}));
<iframe id="frame" widht="500" height="500"></iframe>

<html>
<head>
    <title></title>
    <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<header>
    <nav class="menu">
        <label for="darkmode"><input type="radio" name="theme" value="1" id="darkmode" class="themechange" />Dark Mode</label>
        <label for="lightmode"><input type="radio" checked="checked" name="theme" value="0" class="themechange" id="lightmode" />Light Mode</label>
    </nav>
</header>
<div class="content">
    <p>CSS (Cascading Style Sheets) is a representation style sheet language used for describing the look and formatting of HTML (Hyper Text Markup Language), XML (Extensible Markup Language) documents and SVG elements including (but not limited to) colors, layout, fonts, and animations. It also describes how elements should be rendered on screen, on paper, in speech, or on other media.</p>
    <img src="https://farm8.staticflickr.com/7632/16990947835_3894284fd8_b.jpg">

    <p>CSS (Cascading Style Sheets) is a representation style sheet language used for describing the look and formatting of HTML (Hyper Text Markup Language), XML (Extensible Markup Language) documents and SVG elements including (but not limited to) colors, layout, fonts, and animations. It also describes how elements should be rendered on screen, on paper, in speech, or on other media.</p>


    <p>CSS (Cascading Style Sheets) is a representation style sheet language used for describing the look and formatting of HTML (Hyper Text Markup Language), XML (Extensible Markup Language) documents and SVG elements including (but not limited to) colors, layout, fonts, and animations. It also describes how elements should be rendered on screen, on paper, in speech, or on other media.</p>
</div>
<style>
nav{background:#ddd; height:40px;}
img{width:350px}
body{margin:0px; padding:0px; color:#111; transition:all 0.5s;}
body.dark{color:#fff; background:#000;}
body.dark nav{background:#cc0000;transition:all 0.5s;}
</style>




<script>
$(function(){
    $("#lightmode").click(function(){
            $("body").removeClass("dark");
    })
    $("#darkmode").click(function(){
            $("body").addClass("dark");
    })
})
</script>
</body>
</html>

切换主题选择上的class名称并在css代码中添加transition:all 0.5s以使过渡平滑。

以下是我建议的快速解决方案:我首先从 CSS 中删除背景色 属性,并从导致此冲突 属性 渲染的元素中全部删除.

然后,在我的JS文件中添加一个函数,根据主题检查访问者设置的状态,并直接从JS应用背景。

if(lightmodeON == true) {
  $('body').css({background: "#FFF"});
  console.log('loading white bg');
}

if(lightmodeON == false) {
  $('body').css({background: "#0a0a0a"});
  console.log('loading black bg');
}
}

并且可能在 PHP 代码中包含后备(在你发布在 jsfiddle 上的示例中,我看到你在 PHP 中编码)以防 javascript 是 disabled/not 在访问者的浏览器中支持并回显 CSS 代码, 在标签之后,而不是在 之前,因为浏览器和 DOM 模型充当提示 sheet 的命令,不像面向对象的代码,它总是从上到下加载。所以加载层次会影响事情的工作方式,有时可能会与你想要实现的目标发生冲突:

<script src="yourScriptHere.js">
//Some parameters if needed (Such as state of theme preference retrieved from the session and passed into a variable). For the sake of this example:
var lightmodeON = <?php echo $_SESSION('themePreference');?>;
</script>
<style>/*Then your style here*/</style>
<!--OR-->
<link href="yourStyleSheets.css" rel="stylesheet" />

如果 属性 与您完成的产品发生冲突,则没有理由将 CSS 包含在 CSS 中。但请始终确保在 CSS 文件中添加注释,以便稍后查看您已排除 属性 以及将其放置在何处,以免在以后的编辑中受到影响,例如:

body {
    /* background-color property is set in JS file and excluded from CSS */
    margin: 0;
    [...]
}

我假设在这种情况下从 CSS 中排除一些东西不会有什么坏处,因为看起来您将在这里使用 HTML/CSS/JS 作为一个完整的应用程序包来确保完整的功能。

除此之外,您还可以尝试在 CSS 文件中使用 background-visibility 属性 来处理出现闪烁的元素,因为这有时会奇怪地帮助解决一些闪烁问题问题。

我还建议您创建一个 Ajax 调用并将主题首选项设置存储在会话对象中,这样您就可以通过 JS 在其他页面中传递并访问它,and/or访问者在关闭浏览器后返回站点 window。

希望对您有所帮助。干杯!