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でのラジオ値の取得、割り当て、登録の詳細な説明

推薦する

https暗号化アクセス用にnginxを設定するための詳細なチュートリアル

環境: 1 CentOS Linux リリース 7.5.1804 (コア)ファイアウォールと sel...

ハイパーリンクを表示して開く方法

<br />インターネット上の無数の情報は基本的に HTML ドキュメントで構成されてお...

CSS プロパティ display:flow-root 宣言を 1 つの記事でマスターする

zhangxinxu より https://www.zhangxinxu.com/wordpress...

Web 上の要素を非表示にする方法とその利点と欠点

ソースコードの例: https://codepen.io/shadeed/pen/03caf6b36...

Echart Bar の 2 列チャート スタイルの最も完全な詳細な説明

目次序文インストールと設定1. Echartsをインストールする2. Echartsをグローバルに導...

Mysql5.7.14 インストールと設定方法操作グラフィックチュートリアル(パスワード問題解決)

この記事は主に、以前のインストール方法を使用して MySQL 5.7.14 をインストールするときに...

ウェブページで Enter キーを押すと自動的にフォームを送信し、他のページにジャンプするソリューション

ウェブページでEnterキーを押すと、フォームは自動的に送信され、他のページに移動します。クエリフォ...

W3Cチュートリアル(16):その他のW3Cの活動

このセクションでは、その他の重要かつ興味深い W3C アクティビティの概要を説明します。このセクショ...

インターフェーステストプラットフォームを構築するためのDjango+Vue+Dockerの詳細な説明

1. 冒頭の2つの単語みなさんこんにちは。私の名前はLin Zonglinです。私はテストエンジニア...

ブートストラップ学習体験のまとめ - CSS スタイル デザイン共有

プロジェクトのニーズにより、ブートストラップ フレームワークを慎重に学習する予定です。以前から少しは...

Linux で iostat コマンドを使用するチュートリアル

序文運用・保守を行う人がスキルを持っていなければ、サーバーを操作するのに恥ずかしさを感じてしまうと言...

Vue バインディング オブジェクト、配列データを動的にレンダリングできないケースの詳細な説明

プロジェクトシナリオ: Dark Horse Vueプロジェクト管理の実践、製品分類の取得、拡張バー...

Vueはユーザーログイン切り替えを実装します

この記事では、ユーザーのログイン切り替えを実現するためのVueの具体的なコードを例として紹介します。...

CentOS8でルートパスワードを素早く変更する方法

Centos8仮想マシンを起動し、上下キーを押して図1のインターフェースの最初の行を選択します。図1...

MySQL マスタースレーブレプリケーションの原理からインストールと設定までを包括的に解説します。

マスタースレーブレプリケーションがなぜ必要なのでしょうか? 1. 複雑な業務システムでは、SQL 文...