Skip to content
On this page

useCssVariables

Expose the CSS variables of your choice to reactive properties. Using MutationObserver.

Parameters

typescript
import { useCssVariables } from '@elonehoo/pistachio'

useCssVariables(variables)
useCssVariables(variables, options)
useCssVariables(variables, element, options)

useCssVariables({
  backgroundColor: "color-background", // value is css as --color-background
  foregroundColor: "--color-foreground", // value is css as --color-foreground
  onBackgroundColor: {
    name: "color-on-background",
    value: "red"
  }
});

/**
 * API to assign a value to the css variable
 */
export interface CssVarDefinition {
  name: string
  value: RefTyped<string>
}

/**
 * Possible configuration
 */
export type CssVarDef = CssVarDefinition | string

const defaultOptions = {
  attributes: true,
  childList: true,
  subtree: true
}
import { useCssVariables } from '@elonehoo/pistachio'

useCssVariables(variables)
useCssVariables(variables, options)
useCssVariables(variables, element, options)

useCssVariables({
  backgroundColor: "color-background", // value is css as --color-background
  foregroundColor: "--color-foreground", // value is css as --color-foreground
  onBackgroundColor: {
    name: "color-on-background",
    value: "red"
  }
});

/**
 * API to assign a value to the css variable
 */
export interface CssVarDefinition {
  name: string
  value: RefTyped<string>
}

/**
 * Possible configuration
 */
export type CssVarDef = CssVarDefinition | string

const defaultOptions = {
  attributes: true,
  childList: true,
  subtree: true
}
ParametersTypeRequiredDefaultDescription
variablesRecord<string | CssVarDef>truedictionary with the cssVariable name you wish to track/change
optionsMutationObserverInitfalsedefaultOptionsOptions passed to MutationObserver.observe MutationObserverInit
elementHTMLElementfalsedocument.documentElementelement to keep track of CssVariables, it will default to document.documentElement if is in a client browser

State

The useCssVariables function exposes the following reactive states:

typescript
import { useCssVariables } from '@elonehoo/pistachio'

const {
  supported,
  observing,
  backgroundColor,
  onBackgroundColor
} = useCssVariables({
  backgroundColor: "color-background",
  onBackgroundColor: {
    name: "color-on-background",
    value: "red"
  }
});

// backgroundColor contains the `--color-background` CSS variable
// onBackgroundColor sets `--color-on-background` CSS variable with the value 'red'
// observing is true

backGroundColor.value = "yellow"; // updates the cssVariable to yellow
import { useCssVariables } from '@elonehoo/pistachio'

const {
  supported,
  observing,
  backgroundColor,
  onBackgroundColor
} = useCssVariables({
  backgroundColor: "color-background",
  onBackgroundColor: {
    name: "color-on-background",
    value: "red"
  }
});

// backgroundColor contains the `--color-background` CSS variable
// onBackgroundColor sets `--color-on-background` CSS variable with the value 'red'
// observing is true

backGroundColor.value = "yellow"; // updates the cssVariable to yellow
StateTypeDescription
supportedbooleanReturns true if MutationObserver is supported
observingRef\<boolean>A value that indicates if the observer is listening to CSS variable changes
...variablesRef\<TVariables>Object with the same keys but with reactive CSS variable value

Methods

The useCssVariables function exposes the following methods:

typescript
import { useCssVariables } from '@elonehoo/pistachio'

const { resume, stop } = useCssVariables()
import { useCssVariables } from '@elonehoo/pistachio'

const { resume, stop } = useCssVariables()
SignatureDescription
resumeStart observing the changes again
stopStops observing the changes

TIP

Calling stop() will stop observing for changes in the DOM, changes made to the ref will still update/override the style values.

Check the example bellow.

Example

I am a text with the following color: red
vue
<script setup lang="ts">
import { useCssVariables } from '@elonehoo/pistachio'
import { defineComponent, ref } from 'vue'

const textDiv = ref(null)

const { supported, stop, resume, observing, foreground } = useCssVariables(
  {
    foreground: {
      name: 'color-foreground',
      value: 'red'
    }
  },
  textDiv
)
</script>

<template>
  <div>
    <div>
      <label for="foreground-value">
        Override the value for
        <code>--color-foreground</code>:
      </label>
      <input id="foreground-value" v-model="foreground" type="text">
    </div>

    <div ref="textDiv" class="text" style="color: var(--color-foreground)">
      <span v-if="observing">I am a text with the following color:</span>
      <span v-else>My color will be updated but not my label:</span>
      {{ foreground }}
    </div>

    <div>
      <button type="button" :disabled="!observing" @click="stop">
        Stop observing
      </button>
      <button type="button" :disabled="observing" @click="resume">
        Resume observing
      </button>
    </div>
  </div>
</template>

<style scoped>
div > div {
  margin-top: 15px;
}

.text {
  margin: 15px 0;
}
</style>
<script setup lang="ts">
import { useCssVariables } from '@elonehoo/pistachio'
import { defineComponent, ref } from 'vue'

const textDiv = ref(null)

const { supported, stop, resume, observing, foreground } = useCssVariables(
  {
    foreground: {
      name: 'color-foreground',
      value: 'red'
    }
  },
  textDiv
)
</script>

<template>
  <div>
    <div>
      <label for="foreground-value">
        Override the value for
        <code>--color-foreground</code>:
      </label>
      <input id="foreground-value" v-model="foreground" type="text">
    </div>

    <div ref="textDiv" class="text" style="color: var(--color-foreground)">
      <span v-if="observing">I am a text with the following color:</span>
      <span v-else>My color will be updated but not my label:</span>
      {{ foreground }}
    </div>

    <div>
      <button type="button" :disabled="!observing" @click="stop">
        Stop observing
      </button>
      <button type="button" :disabled="observing" @click="resume">
        Resume observing
      </button>
    </div>
  </div>
</template>

<style scoped>
div > div {
  margin-top: 15px;
}

.text {
  margin: 15px 0;
}
</style>

Released under the MIT License.