CSS 変数に基づくテーマ切り替えに最適なソリューション (推奨)

CSS 変数に基づくテーマ切り替えに最適なソリューション (推奨)

この要件を受け取ったとき、Baidu は、CSS リンクの置き換え、className の変更、less.modifyVars、css in js など、業界でテーマを切り替えるための多くのソリューションを見つけましたが、どのソリューションも面倒で高価に思えました。コードの侵入が少なく、使いやすく、保守しやすいソリューションはありますか?もちろんあります。より正確に言うと、CSS 自体がそれをサポートしています。

CSS3 変数

グローバル カラー変数を定義します。この変数の値を変更すると、ページ内でこの変数を参照するすべての要素が変更されます。とてもシンプルですね。

// ベース.less
:根 {
  --プライマリ: 緑;
  --警告: 黄色;
  --情報: 白;
  --危険: 赤;
}

// var.less
@プライマリ: var(--プライマリ)
@危険: var(--危険)
@info: var(--info)

// ページなし
.ヘッダー{
  背景色: @primary;
  色: @info;
}
。コンテンツ {
  境界線: 1px 実線 @danger;
}
//変更.js
関数 changeTheme(themeObj) {
  const vars = Object.keys(themeObj).map(key => `--${key}:${themeObj[key]}`).join(';')
  document.documentElement.setAttribute('style', vars)
}

この記事の終わり

くそ、 IEをサポートしていない! ! 2020 年でも IE と互換性がありますか?はい、IE と互換性がある必要があります。

CSS 変数 ポニーフィル

はい、IE と互換性のあるポリフィルがあります: css-vars-ponyfill。 IEの扱い方

+-------------------------+
| ページ内のスタイル タグのコンテンツを取得します |
| 外部リンク CSS コンテンツをリクエスト |
+-------------------------+
|
|

+-------------------------+ はい +-------------------------+
| コンテンツに var() が含まれていますか | ----> | src としてマークされています |
+-------------------------+ +--------------------------+
| |
| いいえ |
ううう
+-------------------------+ +--------------------------+
| スキップとしてマーク | | var(*) を変数値に置き換えます |
| | | ヘッドに新しいスタイル タグを追加します |
+-------------------------+ +--------------------------+

効果はおそらくこんな感じです

シンプルで粗雑ですがエレガントです。CSS 変数をサポートするブラウザでは処理されないため、パフォーマンスの問題を心配する必要はありません (これは IE の問題であり、私の問題ではありません)

)。 コードを変更してみましょう

//ストア/テーマ.js
'css-vars-ponyfill' から cssVars をインポートします

エクスポートデフォルト{
  州: {
    「プライマリ」:「緑」、
    「危険」:「白」
  },
  突然変異:
    UPDATE_THEME(状態、ペイロード) {
      定数変数 = {}
      オブジェクト.assign(状態、ペイロード)
      Object.keys(state).forEach((キー) => {
        変数[`--${key}`] = 状態[key]
      })
      cssVars({
        変数
      })
    }
  },
  アクション: {
    テーマを変更する({コミット}, テーマ = {}) {
      コミット('UPDATE_THEME', テーマ)
    }
  }
}

// ルータ.js
// ルートジャンプ後のページでは、必要に応じて新しい CSS リソースが読み込まれるため、再変換します。const convertedPages = new Set()
router.afterEach((to) => {
  if (convertedPages.has(to.path)) 戻り値
  変換されたページをパスに追加します
  context.store.dispatch('theme/changeTheme')
})

SSR プロジェクト フラッシュ スクリーンの問題の最適化

SSRプロジェクトでは、上記の解決策を使用してIEでこれが表示される場合があります。

css-vars-ponyfill

変換を実現するために DOM 要素に依存しており、ノードでは使用できません。そのため、変換されていない CSS コードを直接出力するサーバーと、JS ファイルをロードして CSS を変換するクライアントとの間にスタイルのギャップが生じます。

+- - - - - - - - - - - - - - - - - - - - - - - - +
「スタイルウィンドウ期間:」
' '
+----------+ ' +----------------+ +-------------+ ' +-------------+
| リクエストを開始 | --> ' | SSR 直接出力ページ | --> | js 依存関係をロード | ' --> | css 変数を置き換え |
+----------+ ' +----------------+ +-------------+ ' +-------------+
' '
+- - - - - - - - - - - - - - - - - - - - - - - - +

この問題の解決方法も非常に簡単です。CSS css var使用されている各場所に互換性のある記述方法を追加するだけです。

@_primary: 赤
@プライマリ: var(--プライマリ)

:根{
  --プライマリ: @_プライマリ
}

。テーマ {
  色: @primary;
}

//.themeに変更{
  色: @_primary;
  色: @primary;
}

CSS 変数をサポートしていないブラウザでは、デフォルトの色のredがレンダリングされ、js が読み込まれた後に ponyfill がスタイル オーバーライドを置き換えます。

Webpackプラグイン開発

各箇所に互換性のある記述を手動で追加するのは面倒で、メンテナンスも困難です。このとき、webpack のライフサイクルとプラグイン開発に関する知識を理解する必要があります。webpack プラグインを手動で記述し、 normalModuleLoader (バージョン 5 は非推奨です。NormalModule.getCompilationHooks(compilation).loader を使用してください) のフックですべての CSS モジュールにローダーを追加して、互換性のあるコードを処理できます。

著者のプロジェクトでは less を使用しています。webpack のローダーの実行順序はスタックの先入れ後出し順序に似ていることに注意してください。そのため、less 変数ではなくコンパイルされた CSS 変数の書き込みを処理するようにするには、less ローダーの前に変換ローダーを追加する必要があります。

// プラグイン.js
デフォルトクラス HackCss をエクスポートします。
  コンストラクタ (テーマ = {}) {
    this.themeVars = テーマ
  }

  適用(コンパイラ) {
        コンパイラー.フック.thisCompilation.tap('HackCss', (コンパイル) => {
          コンパイル.フック.normalModuleLoader.tap(
            「ハックCSS」、
            (_, モジュールコンテキスト) => {
              /\.vue\?vue&type=style/.test(moduleContext.userRequest) の場合 {
                // ssr プロジェクトの同型性には 2 つのコンパイラがあります。モジュールにローダーがある場合は追加されません if (hasLoader(moduleContext.loaders, 'hackcss-loader.js')) {
                  戻る
                }

                lessLoaderIndex = 0 とします
                // プロジェクトでは less を使用しているため、less-loader の場所を見つけます。moduleContext.loaders.forEach((loader, index) => {
                  (/less-loader/.test(loader.loader)) の場合 {
                    lessLoaderIndex = インデックス
                  }
                })
  
                moduleContext.loaders.splice(lessLoaderIndex, 0, {
                  ローダー: path.resolve(__dirname, 'hackcss-loader.js'),
                  オプション: this.themeVars
                })
              }
            }
          )
        })
      }
    })
}

// ローダー.js
const { getOptions } = require('loader-utils')

module.exports = function(ソース) {
  if (/module\.exports/.test(source)) ソースを返す
  const theme = getOptions(this) || {}
  ソースを返す.replace(
    /\n(.+)?var\(--(.+)?\)(.+)?;/g,
    (コンテンツ、前、名前、後 = '') => {
      const [キー、インデント] = before.split(':')
      定数add = after.split(';')[0]
      `\n${key}:${indent}${theme[name]}${after}${add};${content}` を返します
    }
  )
}

この時点で、テーマを楽しく自由に切り替えることができます。

追記

「コードを書くのが面倒」になる方法を学ぶことで、新しい知識を吸収する方が面白いです。この記事がお役に立てば幸いです。

CSS 変数に基づくテーマ切り替えの完璧なソリューション (推奨) に関するこの記事はこれで終わりです。CSS 変数テーマ切り替えに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

<<:  Iframe の使用を減らすべきいくつかの理由の分析

>>:  HTMLでのラジオ値の取得、割り当て、登録の詳細な説明

推薦する

CSS画像結合技術(スプライト画像)の詳しい説明

CSS画像結合技術1. 画像のステッチ画像ステッチング技術は、個々の画像を収集する技術です。画像の多...

Linux(中心OS7)は、Java Webプロジェクトの実行環境を構築するためにJDK、Tomcat、MySQLをインストールします。

1. JDKをインストールする1. 古いバージョンまたはシステム独自のJDKをアンインストールする...

この記事では、jsのデータ型とデータ構造の世界を紹介します。

目次1. 動的型付けとは何ですか? 2. データ型2.1 プリミティブ型 (6 つのプリミティブ型、...

完全なショッピングカートを実装するためのミニプログラム

ミニプログラムは、参考までに完全なショッピングカート[すべて選択/選択解除して金額を計算/加算と減算...

docker に nacos をインストールしてデータベースを構成する詳細なチュートリアル

環境の準備 Docker環境 MySQL 5.7 (公式イメージはmysql8をサポートしていません...

Windows 10 での mysql5.5 データベース コマンドラインの中国語文字化け問題を解決する

システムをリセットした後、かなり前にインストールした MySQL データベースのコンソール クエリで...

MySQL 結合クエリ構文と例

接続クエリ:これは、2 つのクエリ (またはテーブル) の各行をペアで接続した結果です。つまり、1 ...

Vue3 コンポジション API の紹介

目次概要例なぜそれが必要なのでしょうか?設定参照、反応的計算して見るライフサイクルVue3.0 は ...

Excel をインポートするときに js で時間を変換する正しい方法について

目次1. 基本2. 問題の説明3. 解決策付録: js を使用して Excel の日付形式を変換する...

MySQL のインデックスとデータ テーブルを管理する方法

目次テーブルの競合を見つけて修正するインデックス統計の更新テーブルの競合を見つけて修正するデータ テ...

jQueryは動的タグイベントを実装します

この記事では、タグイベントを動的に追加するためのjQueryの具体的なコードを参考までに紹介します。...

MySQL 5.7.21 のインストールとパスワード設定のチュートリアル

MySQL5.7.21のインストールとパスワード設定のチュートリアルは次のとおりです。公式リファレン...

Windows でのシンプルな Mysql バックアップ BAT スクリプトの共有

序文この記事では、Windows で Mysql をバックアップするための簡単な BAT スクリプト...

CSS 動的高さ遷移アニメーション効果の実装

この質問は、Nuggets のメッセージから生まれました。友人が、次のコードの高さ遷移アニメーション...

Vueのカスタムディレクティブの詳細なガイド

目次1. カスタム指示とは何ですか? 2. 指示をカスタマイズする方法フック機能3. 応用シナリオ入...