LoginSignup
5
5

More than 1 year has passed since last update.

Nuxt.js で Sass ( Scss ) 変数を TypeScript ( JavaScript ) からも使いたい

Last updated at Posted at 2021-09-19

Nuxt.js で開発していると、Sass ( Scss ) 変数を管理するファイルを作成し、@nuxtjs/style-resources ライブラリを使って、各コンポーネントから参照することが多いかと思います。

// @/assets/scss/_consts.scss

$COLOR_PRIMARY: #4aac00;
$COLOR_SECONDARY: #0f83fd;
<!-- @/components/Test.vue -->

<template>
  <div class="Test">
    <p class="Test_Text">Text1</p>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  name: 'Test'
})
</script>

<style lang="scss" scoped>
  .Test_Text {
    color: $COLOR_PRIMARY;
  }
</style>

こんな感じで。

この Sass ( Scss ) 変数を Vue コンポーネントの <template> 内や、<script> 内でも使いたい!
( JavaScript と CSS で変数を共有したい! )

手順

1、:export を定義する

// @/assets/scss/_consts.scss

$COLOR_PRIMARY: #4aac00;
$COLOR_SECONDARY: #0f83fd;

+ :export {
+   COLOR_PRIMARY: $COLOR_PRIMARY;
+   COLOR_SECONDARY: $COLOR_SECONDARY
+ }

:export で Vue コンポーネントから参照したい変数を定義する。

2、Vue コンポーネントで使う

<!-- @/components/Test.vue -->

<template>
  <div class="Test">
    <p class="Test_Text">Text1</p>
+   <p :style="styleObj">Text2</p>
+   <p :style="{ color: COLOR_SECONDARY }">Text3</p>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
+ import colorModule from '@/assets/scss/_consts.scss';
export default Vue.extend({
+ name: 'Test', // ←カンマ追加しただけ
+ data () {
+   return {
+     COLOR_SECONDARY: colorModule.COLOR_SECONDARY
+   }
+ },
+ computed: {
+   styleObj () {
+     return {
+       color: this.COLOR_SECONDARY
+     }
+   }
+ }
})
</script>

<style lang="scss" scoped>
  .Test_Text {
    color: $COLOR_PRIMARY;
  }
</style>

import colorModule from '@/assets/scss/_consts.scss'; で scss ファイルをインポートします。
そして、colorModule.COLOR_PRIMARYcolorModule.COLOR_SECONDARY とすることで、先ほど :export {} 内に定義した変数にアクセスできます。

3、エラーの解消

stylelint を使っている場合

stylelint を使っているプロジェクトであれば、このようなエラーが出ているのではないでしょうか?

assets/scss/_consts.scss
 5:1  ✖  Unexpected unknown pseudo-class selector ":export"   selector-pseudo-class-no-unknown
 6:3  ✖  Unexpected unknown property "COLOR_PRIMARY"          property-no-unknown             
 7:3  ✖  Unexpected unknown property "COLOR_SECONDARY"        property-no-unknown

これを解消するために、ルールを追加します。

// stylelint.config.js

module.exports = {
  extends: [
    'stylelint-config-standard',
    'stylelint-config-prettier'
  ],
  rules: {
    'selector-pseudo-class-no-unknown': [
      true,
      { 'ignorePseudoClasses': ['export'] }
    ],
    'property-no-unknown': [
      true,
      { 'ignoreProperties': ['/^COLOR_/'] }
    ]
  }
}

TypeScript を使っている場合

TypeScript を使っているプロジェクトであれば、このようなエラーが出ているのではないでしょうか?

 ERROR  ERROR in components/Test.vue:12:25                                                                                                                                                        12:35:18
TS2307: Cannot find module '@/assets/scss/_consts.scss' or its corresponding type declarations.
    10 | <script lang="ts">
    11 | import Vue from 'vue'
  > 12 | import colorModule from '@/assets/scss/_consts.scss';
       |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    13 | export default Vue.extend({
    14 |   name: 'Test',
    15 |   data () {

これを解消するために、型定義ファイルを作成します。

// @/types/scss.d.ts

declare module '*.scss';

番外編

ここまでで、Sass ( Scss ) 変数が vue ファイルの <template> 内や <script> 内で使えるようになったかと思います。

が、:export {} を定義したファイル内で Sass の math 機能 を使ったときに、このようなエラーが出ているのではないでしょうか?

Module build failed (from ./node_modules/sass-loader/dist/cjs.js):                                                                                                                friendly-errors 12:43:45
SassError: @use rules must be written before any other rules.
   ╷
14 │ @use "sass:math";
   │ ^^^^^^^^^^^^^^^^
   ╵

これを解消するために、export: {} 部分のみを別ファイルに切り出します。

// @/assets/scss/constsForJs.scss

:export {
  COLOR_PRIMARY: $COLOR_PRIMARY;
  COLOR_SECONDARY: $COLOR_SECONDARY
}
<!-- @/components/Test.vue -->

<template>
  <div class="Test">
    <p class="Test_Text">Text1</p>
    <p :style="styleObj">Text2</p>
    <p :style="{ color: COLOR_SECONDARY }">Text3</p>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
+ import colorModule from '@/assets/scss/constsForJs.scss';
export default Vue.extend({
  name: 'Test',
  data () {
    return {
      COLOR_SECONDARY: colorModule.COLOR_SECONDARY
    }
  },
  computed: {
    styleObj () {
      return {
        color: this.COLOR_SECONDARY
      }
    }
  }
})
</script>

<style lang="scss" scoped>
  .Test_Text {
    color: $COLOR_PRIMARY;
  }
</style>

まとめ

今回は、Nuxt.js ( Vue.js ) を例に挙げましたが、Next.js ( React ) や、UI ライブラリを使っていない場合でも同じ手法が使えます。

:export で 変数を定義し、sass ( scss ) ファイルを import する。
そして、必要であれば stylelint にルールを追加や型定義ファイルを追加するだけ。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5