无闪烁的黑暗模式在11th中带有尾风CSS
#javascript #html #网络开发人员 #教程

几天前,我正从头开始重建我的投资组合网站。然后,作为典型的Web开发人员,我偶然发现了我应该在静态两页网站上使用哪个框架的问题。我以为要进行全栈框架会过大(例如Next.js,Gatsby等),因此我的选择仅限于某些静态Web生成器。由于我不熟悉Ruby和Go基于Jekyll和Hugo之类的SSG,所以我已经定居了110。

但是问题不止于此,因为稍后,我在尝试实现黑暗模式时面临着一个烦人的错误。因此,每当我尝试以黑暗模式重新加载页面时,它总是会闪烁。我认为原因是一个静态渲染的页面和客户端的黑暗模式实现,但事实证明,这比这更简单:)

好吧,这就是故事的结局。现在,让我们进入教程。 ð

不用担心,本教程应该适用于任何SSG(静态站点生成器)生成的网站,常规静态HTML,甚至是服务器渲染的一个

安装

创建一个带有项目名称的文件夹:

mkdir project-name && cd project-name

一旦在文件夹中启动节点项目,并以dev依赖关系安装11ty软件包:

npm init -y
npm install -D @11ty/eleventy

本质上,11ty是一个CLI工具,因此您可以在全球安装它并在任何地方使用它。但是,为了进行良好的封装练习,我更喜欢将其安装在可以利用它的项目中

将tailwind软件包添加为dev依赖项&init生成tailwind.config.jspostcss.config.js文件:

npm install -D tailwindcss postcss autoprefixer

安装了所有必要的软件包后,现在该设置

设置

在文件夹根中创建.eleventy.js配置文件,然后将此摘要复制到文件中:

module.exports = function(eleventyConfig) {
  // Return your Object options:
  return {
    dir: {
      input: "src",
      output: "_dist"
    }
  }
};
  • input是11Ty从模板生成HTML的入口点,默认情况下它等于Project Folder root。因此,如果定义src,它将寻找一个名为src的文件夹,并在内部处理所有模板
  • output是最终处理模板将写入
  • 的文件夹

更新package.json脚本以看起来像:

"scripts": {
    "start": "npm-run-all --parallel dev:*",
    "build": "run-s build:*",
    "dev:11ty": "eleventy --serve",
    "dev:css": "tailwindcss -i src/assets/css/main.css -o _dist/assets/css/main.css --watch --postcss",
    "build:11ty": "eleventy",
    "build:css": "tailwindcss -i src/assets/css/main.css -o _dist/assets/css/main.css --minify --postcss"
  }

由于NPM默认没有并行脚本执行,因此我们需要安装额外的软件包,以称为npm-run-all

npm-run-all安装为dev依赖性:

npm install -D npm-run-all

现在您可以执行这两个脚本:

"start": "npm-run-all --parallel dev:*",
"build": "run-s build:*",

run-s呢?不用担心,它默认来自npm-run-all,它的作用是顺序执行脚本,而不是并行执行,我们不需要为构建生产版本而做。

在设置了所有必要的脚本和配置之后,现在我们要编写简单的暗模式逻辑。

首先,创建一个src文件夹并在内部制作index.njk模板文件,将此基本摘要复制到文件中:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <script>
      if (
        localStorage.getItem('color-theme') === 'dark' ||
        (!('color-theme' in localStorage) &&
          window.matchMedia('(prefers-color-scheme: dark)').matches)
      ) {
        document.documentElement.classList.add('dark');
      } else {
        document.documentElement.classList.remove('dark');
      }
    </script>

    <link rel="stylesheet" href={{
      '/assets/css/main.css' | url
    }}
    type="text/css" />

    <title>Dark Mode in 11ty</title>
  </head>
  <body class="bg-white dark:bg-knight">
    <div>
      hello from index
    </div>
  </body>
</html>

注意如何在头上导入样式表,但是我们实际上没有CSS文件,现在是时候在src/assets/css中创建一个名为main.css(您可以将CSS文件放在您喜欢的任何地方在分类的文件夹中,例如assets/css

现在将此摘要复制到main.css

@tailwind base;
@tailwind components;
@tailwind utilities;

也不要忘记设置尾风配置,以便尾风编译器可以搜索所有使用的类并将其转换为常规CSS,现在将此片段复制到tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./src/**/*.{njk,md}', './src/**/*.svg'],
  darkMode: 'class',
  theme: {},
  plugins: [],
};
  • content是尾风编译器查找的路径
  • darkMode是用于尾风的暗模式方法,它具有两种类型的classmedia。我们在这里使用class,因为是最灵活的一个

好吧,现在创建一个名为bundle.js的文件或您在src/js文件夹中喜欢的任何内容,然后复制此片段:

const THEME_KEY = 'color-theme';
const toggleButton = document.querySelector('#dark-mode-toggle');
const docEl = document.documentElement;

toggleButton.addEventListener('click', function () {
  if (localStorage.getItem(THEME_KEY)) {
    if (localStorage.getItem(THEME_KEY) === 'light') {
      docEl.classList.add('dark');
      localStorage.setItem(THEME_KEY, 'dark');
    } else {
      docEl.classList.remove('dark');
      localStorage.setItem(THEME_KEY, 'light');
    }

    // if NOT set via local storage previously
  } else {
    if (docEl.classList.contains('dark')) {
      docEl.classList.remove('dark');
      localStorage.setItem(THEME_KEY, 'light');
    } else {
      docEl.classList.add('dark');
      localStorage.setItem(THEME_KEY, 'dark');
    }
  }
});

然后,在index.njk中的</body>标签之前添加此代码:

<script type="module" src="/js/bundle.js"></script>

现在,返回src中的index.njk文件,然后写下这样的东西:

<body class="bg-white dark:bg-knight">
  <div>
    Hello from index
      <button id="dark-mode-toggle" class="-mt-1" aria-label="dark-mode-button">
       <p class="dark:hidden">Dark</p>
       <p class="hidden dark:inline">Light</p>
      </button>
  </div>
</body>

确保按钮ID等于QuerySelector中的按钮ID,在这种情况下为dark-mode-toggle

有些人想直接从JavaScript中切换到切换按钮内的深色/灯光图标或文本,但是我在这里使用dark:伪级本身是非常常规但非常有效和简单的方法。

最后,不要忘记将所有未经处理的文件传递到_dist文件夹,因为只有110个仅处理模板文件,例如nunjucks(.njk),liquid(.liquid),等等。

将此摘要写入.eleventy.js

module.exports = function (eleventyConfig) {

// we're copying the bundle.js to _dist/js since is not proccessed
 eleventyConfig.addPassthroughCopy({ 'src/js/bundle.js': 'js/bundle.js' })

/*
* but we don't need to copy the CSS because it has already been 
* processed by the Tailwind, you can see the scripts in package.json
* and how they instruct the compiler to output it into the 
* _dist/assets/css folder.
*/

// you can copy the rest of unprocessed file here

  return {
     dir: {
       input: 'src',
       output: '_dist',
       data: '_data',
       includes: '_includes',
       layouts: '_layouts',
     },
  };
};

完成上面的所有步骤后,在项目目录中运行NPM运行启动命令,转到Localhost:8080,测试Toggle按钮和VOILã,您现在应该在静态上具有无闪烁的黑暗模式使用Tailwind CSS和Vanilla JavaScript的站点。

概括

  • 这是什么解决方案?为什么黑暗模式不再闪烁了?好吧,原因很简单。 <head>中的此内联脚本是构造障碍物,并在请求后立即运行,并且由于没有“ async”或“ defer”关键字。从下载和执行此脚本开始的所有内容都将阻止HTML渲染,因此,没有发生FOUC(未风格的内容)。
  <script>
      if (
        localStorage.getItem('color-theme') === 'dark' ||
        (!('color-theme' in localStorage) &&
          window.matchMedia('(prefers-color-scheme: dark)').matches)
      ) {
        document.documentElement.classList.add('dark');
      } else {
        document.documentElement.classList.remove('dark');
      }
    </script>

您可能想将此脚本放在任何其他渲染障碍资产之上,例如CSS样式表链接和第三方CDN字体。

  • 您可以在此处阅读完整的110文档:https://www.11ty.dev/docs/
  • 今天就这样。我希望您喜欢本教程,如果您想纠正或添加某些内容,请在下面发表评论。