web-dev-qa-db-ja.com

ReactでLess + CSSモジュールを使用してテーマを切り替える

私のプロジェクトでは、CSS Modules with Lessを使用しています。つまり、両方の長所を利用しています。

私のsrcフォルダは次のようになります。

components/
    [all components]
theme/
    themes/
        lightTheme.less
        darkTheme.less
    palette.less

palette.less

@import './themes/lightTheme.less';

次に、テーマの色を使用するすべてのコンポーネントで、次のことを行います。

component.module.less

@import '../../theme/palette.less';

.element {
    background-color: @primary;
}

この構造により、palette.lessを編集して、使用するテーマをインポートできます。問題はユーザーが自分の好きなテーマを選択できるようにしたい自分で。テーマは実行時に切り替え可能である必要があります。つまり、どういうわけか両方のテーマをコンパイルする必要があります。


私はこのようなものになる完璧な解決策を想像します:

app.less

body {
    @theme: @light-theme;

    &.dark-theme {
        @theme: @dark-theme;
    }
}

そして、どういうわけか、この@theme変数をすべてのコンポーネントにインポートし、そこからプロパティを読み取ります(つまり、@theme[primary])。

残念ながら、スコープの少ない変数はこのように機能しません。


私はLessモジュールを使用するどんなソリューションにも心を開いています。

ありがとうございました!

7
Itay Ganor

Less/CSSモジュールを使用するソリューションを探していると思いますが、(Morpheusが質問にコメントしたように)css変数を使用するだけで状況を解決できる可能性が非常に高いです。

どのように機能しますか?

すべてのスタイリングでハードコードされた値を使用しないようにする必要があります。

.awesome-div {
  background-color: #fefefe;
}

あなたは:

:root {
  --awesome-color: #fefefe;
}

.awesome-div {
  background-color: var(--awesome-color);
}

明暗の切り替え

このアプローチでテーマを変更するには、2つの方法があります。

  • React内でバニラJsコードを使用して:root CSS要素を更新します。詳細については、これをチェックしてください codepen ;
  • すべての新しい:root変数を含むコンポーネントをそのcomponent.cssファイルにロードするだけです。

React(バニラCSSでも))で、.cssファイルで独自の:rootを宣言する複数のコンポーネント/要素を簡単に作成できます。

さらに、新しい:rootは、以前の:rootの競合する値を上書きします。たとえば、ファイルapp.cssに:root { --color: red; }があり、別のコンポーネント、たとえばコンポーネントAをロードする場合、component_a.cssで同じ変数が上書きされます。 :root { --color: blue; }ブラウザでレンダリングされたものは、コンポーネントAのものです。

このロジックに従うと、何も実行せず、まったくレンダリングしないダミーコンポーネントを作成できますが、代わりに、このcomponent.jsファイルで、テーマの.cssをインポートします。例:

import './light.css'; // suppose this is the light-theme dummy component

アプリでテーマを切り替えるときは、ダミーコンポーネントをシーンから削除して、他のコンポーネントを呼び出す必要があります。

そこにインポート/モジュールを含む例を提供するまで、私はコードペンにあまり慣れていませんが、上記の説明が私の意味を理解してくれることを願っています。それでも、ここで私が実証しようとしているものの簡単な疑似コードを示します。


loadTheme() {
  if (this.state.theme === 'dark') return <LightTheme />;
  if (this.state.theme === 'user-3232') return <UserTheme />;
  return <DarkTheme />;
}

render() {
  return (
    <App>
      {this.loadTheme()}
      <OtherContent>
    </App>
  );
}

2
Lukas Danin

スタイル付きコンポーネントを確認してください。

https://www.npmjs.com/package/styled-components

https://styled-components.com/docs/advanced#theming

私は自分のアプリでイースターエッグとして自分でやったので、きちんと機能することは確かです。残念ながらコードは公開されていないため、コードを公開することはできません。

0
xurei