ShaderGradientは、three.jsで描く動く3Dグラデーションを、ブラウザのエディタで調整してReactやVueのコンポーネントとして貼り込めるOSSです。インストーラで入れるデスクトップアプリは無く、Webエディタ shadergradient.co、npmパッケージ、Figma・Framerのプラグインで使います。この記事では、公式リポジトリ ruucm/shadergradient と npm に公開されているパッケージの中身をもとに、導入手順、Next.jsで必要な版の組み合わせ、バンドルサイズの実測値までを2026年10月26日時点の情報で整理します。
まとめ
- React版は
@shadergradient/react2.4.20(2025年12月8日公開)。2026年9月23日に公式のVue版@shadergradient/vue0.1.0 が加わり、Vue 3とNuxtでも使えるようになった。 - React版は依存を宣言していないので、
threeと@react-three/fiberは自分で入れる。入れ忘れてもnpmは警告しない。 - Next.js 15・16のApp RouterはReact 19系のcanaryを同梱しているため、React 19と
@react-three/fiber9系の組み合わせが必須。React 18に留まるなら8系(最終8.18.0)を使う。 - three.jsごと取り込むので、最小構成でもgzip後に約290KB増える(esbuildで実測)。ファーストビューの装飾なら
React.lazyで別チャンクに分ける。 - three 0.183以降で出る
THREE.Clockの非推奨警告を消す修正PR #159は、2026年10月26日時点で未マージ。マージ後もR3F由来の警告が1件残るが、動作には影響しない。
ShaderGradientの4つの使い方|Webエディタ・Figma・Framer・npm
公式リポジトリは自らを「Create beautiful moving gradients on Framer, Figma and React」と説明しています。2022年4月16日に作成され、2026年10月26日時点でスター2,978・フォーク177、最後の更新はVue版を追加した2026年9月23日です。この記事で使うthree 0.186.1の描画には、WebGL 2が利用できるブラウザ環境が必要です。npmパッケージの利用にライセンスキーや独自のプロジェクトファイルは不要です。描画の土台になっているthree.jsの仕組みは Three.jsとは?r185の導入手順とglTF表示・バンドルサイズ実測まで解説 で扱っています。
成果物から決める経路の選び分け
どの経路を使うかは、最後に何を納品するかで決まります。
| 欲しいもの | 使う経路 | 入手先 |
|---|---|---|
| カンプ用のGIF・動画 | Figmaプラグイン | Figma Community ID 1203016883447870818 |
| Framerサイトの背景 | Framerコンポーネント | READMEのコンポーネントURLをキャンバスに貼る |
| Reactアプリの背景 | @shadergradient/react | npm |
| Vue・Nuxtアプリの背景 | @shadergradient/vue | npm |
コードを書く必要があるのはnpmの2つだけです。npmの2つはMITライセンスで無料ですが、Figmaプラグインは書き出しに有料プランがある点だけ扱いが違います(よくある質問で扱います)。見た目をWebエディタで調整し、設定URLを共有しておくと、色や形状の指定を伝えやすくなります。
shadergradient.coのカスタマイズ画面で設定を作りURLで持ち出す手順
公式サイトの /customize は、形状・3色・カメラ角度・アニメーション速度をGUIで詰めるエディタです。調整した状態はすべてURLのクエリ文字列に載るので、URLをコピーすれば設定を持ち出せます。READMEが例に挙げているURLは次の形です。
https://www.shadergradient.co/customize?animate=on&cDistance=3.6&cPolarAngle=90
&color1=%2352ff89&color2=%23dbba95&color3=%23d0bce1&lightType=3d&shader=defaults
&type=plane&uFrequency=5.5&uSpeed=0.4&uStrength=4
クエリのキー名は、そのままコンポーネントのprops名です。type、color1、uSpeed の値をコード上で手探りするより、デザイン担当がエディタで見た目を決め、そのURLを開発側に渡すほうが早く終わります。
ReactでShaderGradientを動かす|@shadergradient/reactのインストールと最小構成
three・@react-three/fiberを自分で追加する理由
npm上の2.4.20のpackage.jsonを見ると、dependencies の項目自体が無く、peerDependencies も react と react-dom(どちらも ^18.2.0 || ^19.0.0)の2つだけです。ところが配布されているdistは、外部モジュールとして three と @react-three/fiber をimportしています。宣言と実装が食い違っているので、この2つを入れ忘れてもインストールは通り、ビルドや実行の段階で初めてモジュール解決エラーになります。
npm i @shadergradient/react @react-three/fiber three
npm i -D @types/three
READMEの手順には three-stdlib と camera-controls も並んでいます。しかし2.4.20のdistでは、この2つはチャンクに同梱済みで外部importとしては出てきません。自分で入れる必要があるのは three と @react-three/fiber です。
ShaderGradientCanvasとShaderGradientの最小コード
キャンバス(ShaderGradientCanvas)の中にグラデーション(ShaderGradient)を1つ置くのが基本形です。READMEの例をそのまま使えます。
import { ShaderGradientCanvas, ShaderGradient } from '@shadergradient/react'
export function Background() {
return (
<ShaderGradientCanvas
style={{ position: 'absolute', inset: 0 }}
pixelDensity={1.5}
fov={45}
>
<ShaderGradient cDistance={32} cPolarAngle={125} />
</ShaderGradientCanvas>
)
}
v2はレンダラーだけを提供し、状態管理やコントロールUIは持ちません。色をユーザー操作で変えたいなら、自分のstateからpropsに渡します。
control=’query’による設定URLの読み込み
propsを1つずつ書き写す代わりに、control='query' を指定して urlString にエディタのURLを渡せます。色や速度を微調整するたびにpropsを書き換える往復がなくなります。
<ShaderGradientCanvas>
<ShaderGradient
control='query'
urlString='https://www.shadergradient.co/customize?animate=on&cDistance=3.6&uSpeed=0.4'
/>
</ShaderGradientCanvas>
指定を省くと 'props' として扱われ、JSXに書いた値が使われます。1つのコンポーネントの中では、どちらか一方に寄せてください。
Next.jsとReactの版の組み合わせ|15・16のApp RouterとReact 19・@react-three/fiber 9
版の制約はShaderGradient本体ではなく、React Three Fiber(R3F)から来ています。npmに公開されている各版のpeerDependenciesを並べると、組み合わせは次のとおりです。
| 環境 | React | @react-three/fiber | three |
|---|---|---|---|
| Next.js 15・16 App Router | 19.0〜19.3 | 9系(最新9.8.2) | 0.158.0以上 |
| React 19のVite・Pages Router | 19.0〜19.3 | 9系 | 0.158.0以上 |
| React 18のプロジェクト | 18.2以上 | 8系(最終8.18.0) | 0.158.0以上 |
R3F 9.8.2のpeerDependenciesは react: ">=19 <19.4"、8.18.0は react: ">=18 <19" です。React 18のまま9系を入れることはできず、逆にReact 19で8系も使えません。three の下限0.158.0はREADMEの互換表の値です。
App Routerで8系を使うと、Cannot read properties of undefined (reading 'ReactCurrentOwner') でページが落ちます。App Routerが内部に同梱するReact 19 canaryと8系が噛み合わないためで、issue #138 で原因が説明されています。READMEの互換表はNext.js 15までしか書かれていませんが、Next.js 16.4.3のパッケージに同梱されたReactも 19.3.0-canary なので、16でも同じ組み合わせが必要です。この組み合わせを守れば、next.config への transpilePackages の追加は要りません。
App Routerでは、ShaderGradientを使うファイルの先頭に 'use client' を書きます。2.4.20のdistには 'use client' の指定が無く、内部で useState や useEffect を使っているので、Server Componentから直接importするとエラーになります。公式のNext.jsサンプル(apps/example-nextjs-dev)も、ページの1行目を 'use client' にしています。なお、READMEの「Next.js Starter (App Router)」のCodeSandboxリンクが指す apps/example-nextjs-approuter は、mainブランチにはもうありません。
VueとNuxtでShaderGradientを動かす|公式@shadergradient/vue 0.1.0
2026年9月23日、PR #160「feat(vue): add Vue 3 and Nuxt support」がマージされ、公式のVue版 @shadergradient/vue 0.1.0 が公開されました。React版と同じシェーダーとプリセットを、ReactもR3Fも読み込まずにTresJS(Vue用のthree.jsレンダラー)の上で動かします。リリースから1か月(2026年9月23日〜10月22日)のダウンロード数は183で、React版の116,291と比べるとまだ初期段階です。
Vue版のインストールと最小コード
必要なのはVue 3.5以上、TresJS 5、three 0.180以上です。npmの0.1.0のpeerDependenciesも vue ^3.5.0、@tresjs/core ^5.0.0、three >=0.180.0 になっています。React版と違い、camera-controls(2.9.0固定)は正式な依存として宣言されています。
pnpm add @shadergradient/vue vue@^3.5 @tresjs/core@^5 three@^0.186.0
pnpm add -D @types/three@^0.186.0
<script setup lang="ts">
import { ShaderGradient, ShaderGradientCanvas } from '@shadergradient/vue'
</script>
<template>
<ShaderGradientCanvas style="height: 400px" :pixel-density="1.5">
<ShaderGradient color1="#ff5005" color2="#dbba95" color3="#d0bce1" />
</ShaderGradientCanvas>
</template>
ラッパーの高さが0だと何も表示されないので、必ず高さを与えてください。エディタのURLは control="query" と url-string で読み込めます。URLに無い値はpropsの既定値のまま、未知のキーや不正な値は無視されます。
NuxtのSSRとreduced motionへの対応
Nuxtでは専用モジュールも ssr: false も要りません。ShaderGradientCanvas はサーバー側ではコンテナと fallback スロットだけを描き、ブラウザでマウントした後にキャンバスを作ります。READMEはサイト全体のSSRを切らないよう求めています。Nuxt自体のレンダリング方式は Nuxtとは:Vue.jsとの違い・レンダリング方式・4系への移行手順と採用判断を実装視点で解説 で整理しています。
<script setup lang="ts">
import { ShaderGradient, ShaderGradientCanvas, presets } from '@shadergradient/vue'
</script>
<template>
<ShaderGradientCanvas style="height: 400px">
<ShaderGradient v-bind="presets.mint.props" animate="off" />
<template #fallback>
<div style="height: 100%; background: #94ffd1" />
</template>
</ShaderGradientCanvas>
</template>
Vue版は、OSの「視差効果を減らす」設定(prefers-reduced-motion: reduce)を検知するとアニメーションを止め、カメラの遷移も切ります。0.1.0のdistに window.matchMedia("(prefers-reduced-motion: reduce)") の処理が入っていることも確認しました。React版2.4.20のdistにはこの処理が無いので、Reactで同じことをするなら自分で書く必要があります(よくある質問で扱います)。
第三者製のVue移植との違い
公式版が出る前から、npmにはVue向けの移植がいくつかあります。いずれも作者が別で、公式のサポート対象ではありません。
@shader-gradient/vue・@shader-gradient/react(0.3.0/2026年6月21日):スコープ名にハイフンが入る別プロジェクトで、リポジトリは Jannchie/shader-gradient。shader-gradient-vue(1.0.0/2026年2月2日)、@siavava/shadergradient-vue(0.1.0/2026年7月9日):個人によるVue移植。
これから新しく入れるなら、公式の @shadergradient/vue を選んでください。スコープ名が @shadergradient(ハイフンなし)であることが目印です。
主要プロパティと見た目を詰める順番
| 分類 | 主なプロパティ | 値の例 |
|---|---|---|
| 形状 | type・uStrength・uDensity・uFrequency・uAmplitude | plane, sphere, waterPlane |
| 色・質感 | color1〜3・shader・reflection・brightness | HEX、defaults, glass ほか |
| アニメーション | animate・uSpeed・uTime・loop・loopDuration | on, off、数値 |
| カメラ | cDistance・cPolarAngle・cAzimuthAngle・cameraZoom | 数値(角度は度) |
| ライト・効果 | lightType・envPreset・grain・grainBlending | 3d, env・city, dawn, lobby |
| キャンバス | pixelDensity・fov・lazyLoad | 既定は1、45、true |
触る順番は、type、色3点、カメラ、最後にアニメーション速度です。typeを変えると同じカメラ設定でも見え方が大きく変わるので、先に色や速度を詰めると作業が無駄になります。カメラは形状によって効くpropsが違い、Vue版READMEによると、sphereは距離14で固定され cameraZoom で寄せ、planeは cDistance で寄せます(React版も同じ挙動と明記)。sphereで cDistance を変えても見た目が変わらないのはこのためです。
バンドルサイズの実測|three.js込みでgzip後約290KB増える
2026年10月26日に、esbuild 0.25.12で最小構成をビルドし、サイズを測りました(--bundle --minify、本番モード、gzip -9)。比較対象は、同じフレームワークで空の要素だけを描くコードです。
| 構成 | minify後 | gzip後 | ShaderGradientによる増分(gzip) |
|---|---|---|---|
| React 19.2.0 のみ | 194,260 B | 60,390 B | – |
| React+@shadergradient/react 2.4.20 | 1,369,353 B | 353,471 B | +293,081 B |
| Vue 3.5.44 のみ | 65,383 B | 25,854 B | – |
| Vue+@shadergradient/vue 0.1.0 | 1,170,542 B | 293,252 B | +267,398 B |
増分の大半はthree.js本体(0.186.1)です。React版はR3F 9.8.2、Vue版はTresJS 5.10.0を含みます。海外の解説記事には「約450KB(minify後)」とする記述がありますが、今回の構成ではminify後で1MBを超えました。ページの重さを見積もるときは、自分の構成でビルドして測り直してください。
React.lazyで初期チャンクから外す方法
背景のグラデーションは、本文と同時に表示されなくても困りません。ShaderGradientを使うコンポーネントを別ファイルにして React.lazy で読み込めば、three.jsは別チャンクに分かれます。esbuildの --splitting で同じ構成をビルドすると、エントリーファイルは185,202 B(gzip 57,740 B)、初期読み込みに必要な共有チャンクは9,199 B(gzip 3,480 B)で、合計194,401 B(gzip 61,220 B)となり、ShaderGradientを入れる前のReactだけの構成とほぼ同じでした。ShaderGradientのチャンク(gzip 293,105 B)は、そのコンポーネントを初めてレンダーしようとした時点で読み込まれます。この例ではHeroの初回レンダー時に取得が始まり、本文の表示完了や画面内への進入まで待つわけではありません。
// GradientBackground.jsx
import { ShaderGradientCanvas, ShaderGradient } from '@shadergradient/react'
export default function GradientBackground() {
return (
<ShaderGradientCanvas style={{ position: 'absolute', inset: 0 }}>
<ShaderGradient />
</ShaderGradientCanvas>
)
}
// Hero.jsx
import { lazy, Suspense } from 'react'
const GradientBackground = lazy(() => import('./GradientBackground'))
export function Hero() {
return (
<section style={{ position: 'relative', height: '100vh', background: '#d0bce1' }}>
<Suspense fallback={<div style={{ position: 'absolute', inset: 0, background: '#d0bce1' }} />}>
<GradientBackground />
</Suspense>
</section>
)
}
Suspenseのfallbackに単色やCSSグラデーションを置くと、コード取得中の背景を表示できます。コード取得後のCanvas生成や初回描画まで背景を維持するには、外側のsectionにも背景色を指定してください。Next.jsのApp Routerなら、'use client' を付けたファイルの中で next/dynamic を使っても同じように分割できます。
lazyLoadの既定値と画面外でのアンマウント
ShaderGradientCanvas の lazyLoad は、React版・Vue版とも既定で true です(React版2.4.20のdistでは lazyLoad=!0・threshold=.1・rootMargin="0px")。IntersectionObserverでキャンバスが画面に入ったかを見ており、外れるとWebGLのCanvasをアンマウントします。つまり、何も設定しなくても、画面外のグラデーションは描画されていません。
ここで誤解しやすいのは、lazyLoad が遅らせるのは描画だけで、JavaScriptのダウンロードは遅らせない点です。上の約290KBは、lazyLoad を有効にしていても初回の読み込みに含まれます。また画面に戻るたびにシーンを作り直すので、スクロールで何度も出入りする位置に置くと、そのたびにシェーダーのコンパイルが走ります。ヘッダー背景のように画面に残り続ける場所なら lazyLoad={false} にしても描画コストは変わりません。
ShaderGradientを採用しないほうがよいページ
Core Web Vitalsの数値を厳しく見られるLPや、モバイルからの流入が大半のサイトでは、ShaderGradientを使わず静止画やCSSのグラデーションにするほうが妥当です。画面に見えている間はGPUで毎フレーム描き続けるので、遅延読み込みで減らせるのは初期の負荷だけです。リポジトリには「Google Pagespeed Timeout」(issue #80、2024年4月7日)と「Stuttering on mobile」(issue #81、2024年4月8日)が、2026年10月26日時点でも未解決のまま残っています。指標の測り方は Core Web Vitalsとは:LCP・INP・CLSの基準値とweb-vitals・CrUX APIでの測り方【2026年10月】 を参考にしてください。動く背景を入れるかどうかは、表示速度とコンバージョンを合わせて判断することになります。LP制作・ランディングページ制作では、こうした演出と表示速度の兼ね合いも含めて設計を支援しています。
導入前に確認する制約|ESM専用とTHREE.Clockの非推奨警告
import条件だけのexportsとrequire()の非対応
React版2.4.20の exports は {".": {"import": "./dist/index.mjs", "types": "./dist/index.d.mts"}} だけで、require 条件もCJSビルドもありません。Vue版0.1.0も import 条件だけです。Node.js 20.19・22.12以降の require(esm) を使えばESMを require() で読めるようになりましたが、このパッケージには当てはまりません。Node.js 26.5.0で require('@shadergradient/react') を実行すると、exports に require 条件も default 条件も無いため ERR_PACKAGE_PATH_NOT_EXPORTED で失敗しました(Vue版も同じ)。CommonJSのまま動かしているJestのテストなどから使うなら、テスト側をESM対応にするか、テストではモックに差し替えます。ESMとCommonJSの解決の違いは ESMとCommonJSの違い|require(esm)で変わった相互運用と移行手順【Node.js 26実測】 で確認できます。
three 0.183以降のTHREE.Clock警告と修正PRの状況
React版2.4.20のdistは、threeから Clock をimportして使っています。three側は0.183で Clock を非推奨にし、最新の0.186.1(2026年9月24日公開)でも src/core/Clock.js が「Clock: This module has been deprecated. Please use THREE.Timer instead.」という警告を出します。そのため、three 0.183以降と組み合わせるとコンソールにこの警告が出ます。
この問題は2026年7月25日に issue #158 として報告され、8月30日に、Clockの代わりにR3Fのフレーム間の経過時間を使う修正 PR #159 が出ています。ただし2026年10月26日時点でPRはマージされていません。また、このPRが除去するのはShaderGradient自身のClock参照で、PRの説明ではR3F 8・9由来の警告は残るとされています。描画は正常なので、基本は警告を許容してかまいません。CIでコンソールの警告をエラー扱いにしている場合だけ、threeを0.182.xに固定して避けてください。なおVue版0.1.0のdistには Clock への参照が無く、土台のTresJS 5.10.0もthree r179以降では Clock ではなく Timer を使います。Vue版はthree 0.180以上が前提なので、コード上はこの警告の出どころがありません。
GitHubリポジトリとnpmパッケージの見分け方|v1・v2・未公開版
v1のshadergradientとv2の@shadergradient/react
スコープなしの shadergradient がv1で、1.3.5(2024年10月22日)を最後に更新が止まっています。v1はストアとUIを同梱していましたが、v2の @shadergradient/react はレンダラーだけに絞られました。直近1か月(2026年9月23日〜10月22日)のダウンロード数は、v2の116,291に対してv1は16,596です。新しく入れるならv2を選んでください。
READMEにはもう1つ、shadergradient-old(1.2.7/2024年3月31日)が出てきます。READMEは「古いwith-storeビルドに依存している場合だけ使い続ける」レガシーv1と位置づけています。版番号は shadergradient の1.3.5のほうが新しいので、名前の「old」だけで判断すると取り違えます。
npmに無い版と名前が紛らわしいリポジトリ
リポジトリのCHANGELOG(packages/shadergradient)には2.4.21〜2.4.24まで記録されていますが、npmに公開されているのは2.4.20までで、dist-tagsのlatestも2.4.20です。CHANGELOGの版番号で npm i @shadergradient/[email protected] としても入りません。版はnpm registry側で確認してください。
@shadergradient/ui:READMEのとおりnpmには公開されておらず、0.0.0のプレースホルダ(2025年2月9日)だけがある。Framer・Figma向けのコントロールUIで、アプリから使うものではない。- zavalit/ruucm-shadergradient:検索で出てくるが、GitHub上は ruucm/shadergradient のフォーク。
ライセンスはREADMEとpackage.jsonでMITと明記されており、商用サイトでも使えます。
よくある質問
ShaderGradientの利用に費用はかかりますか?
React版・Vue版のnpmパッケージは無料です。READMEとnpmのpackage.jsonは、どちらもライセンスをMITとしています。ただし2026年10月26日時点で、リポジトリ直下にLICENSEファイルは置かれていません。社内の法務確認でライセンスの根拠を求められたら、READMEのLicense節とpackage.jsonの license フィールドを示してください。有料になりうるのはFigmaプラグインで、mainブランチのソース(FigmaPlugin/Pricing.tsx)にはStripeでのPro購読と「年払いなら月2ドル、月払いなら月4ドル」という表示があります。
デザインカンプ用にGIFや動画だけ欲しい場合はどうしますか?
Figmaプラグイン(Figma Community ID 1203016883447870818)を使えば、コードを書かずに済みます。mainブランチのソースでは、GIFと動画(WebM)の書き出しに対応しており、Figma SlidesとFigma Buzzでは動画をそのままキャンバスに置けます。ただし書き出しには7日間の試用期間があり、期限が切れるとボタンが「Upgrade to Pro」に変わってPro購読が必要になる作りです。実際の価格と条件はプラグインの画面で確認してください。また、そのGIFをWebサイトの背景に使うのはおすすめしません。GIFは256色までしか使えずグラデーションに段差が出るうえ、ファイルも重くなります。Web掲載では、静止した背景なら画像やCSS、動きが必要なら動画またはnpm版を、転送量と描画負荷を比較して選んでください。Figmaでのアニメーション制作全般は Figma Motionとは?使い方・書き出し・無料でできる範囲を解説【2026年10月】 で扱っています。
GitHubのどのリポジトリが公式ですか?
ruucm/shadergradient です。homepageにshadergradient.coが設定され、npmの @shadergradient/react と @shadergradient/vue もここで開発されています。スコープ名にハイフンが入る @shader-gradient 系は、Jannchie/shader-gradientという別作者のプロジェクトです。
ReactでもOSの「視差効果を減らす」設定に合わせて動きを止められますか?
止められますが、自分で書く必要があります。React版2.4.20には prefers-reduced-motion を見る処理が無いので、window.matchMedia('(prefers-reduced-motion: reduce)') の結果を見て animate に 'off' を渡します。Vue版0.1.0はこの処理を内蔵しています。本文とともに動き続ける背景には、OS設定への追従に加えて、利用者が停止・再開できる操作も用意してください。
'use client'
import { useEffect, useState } from 'react'
import { ShaderGradientCanvas, ShaderGradient } from '@shadergradient/react'
export default function GradientBackground() {
const [reduce, setReduce] = useState(false)
useEffect(() => {
const mq = window.matchMedia('(prefers-reduced-motion: reduce)')
setReduce(mq.matches)
const onChange = (e) => setReduce(e.matches)
mq.addEventListener('change', onChange)
return () => mq.removeEventListener('change', onChange)
}, [])
return (
<ShaderGradientCanvas style={{ position: 'absolute', inset: 0 }}>
<ShaderGradient animate={reduce ? 'off' : 'on'} />
</ShaderGradientCanvas>
)
}
SvelteやSolid.jsでも使えますか?
公式に対応しているのはReactとVueだけです。Solid.jsへの対応は2026年5月7日に issue #156 で要望が出た段階で、Svelte版はありません。READMEのFuture Planには「シェーダーコードを別パッケージに切り出してJSなどから再利用できるようにする」が未完了の項目として残っています。それまでは、three.jsで同じシェーダーを自分で組むか、PixiJSとは?WebGL/WebGPUで動く2D描画エンジンの使い方をv8.22対応で解説 のような別の描画ライブラリでグラデーションを作ることになります。