年別アーカイブ 2026年6月20日

WooCommerceで国別価格設定後にカートで価格が18%下がる原因

WooCommerceで国別価格設定後にカートで価格が18%下がる原因

国別価格プラグインとWooCommerceの標準税設定を併用していると、商品をカートに入れた瞬間に約18%引きの価格が表示される現象が起きる。これはインド向けの税率が米ドル建ての表示価格にまで漏れ出し、税抜き再計算が走ってしまうためだ。

なぜカートで価格が18%下がるのか

なぜカートで価格が18%下がるのか

カートに追加した直後に129ドルが約109ドルに減る理由は、WooCommerceの「税設定」と「価格表示」に潜む優先順位の構造にある。販売地域がインドで基本通貨を米ドルに設定し、かつ国別価格プラグインで国ごとに異なる価格を手動入力している店舗では、インド向けの18%税率が米ドル表示側に干渉しやすい。

WooCommerceの税設定には「税込で価格を入力する」か「税抜きで入力する」かの二択がある。税込(ベース価格に税が含まれている前提)を選ぶと、システムは表示価格を税込み総額とみなし、該当する税率に基づいて税抜き部分と税額に内部で分離する。ここに、本来その国には適用されるはずのないインドの18%スラブが食い込むと、129ドルを「税抜き価格+18%税相当」と計算し直し、税抜き価格約109ドルをカートに表示してしまう。

特にPrice Based on Country系のプラグインは、通貨ごとに手動価格を入力できても、WooCommerceの標準税テーブルと密接に連動しているわけではない。このため国検出ロジックと税ルールが別々に動き、非インド顧客の米ドル表示にもインド税率がかぶさる不整合が起こる。

税テーブルと国別価格の干渉を解消する手順

税テーブルと国別価格の干渉を解消する手順

不整合の根源である税テーブルを整理し、適用範囲を正しく限定すれば価格の引き下げは止まる。管理画面から次の流れで修正する。

STEP 1 WooCommerceの「設定」→「税」を開き、税率一覧を確認する
↓
STEP 2 インド向け税率の「国」欄が「IN」のみであることを確認し、誤って「全地域」などになっていれば修正する
↓
STEP 3 税設定の「税込で価格を入力する」を一旦「税抜きで価格を入力する」に切り替え、すべての通貨で正しい価格を再入力する

税率テーブルを開くと、インド向けの18%行の「国コード」欄が空白または複数国に誤設定されているケースがある。これをIN単独に直し、米国など他国に波及しないようにする。Price Based on Countryプラグイン側でも、米ドル表示の国リストに見落としがないか再確認する必要がある。

価格表示オプションの「税込」「税抜」を整理する

価格表示オプションの「税込」「税抜」を整理する

税込み入力モードは税テーブルと不可分に動くため、通貨ごとに手動価格を割り当てる運用との相性が悪い。税抜き入力に切り替えて価格を純粋な本体金額とし、税は決済時に国ごとのテーブルにしたがって自動加算する形が安定する。

ただし切替時に既存商品の価格は変わらないため、129ドルと入力していた商品は税抜き129ドルとみなされ、かえって値上がりする。そこで切り替え後は全商品の価格を意図した税抜き金額(たとえば税込み表示にしたいなら本体109ドル前後)に書き換える作業が必要になる。国別価格プラグインに一括更新機能があれば活用すると手間を減らせる。

Before 税込み入力モード
商品価格 129ドル → 自動で18%税抜き計算 → カートに109ドル表示
↓
After 税抜き入力モード
商品価格 109ドル(本体) → 税は決済時のみ加算 → カート表示は109ドルで安定
■ 税込み入力で誤動作  ■ 税抜き入力で安定

税込み入力モードのまま運用を続ける場合は、インドの税率をいったん無効化し、Price Based on Countryプラグイン側の価格に税込み金額を直接登録する方法もある。ただこの方法は今後の税率変更に弱く、国ごとの税計算をWooCommerceの標準機能に任せられなくなるため推奨しない。

よくある質問

米ドル建てに18%の税率が見当たらないのに価格が下がるのはなぜか

米ドル用の税率が存在しなくても、WooCommerceは税込み入力モード時に「顧客の所在地に連動した税率」を内部で適用しようとする。国検出がインドと判定された瞬間に18%スラブが動き、価格が再計算されるのが根本原因だ。

国別価格プラグインを一時停止すればすぐ直るか

プラグインを無効化すると国別の価格表示そのものが消え、全ユーザーに基本通貨の価格が表示されるため、18%引きは起こらなくなる。ただし根本解決ではなく、多通貨販売をあきらめることになる。

税率テーブルでIN以外の国をすべて削除しても問題ないか

税率を適用したい国が増えるたびに行を追加する運用になるが、現在問題が起きている状態よりは安全だ。税率テーブルには最低限必要な国コードだけを残し、ワイルドカード指定は避けることを勧める。

価格を税抜き入力に切り替えた後、カートで税が表示されずに困る場合の対処は

税抜き入力にしたら「表示価格」の設定を「税込み」に戻すと、フロントエンドでは本体価格に税が乗った金額が表示される。この設定は「WooCommerce → 設定 → 税」の「店舗での価格表示」で変更できる。

キャッシュが原因で設定変更がすぐ反映されないときはどうするか

WooCommerceの「ステータス → ツール」から顧客セッションと製品の価格キャッシュをクリアし、さらにサイトキャッシュやCDNキャッシュもあわせて削除する。プライベートウィンドウで確認すると切り分けが早い。

この記事のポイント

  • カートでの価格引き下げは税込み入力モードと国別税率の干渉で起こる
  • 税率テーブルの国コードを見直し、不要な適用範囲を削除する
  • 「税抜きで価格を入力する」モードに統一すれば価格は安定する
  • 設定変更後はキャッシュクリアと価格再設定を忘れずに行う
TypeScript 7.0 RCリリース、Go実装でコンパイル速度10倍に

TypeScript 7.0 RCリリース、Go実装でコンパイル速度10倍に

TypeScript 7.0 RCの概要とインストール方法

TypeScript 7.0 RCの概要とインストール方法

TypeScript 7.0 RCの最大の変更点は、コンパイラそのものがGo言語で再実装されたことにある。これまで約10年にわたってTypeScript自身(セルフホスト)で書かれJavaScriptにトランスパイルされてきたコードベースを、Goに移植し直した。ネイティブコードの実行速度と共有メモリによる並列処理によって、コンパイル速度はTypeScript 6.0と比較して約10倍高速化した。

パッケージのインストールは従来と変わらずnpmから行える。以下のコマンドでRelease Candidateを取得し、すぐに試せる。

npm install -D typescript@rc

インストール後は npx tsc --version でバージョンを確認できる。7.0.1-rc が表示されれば準備完了だ。コマンドラインの挙動はTypeScript 6.0と変わらず、同じ型チェック結果が得られる。エディタで試すには、VS Code向けに提供されている TypeScript Native Preview 拡張機能 をインストールするとよい。この拡張機能はLanguage Server Protocol(LSP)に基づいており、Copilot CLIを含む多くのエディタで動作する。

既存のTypeScript 6.0との共存

TypeScript 7.0 RCは安定版に近いが、プログラム向けの正式なAPIは少なくとも数か月先のバージョン7.1まで提供されない。このため、TypeScriptチームは6.0と7.0を並行して使い分けられる仕組みを用意した。互換パッケージ @typescript/typescript6 を導入すると、tsc6 という別名のバイナリが利用可能になる。従来のツールチェーンは6.0に固定しつつ、開発中の7.0を試す構成が取れる。

npm install -D typescript@npm:@typescript/typescript6
npm install -D typescript-7@npm:typescript@rc

これにより tsc は7.0を指し、tsc6 は6.0を指す。typescript-eslintのようなピア依存関係を持つツールでも問題なく使い分けられる。ナイトリービルドは現在 @typescript/native-preview パッケージで提供されており、バイナリ名は tsgo となっている。安定版リリース後は typescript パッケージに統合される予定だ。

単一スレッド動作と並列化の制御

TypeScript 7.0では、解析(パース)、型チェック、出力(エミット)の各段階が並列化されている。解析と出力はファイルごとに独立して処理できるため、大規模なコードベースほど効率よくスケールする。一方、型チェックはファイル間の依存関係が複雑で、完全に独立して動かすと計算の重複やメモリ消費が増える。この課題に対処するため、7.0は 固定数の型チェッカーワーカー を立ち上げる仕組みを採用した。デフォルトのワーカー数は4で、--checkers フラグで変更できる。

CIランナーのようにCPUコア数やメモリが限られた環境では、ワーカー数を減らすことでオーバーヘッドを抑えられる。稀に、--checkers の値によって型チェック結果にわずかな順序依存の差異が出る場合がある。チーム間で同じ結果を得るには、明示的にワーカー数を固定しておくのが安全だ。

従来のシングルスレッド処理と 7.0 の並列処理の比較
従来(TypeScript 6.0)シングルスレッド
パース ファイルA → 型チェック ファイルA → 出力 ファイルA
全ファイルを 1 スレッドで逐次処理するため、コードベースが大きいと待ち時間が線形に増加する
↓
TypeScript 7.0 の並列処理
パース ファイルA + パース ファイルB (同時実行)
型チェッカー 1 担当範囲内のファイル群 + 型チェッカー 2 別範囲のファイル群
出力 ファイルA + 出力 ファイルB
複数スレッドが並列動作し、全体のビルド時間が大幅に短縮される
■ パース(解析)  ■ 型チェック  ■ 出力

このデモで示したように、TypeScript 7.0は複数のスレッドを活用して処理を同時に進める。単一スレッドに制限したい場合は --singleThreaded フラグを指定すると、すべての処理を1スレッドで行える。デバッグやパフォーマンス比較に役立つモードだ。

プロジェクト参照ビルドの並列化

TypeScript 7.0はプロジェクト内の並列化に加え、複数のプロジェクト参照を同時にビルドできるようになった。新しい --builders フラグで、並列実行するプロジェクトビルダーの数を制御する。モノレポ構成で多数のプロジェクトを抱える開発環境では、全体のビルド時間をさらに短縮できる可能性が高い。

注意点として、--builders の数と --checkers の数は乗算で効いてくる。たとえば --builders 4 --checkers 4 と指定すると、最大で16個の型チェッカーが同時に動作し、マシンのリソースを圧迫する場合がある。CIランナーやローカル環境のコア数、メモリ容量に応じて適切なバランスを探ることが重要だ。--builders の数値を変えても型チェック結果自体は変わらないが、プロジェクト間の依存グラフがボトルネックになるため、すべてのケースでリニアに速くなるわけではない。

Goへの移植がもたらす互換性と安定性

Goへの移植がもたらす互換性と安定性

今回の移植は「スクラッチからの書き直し」ではなく、既存のTypeScript実装を忠実にGoへ移植する手法が取られた。型チェックのロジックはTypeScript 6.0と構造的に同一であり、これまで蓄積してきた膨大なテストスイートをすべてパスしている。Microsoft社内外の数百万行に及ぶコードベースで実際に使われており、高い互換性と安定性を維持している。

Bloomberg、Canva、Figma、Google、Linear、Miro、Notion、Slack、Vercelなど多くの企業がプレリリース版をテストし、ビルド時間の大幅な短縮と軽快な編集体験を報告している。TypeScriptチームはこれらのフィードバックを受け、リリース候補の品質に自信を持っている。

テンプレートリテラル型のUnicode対応改善

TypeScript 7.0では、テンプレートリテラル型におけるUnicodeコードポイントの扱いがより直感的になった。これまではJavaScriptのUTF-16インデックスに従い、サロゲートペアの分割が発生していた。たとえば "😀abc" をテンプレートリテラル型で推論すると、["\ud83d", "\ude00abc"] のように分割されることがあり、意味的に正しくない文字列リテラル型が生成される可能性があった。

7.0では for...of ループやスプレッド構文と同様に、"😀" を1つの単位として扱う。これにより、絵文字や一部の多バイト文字を含む文字列操作がより自然になり、意図しない型エラーを防げる。UTF-16コードユニット単位での操作を前提としていた型レベルユーティリティには破壊的変更となるが、ほとんどのケースで開発者の期待に沿う結果になる。

JavaScriptファイルのサポート見直し

TypeScriptはもともと、JSDocコメントや特定のコードパターンを解析することでJavaScriptファイルの型チェックをサポートしてきた。7.0ではこの動作をTypeScriptファイル(.ts)の解析ロジックとより一貫性のある形に再設計している。一部の旧来のパターンやJSDocタグの解釈が変更され、より厳密な型の扱いが求められるようになった。

たとえば、値が期待される箇所で直接型として値を使う記法は許容されず、typeof someValue と記述する必要がある。@enum タグは特別扱いされない。単独の ? を型として使うこともできず、代わりに any を使う。Closureスタイルの関数シンタックスもサポート対象外となった。詳細な変更点は公式の CHANGES.md ファイルにまとめられている。

改善されたwatchモードとエディタ体験

改善されたwatchモードとエディタ体験

TypeScript 7.0の --watch モードは、ファイル監視の基盤が全面的に刷新された。新しいファイルウォッチャーは、バンドラのParcelが採用している @parcel/watcher をGoへ移植したものだ。ParcelのウォッチャーはC++で実装されており、ビルドに完全なC++ツールチェーンが必要だったが、今回の移植では最小限のアセンブリシムを併用することで、Goのみで完結する形に仕上げられた。

この移植は、C++からGoへの直接的な翻訳から始まり、最終的にはGoらしいコードへと洗練された。テストスイートも移植され、プラットフォームを問わず安定して動作する。従来のポーリングベースのファイル監視は、大規模プロジェクトで node_modules 以下のファイル変更を監視する際に計算負荷が高かったが、新しいウォッチャーはリソース消費を大幅に抑えている。TypeScriptチームは、VS Codeでの長年の使用実績を持つParcelのウォッチャーをGoでも利用可能にしたことで、エディタとCLIの両方で一貫した高速なファイル監視を実現した。

エディタでの進化とLSP対応

エディタ体験も大きく向上している。VS Code向けのTypeScript Native Preview拡張機能は、LSP(Language Server Protocol)上に構築されており、複数スレッドを活用してリクエストを並列処理する。自動インポート、ホバー情報の展開、インラインヒント、コードレンズ、ソース定義への移動、JSXのリンク編集やタグ補完など、多くの機能が追加された。ベータ版で不足していたセマンティックハイライトや「インポートの並び替え」「未使用インポートの削除」といった機能もRCで組み込まれている。

TypeScriptチームの分析によれば、言語サーバーの失敗コマンド数はTypeScript 6.0と比較して20分の1以下に削減された。GitHub上の主要なTypeScriptおよびJavaScriptコードベースを使ったファズテストを通じて、品質の高さが裏付けられている。

TypeScript 6.0からの移行で注意すべき点

TypeScript 6.0からの移行で注意すべき点

TypeScript 7.0は6.0の型チェック動作と互換性を持つが、6.0で導入された新しいデフォルトや非推奨機能はそのままハードエラーとして扱われる。6.0から7.0への移行をスムーズに進めるために、まず6.0を導入し、非推奨フラグや新しい設定にコードベースを適応させておくことが推奨されている。

以下に主なデフォルト変更点をまとめる。

  • strict がデフォルトで true になる
  • module のデフォルトが esnext になる
  • target が esnext 直前の安定版ECMAScriptバージョンを指す
  • noUncheckedSideEffectImports がデフォルトで true になる
  • libReplacement がデフォルトで false になる
  • stableTypeOrdering がデフォルトで true になり、無効化できない
  • rootDir がデフォルトで ./ になり、内部のソースディレクトリを明示的に設定する必要がある
  • types のデフォルトが [] になり、以前の動作に戻すには ["*"] を指定する

rootDir の変更は、tsconfig.json が src のようなディレクトリの外にあるプロジェクトで影響が大きい。include で ./src を指定しつつ、compilerOptions.rootDir に ./src を追加すれば、ディレクトリ構造を維持できる。また、非推奨からハードエラーになった項目として、target: es5 や module: amd, umd, systemjs, none のサポート終了、moduleResolution: node/node10/classic の非サポート化、alwaysStrict の強制などが含まれる。詳細はTypeScript 6.0のリリースブログでも確認できる。

今後のロードマップと安定版リリース

今後のロードマップと安定版リリース

TypeScriptチームは、RCの公開から約1か月以内にTypeScript 7.0の安定版をリリースする計画を立てている。今後はリリース調整やロジスティクス、報告されたリグレッションの修正に注力し、7.1でのAPI機能の拡充にも取り組む。

実際のプロジェクトでTypeScript 7.0を試し、問題があればGitHubの microsoft/typescript-go リポジトリ でフィードバックを送ることが期待されている。TypeScriptチームは、コミュニティのテスト参加によって安定版を万全の状態で届けたいと考えている。フィードバックは、BlueskyやMastodon、Twitterでも受け付けている。

この記事のポイント

  • TypeScript 7.0 RCはGo言語で再実装され、コンパイル速度が最大約10倍に向上した
  • 既存のTypeScript 6.0と並行して使い分けられる共存パッケージが提供されている
  • 並列化機能(–checkers、–builders)により大規模プロジェクトのビルド時間を短縮
  • watchモードの刷新とエディタのLSP対応強化で、開発体験全体が高速化された
  • 6.0からの移行には、非推奨機能のハードエラー化やデフォルト設定の変更に注意が必要
Contact Form 7 PayPal Stripe Add-onの脆弱性と最新版への更新手順

Contact Form 7 PayPal Stripe Add-onの脆弱性と最新版への更新手順

Contact Form 7 PayPal & Stripe Add-on のバージョン 2.4.9 以前には、PayPal 決済を本来の支払い金額や通貨と無関係に「支払い完了」として通過させてしまう脆弱性がある。最新版へ更新すれば対処でき、放置すると注文だけが成立して金銭が回収できない重大なリスクを抱えるため、至急確認する必要がある。

Contact Form 7 用 PayPal & Stripe Add-on にどんな脆弱性があるのか

Contact Form 7 用 PayPal & Stripe Add-on にどんな脆弱性があるのか

この脆弱性は CVE-2026-9189 として採番されており、攻撃者が PayPal の正当な通知(IPN)に見せかけたリクエストを送信することで、実際の支払い金額や通貨、受取人の一致をまったく検証せずに「支払い済み」とマークできてしまう。プラグインは PayPal からの通知の署名検証は行っていたものの、肝心の取引金額・通貨コード・受取人メールアドレスの突き合わせを実装していなかったため、ゼロまたは極端に低い金額の注文が成立してしまう。

具体的には、フォーム送信時に生成される注文レコードに対して、PayPal のトランザクション ID と支払いステータスのみが照合され、注文時に設定された金額と実際に PayPal 上で決済された金額の比較が行われない。このため、正規のトランザクション ID を悪用、あるいは偽装した通知に対してプラグインが「正当な支払い」と誤認する状況が生まれていた。

Before(脆弱な状態)

PayPal 通知の受信 → 署名検証のみ実施 → 金額・通貨・受取人の検証なし → 0円でも「支払い完了」

↓
After(修正後)

PayPal 通知の受信 → 署名検証 → 金額・通貨・受取人を注文情報と突合 → 一致時のみ「支払い完了」

■ 脆弱な状態 ■ 修正後の状態

上の図が示す通り、修正後は金額・通貨・受取人の3点を必ず比較するロジックが追加されている。この検証が欠けていたことが、支払いバイパスを成立させる根本原因だった。

どのバージョンが影響を受けるのか

どのバージョンが影響を受けるのか

Contact Form 7 PayPal & Stripe Add-on のバージョン 2.4.9 以下が影響を受ける。2026年6月中旬時点で修正済みのバージョンがリリースされており、2.5.0 以降に更新すればこの脆弱性は解消される。

自分のサイトでどのバージョンを使用しているかは、WordPress 管理画面の「プラグイン」→「インストール済みプラグイン」一覧で確認できる。該当プラグインが有効化されている場合は、バージョン番号を直ちにチェックしておきたい。

最新版へ更新する具体的な手順

最新版へ更新する具体的な手順
STEP 1 管理画面「ダッシュボード」→「更新」を開く
↓
STEP 2 該当プラグインの更新チェックボックスをオンにする
↓
STEP 3 「プラグインを更新」をクリックして完了

更新前にサイト全体のバックアップを取得しておくとなお安心だ。更新が完了したら、プラグイン一覧でバージョンが 2.5.0 以降に切り替わっていることを必ず確認する。

更新がすぐに実行できない場合の対処

更新がすぐに実行できない場合の対処

何らかの理由で即時更新が難しい場合は、一時的に PayPal 決済機能を停止し、フォームそのものを別の決済手段に切り替えるなどの対策が有効だ。とはいえ、あくまで暫定的な措置であり、根本対策は最新版への更新以外にない。

プラグインを無効化すれば脆弱性は発動しなくなるが、フォーム経由の PayPal 決済も一切使えなくなる。その間に代替として WooCommerce の標準決済や別のフォームプラグインへ移行する判断も必要になるだろう。

よくある質問

Stripe 決済にも同じ問題はあるのか

この脆弱性は PayPal の通知処理に起因する問題であり、Stripe 側の処理ロジックには同様の不備は確認されていない。ただし、セキュリティ修正の一環で Stripe 関連のコードにも改善が加えられているため、プラグイン全体を最新に保つのが賢明だ。

すでに不正な取引が行われていないか調べる方法はあるか

PayPal の取引履歴と Contact Form 7 の送信ログを突き合わせ、注文金額と実際の決済金額が一致しているかを手動で検証する必要がある。プラグイン自体に取引監査の機能はないため、自社の売上レポートと PayPal の管理画面を定期的に照合する習慣をつけることを推奨する。

自動更新を有効にしていれば問題は起きなかったのか

自動更新が有効でも、WordPress.org のプラグインディレクトリに修正版が配信されるタイミング次第では数時間から数日のラグが生じる。さらに、サイトの更新設定によってはメジャーアップデートが自動適用されないケースもあるため、手動での確認を怠らないほうが安全だ。

このプラグインを使い続けるリスクは他にもあるか

Contact Form 7 のアドオンは多数の開発者によって提供されており、サポートや更新の頻度はプラグインごとにまちまちだ。決済を扱う以上、常に開発が継続され、すみやかにセキュリティパッチが提供されるプラグインを選ぶことが大前提となる。

この記事のポイント

  • Contact Form 7 PayPal & Stripe Add-on 2.4.9 以前に支払いバイパスの脆弱性がある
  • PayPal 通知の金額・通貨・受取人を検証しないため 0 円でも「支払い完了」になる
  • 修正済みの最新版(2.5.0 以降)に更新すれば問題は解消される
  • 更新前にバックアップを取り、バージョン番号を必ず確認する
  • 決済系プラグインは常に最新を保ち、定期的なログ照合を習慣化する
CSS @functionとalpha()、Grid Lanesの最新動向

CSS @functionとalpha()、Grid Lanesの最新動向

CSSは日々進化している。2026年6月半ば、CSSの関数定義を刷新する@functionや、透明度操作をシンプルにするalpha()、レイアウトの可能性を広げるGrid Lanes、対話要素の使い勝手を高める<dialog>の改良など、実務に直結する話題が相次いでいる。

これらの機能は、現時点ではブラウザ対応が完了していないものも含まれるが、開発体験を大きく変えるポテンシャルを持つ。とくに@functionは今年中にBaseline入りする可能性が高い機能として注目されている。この記事では、それらの仕組みと現場での活用イメージをまとめた。

CSS @functionの基礎と開発体験

CSS @functionの基礎と開発体験

CSSのカスタムファンクションを定義できる@functionルールが、2026年の大きなトピックの一つだ。従来のプリプロセッサ(Sassなど)に頼らず、ブラウザ上で直接再利用可能な関数を記述できる点が画期的である。Jane Ori氏が執筆した解説記事は、初心者にも理解しやすいステップバイステップ形式で、CSS-TricksのAlmanacにもドキュメントが用意されている。

@functionの書き方と基本構造

@functionは、入力値を受け取り、計算や変換を経て新たなCSS値を返す仕組みだ。基本的な構文は以下のようになる。

@function --my-function(--param1, --param2) {
  result: calc(var(--param1) + var(--param2));
}
従来の方法(Before)
毎回手動で計算
幅: 100% – 20px などを都度記述
↓
@function導入後(After)
関数を定義して再利用
width: calc(100% – var(–gap)); の代わりに関数適用

この例では、2つのパラメータを受け取り、calc()で合計を返すだけのシンプルな関数だが、より複雑な条件分岐やループ処理に相当するロジックも記述できるようになる見込みだ。開発者は、これまでJavaScriptやビルドツールに頼っていたスタイルロジックを、CSSのレイヤーで完結させられる。

実践で役立つユースケース

@functionが威力を発揮するのは、テーマのカラーパレット管理やレスポンシブな余白計算などの局面だ。たとえば、ブランドカラーをベースに明度や彩度を動的に調整する関数を定義すれば、ダークモードへの切り替えも数行で済む。

@function --tint(--color, --amount) {
  result: oklch(from var(--color) l, calc(c * var(--amount)), h);
}
関数による色生成デモ(概念イメージ)
基本色
彩度を下げた色(tint適用)
彩度を上げた色(tint適用)
※このデモは@functionの概念を視覚化したイメージです。実際の動作はブラウザの対応状況を確認してください。

@functionと@ifや@forといった制御ルールを組み合わせれば、Sassの関数に匹敵する表現力が手に入る。ビルドステップを減らせるため、サイトパフォーマンスの向上にも寄与するだろう。

alpha()関数がもたらす色指定の簡素化

alpha()関数がもたらす色指定の簡素化

CSSの色操作で長年煩わしかったのが、透明度(アルファチャンネル)の指定方法だ。alpha()関数は、このストレスを大幅に軽減する。これまで相対色構文で必須だった長い記述が、直感的な構文に置き換わる。

従来の相対色構文との比較

カスタムプロパティで色を管理している場合、透明度を変更するにはoklch(from var(--color) l c h / 0.5)のように、色空間とチャンネルを明示しなければならなかった。--colorに値だけを格納する回避策もあるが、結局はoklch()を毎回書く手間が残る。

/* 値だけを格納する方式 */
--color-values: 0.65 0.23 230;
color: oklch(var(--color-values));
color: oklch(var(--color-values) / 0.5);
/* 関数ごと格納する方式 */
--color: oklch(0.65 0.23 230);
color: var(--color);
color: oklch(from var(--color) l c h / 0.5); /* 冗長 */

alpha()を使えば、色空間やチャンネルを意識せずに済む。Jason Leo氏のコメントにもあるように、コードの意図が明確になり、宣言も短くなる。

color: alpha(from var(--color) / 0.5);
Before(相対色構文)
oklch(from var(--color) l c h / 0.5)
色空間と全チャンネルを列挙する必要あり
↓
After(alpha()関数)
alpha(from var(--color) / 0.5)
短く、意図が明確

alpha()はAdam Argyle氏が言及した機能で、色フォーマットに依存しない透過度の指定を実現する。カラーデザインシステムを扱うプロジェクトでは、可読性と保守性の両面でメリットが大きい。

Grid Lanesで広がるレイアウトの選択肢

Grid Lanesで広がるレイアウトの選択肢

WebKitが公開した「Field Guide to Grid Lanes」は、以前「CSS Masonry Layout」と呼ばれていたレイアウト手法の解説サイトだ。一見するとCSSグリッドの応用に見えるが、要素を自然な流れで敷き詰めるPinterest風のレイアウトを実現する。

Grid Lanesの仕組みと実装例

グリッドレーンは、カラムは固定しつつ、アイテムの高さを内容に応じて自動調整し、空きスペースを詰めて表示する。従来のCSSグリッドでは、各アイテムの行トラックを手動で調整するか、JavaScriptで高さを計算する必要があった。

.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;
}
Grid Lanesのデモ(概念イメージ)
写真1
写真2
写真3
写真4
写真5
写真6
※このデモはgrid-template-rows: masonryを疑似的に再現したイメージです。ブラウザのサポート状況を確認してください。

WebKitのガイドには、写真ギャラリー、レシピ一覧、新聞スタイル、メガメニュー、タイムライン、ピンボードといった6つの実例デモが含まれている。各デモは最小限のコードで構築されており、実務への応用がしやすい。

レスポンシブ対応とフォールバック

グリッドレーンはまだ実験的な機能だが、プログレッシブエンハンスメントの考え方で導入できる。@supportsを使えば、非対応ブラウザでは従来のグリッドレイアウトにフォールバックさせることも可能だ。

.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

@supports (grid-template-rows: masonry) {
  .gallery {
    grid-template-rows: masonry;
  }
}

WordPressのブロックエディタで動的に生成されるコンテンツ一覧にも、このレイアウトを適用すれば、よりリッチなデザインを提供できる。とくにポートフォリオサイトやECサイトの商品一覧で効果を発揮するだろう。

<dialog>要素の品質向上テクニック

<dialog>要素の品質向上テクニック

モーダルダイアログやポップアップを実装する<dialog>要素が、さらに使いやすくなる。Una Kravets氏が紹介したclosedby属性とoverscroll-behavior: contain、Chris Coyier氏が解説したアニメーションテクニックを合わせて見ていこう。

closedby属性とスクロール制御

closedby属性は、ダイアログ外のクリック(ライトディスミス)やESCキー押下でダイアログを閉じる動作を制御する。従来はJavaScriptで一つひとつ実装していたが、closedby="any"を指定するだけで標準動作として利用できる(Safariは未対応)。

<dialog closedby="any">
  閉じる操作を簡略化したモーダル
</dialog>
従来の挙動(Before)
JSで閉じる処理が必要
スクロールバーの有無でレイアウトシフト発生
↓
改善後(After)
closedby=”any”で自動閉じ
overscroll-behavior: contain でスクロールを抑制

さらに、overscroll-behavior: containを併用すると、ダイアログ表示中に背面コンテンツがスクロールするのを防げる。コメントではscrollbar-gutter: stableでスクロールバーの有無によるレイアウトシフトを防ぐテクニックも紹介されている。

ダイアログのアニメーション実装

Chris Coyier氏がFrontend Mastersで公開したシリーズでは、@starting-styleを用いたスムーズな開閉アニメーションの手法を解説している。多くの開発者がつまずくポイントであるだけに、実例付きの解説は貴重だ。

dialog {
  transition: opacity 0.3s, transform 0.3s;
}

dialog[open] {
  opacity: 1;
  transform: scale(1);
}

@starting-style {
  dialog[open] {
    opacity: 0;
    transform: scale(0.9);
  }
}
t=0%(非表示)
ダイアログ(閉じている)
↓
t=50%(アニメーション中)
ダイアログ(フェードイン中)
↓
t=100%(表示完了)
ダイアログ(完全表示)

このアニメーションは実際に約0.3秒かけて連続的に実行される。@starting-styleで初期状態を定義することで、ブラウザが自動的に終了状態との間を補間する。ログインフォームやクッキー同意バナーなど、モーダルの表示が必要なコンポーネントで即座に活用できるテクニックだ。

CSS Day 2026とコミュニティの最新動向

CSS Day 2026とコミュニティの最新動向

毎年恒例のCSSコミュニティカンファレンス「CSS Day」が、2026年6月11日と12日にアムステルダムで開催された。今年はライブストリーミングがなかったものの、Bluesky上で多くの参加者がリアルタイムに情報を共有している。

講演スライドと舞台裏の共有

発表者のスライドや会場の様子は、#CSSDayのハッシュタグで検索できる。CSS-Tricksの記事には、登壇者のポートレート写真も掲載されており、イベントの雰囲気が伝わってくる。

現地参加できなかった日本の開発者にとっては、6月下旬に公開予定の録画が待ち遠しいところだ。新しい@functionや相対色構文に関するセッションがあったかどうかも気になるところで、動画公開後に改めて重要なポイントを整理したい。

CSS Wordleで遊びながらスキルアップ

CSS Wordleで遊びながらスキルアップ

学習ツールとして面白いのが、Sunkanmi Fafowora氏が作成した「CSS Wordle」だ。CSSのプロパティ名をWordle形式で当てるゲームで、CSS-Tricksの著者が「ここ一週間ずっとハマっている」と絶賛するほどの中毒性がある。

ゲームの仕組みと学習効果

CSS Wordleは、CSSプロパティのスペルを数回の試行で推測する。正解すると、そのプロパティの簡単な説明やブラウザ対応状況も表示されるため、遊びながら知識が広がる仕組みだ。

CSS Wordle 概念デモ
f l e x
g r i d
b o r d e r
各マスにCSSプロパティを当てはめていく

実務でCSSを扱うエンジニアはもちろん、これからCSSを学ぶ初心者にも最適なツールだ。隙間時間に数ラウンド遊ぶだけで、プロパティのスペルミスが減り、あまり使ったことのないプロパティにも触れるきっかけになる。

新たにBaseline入りしたCSS機能

新たにBaseline入りしたCSS機能

2026年6月時点で、いくつかのCSS機能が新たにBaseline(主要ブラウザで安定利用可能)に到達した。Chrome 149に含まれるこれらの機能は、実務への導入のハードルが大きく下がっている。

gap装飾と画像レンダリング

グリッドやフレックスアイテム間の溝に装飾を追加できる「Gap decorations」がBaseline入りし、image-rendering: crisp-edgesによるピクセルアートの鮮明表示も安定して使えるようになった。また、rect()関数とxywh()関数もBaselineに追加され、シェイプの定義が簡素化されている。

Baseline入り機能の関係図
Chrome 149 → Gap decorations crisp-edges rect()
※一部機能(path()によるshape-outside)はSafariやFirefoxでのサポートが未対応

一方で、path()を用いたshape-outsideやshape()はまだSafari・Firefoxでの対応が進んでいない。導入する際は@supportsでフォールバックを用意するのが無難だ。

この記事のポイント

  • @functionで独自のCSS関数を定義でき、ビルドツールへの依存を減らせる。
  • alpha()は色の透明度指定を短く直感的に書ける関数である。
  • Grid LanesはPinterest風のレイアウトをCSSだけで実現する新しい手法だ。
  • closedbyやoverscroll-behaviorで<dialog>のUXが大幅に改善される。
  • CSS Day 2026の録画は6月下旬公開予定、Blueskyでスライドや写真を確認できる。
  • CSS Wordleは楽しみながらCSSプロパティのスペルや知識を習得できるゲームだ。
Relevanssiで日本語検索クエリが原因のテーブルフルスキャンを防ぐ

Relevanssiで日本語検索クエリが原因のテーブルフルスキャンを防ぐ

—

Relevanssiで日本語だけの検索クエリがデータベースの全テーブルスキャンを引き起こす問題は、トークナイズ結果が空文字になるケースをカスタムコードで事前に検知し、SQLを発行せずに空の結果を返すことで根本的に回避できる。設定のチューニングと併用すれば、サイト全体の検索パフォーマンスを維持できる。

なぜ日本語の検索クエリでRelevanssiがテーブル全体を読み込むのか

なぜ日本語の検索クエリでRelevanssiがテーブル全体を読み込むのか

Relevanssiは登録された投稿のタイトルや本文を分解し、単語単位でインデックスを作る全文検索プラグインだ。英語などスペースで区切られた言語では問題なく機能するが、日本語や中国語、韓国語といったCJK(中国語・日本語・韓国語)テキストでは事情が異なる。

CJKの文字列は単語境界の空白が存在しないため、Relevanssiが検索クエリを受け取ると、内部のトークナイザ(単語への分割処理)で適切な単位に区切れないことがある。特に、形態素解析エンジンがインストールされていない標準環境では、クエリが解析不能と見なされ、トークンがゼロ個、つまり空の状態になりやすい。

この「空のクエリ」が問題の本質だ。Relevanssiの検索SQLでは、本来なら検索語に基づいてWHERE term = '検索語'のように絞り込む。しかしトークンが空になると、検索語を表す変数に何も入らず、SQLがWHERE term = termという常に真になる条件へと崩れる。結果としてwp_relevanssiテーブルの何百万行という全レコードを走査するフルスキャンに陥り、応答に数十秒かかる事態を引き起こす。

これはバグではなく、空のクエリに対するフォールバック(予備動作)が設計上考慮されていないために発生する。本来なら検索語が存在しないと判断された時点で、データベースに問い合わせず「該当なし」を返すのが望ましい。

検索クエリが空になるのをコードで検出し早期リターンする

検索クエリが空になるのをコードで検出し早期リターンする

最も確実な解決策は、RelevanssiがSQLを構築する前に検索クエリの内容をチェックし、有効なトークンがなければ検索処理を打ち切る仕組みをテーマのfunctions.phpに組み込むことだ。Relevanssiは複数のフィルターフックを提供しており、そのうちrelevanssi_search_okまたはrelevanssi_modify_wp_queryを利用する。

具体的な実装コードと設置手順

STEP 1 子テーマまたはカスタムプラグインの準備
↓
STEP 2 functions.php にフィルターフックを追加
↓
STEP 3 検索クエリのトークン有無を判定する条件を記述
↓
STEP 4 空の場合は検索をキャンセルし空結果を返す

このデモが示す流れで、コードを追加する。以下は実際に利用できる実装例だ。

add_filter( 'relevanssi_search_ok', function( $ok, $query ) {
    // 検索クエリが文字列であり、内容が空でないか確認する
    if ( ! is_string( $query->query_vars['s'] ) || '' === trim( $query->query_vars['s'] ) ) {
        return false; // 検索を実行せず早期リターン
    }

    // スペースを除いたテキストがCJK文字だけで構成されているか簡易チェック
    $search_term = trim( $query->query_vars['s'] );
    // CJK統合漢字・ひらがな・カタカナ・ハングルの正規表現
    $cjk_pattern = '/[\x{4e00}-\x{9faf}\x{3040}-\x{309f}\x{30a0}-\x{30ff}\x{ac00}-\x{d7af}]+/u';
    preg_match_all( $cjk_pattern, $search_term, $matches );

    // マッチしたCJK文字列が存在するかを確認
    if ( empty( $matches[0] ) ) {
        // CJK文字がなければ通常の検索を続行
        return $ok;
    }

    // 簡易的なトークン判定: Relevanssiが実際に使うトークナイザを再現
    // ここではCJKクエリが本当にインデックス可能か簡易判定する
    $tokens = relevanssi_tokenize( $search_term, true );
    if ( empty( $tokens[0] ) ) {
        return false; // 有効なトークンがないため検索中止
    }

    return $ok;
}, 10, 2 );

このコードでは、Relevanssiの内部関数relevanssi_tokenize()を呼び出し、実際に検索に使われるトークンが生成されるかどうかを見ている。もし空の配列が返ってきたら、それは全テーブルスキャンを引き起こす危険な状態だと判断し、falseを返すことで検索SQLの実行そのものをブロックする。

もうひとつ重要なのは、relevanssi_search_okフィルターがSQL構築の直前で動作するため、無駄なクエリがデータベースに発行される前に検索を止められる点だ。サイトの規模が大きく、wp_relevanssiテーブルが数百万行を超える場合でも、安全に空の結果を返せるようになる。

テーマの functions.php に追加する際の注意点

コードは必ず子テーマのfunctions.phpまたは専用のカスタムプラグインに記述する。親テーマのfunctions.phpを直接編集すると、テーマのアップデートで変更が失われる。また、PHPのバージョンが7.4以上であることをあらかじめ確認しておく。

コードを追加したら、日本語だけで構成された検索クエリを実際に投げてみる。検索結果がゼロ件で返ってくることを確認し、同時にMySQLのスロークエリログやQuery Monitorプラグインで、フルスキャンが発生していないかチェックすると確実だ。

データベースの負荷を根本的に下げるRelevanssiの設定

データベースの負荷を根本的に下げるRelevanssiの設定

コードによる早期リターンと並行して、インデックスと検索設定そのものを見直すことで、CJKクエリ以外の場面でもパフォーマンスを向上させられる。

最小文字数制限をCJKに合わせて調整する

Relevanssiの管理画面には「インデックスを作成する最小文字数」という設定がある。デフォルトでは2文字程度に設定されていることが多いが、CJK環境では1文字でも意味を持つ(例: 「本」「水」など)ため、1に下げるのが基本だ。ただし、1文字にするとインデックスサイズが膨張しやすいため、サイトの投稿規模に応じて2以上にするか、あるいは後述の文字種フィルタリングと組み合わせる。

検索から除外する投稿タイプやステータスを絞る

wp_relevanssiテーブルが肥大化する大きな要因は、リビジョンや自動下書き、非公開のカスタム投稿タイプまでインデックスに含めているケースだ。設定画面の「インデックスを作成する投稿タイプ」で、実際にサイトのフロントエンド検索で必要になる投稿タイプと公開済みのものだけに限定する。リビジョンが無駄に行を占有しているだけで、テーブルサイズが数割変わることもある。

MySQL / MariaDB のバッファ設定を最適化する

13万投稿、1300万行のインデックスを持つ規模では、サーバーのデータベース設定そのものがボトルネックになる。特にinnodb_buffer_pool_sizeをサーバーの物理メモリの70%程度に設定し、Relevanssiのテーブル全体がメモリに収まるようにすると、たとえスキャンが発生してもディスクI/Oを避けられる。設定変更は必ず本番環境でテストした後に適用する。

よくある質問

コードを追加した後、通常の英語検索に影響はないか

上記のコードは、トークンが空になる場合にのみ検索を中止する。英語のスペース区切りクエリや、英数字が混在する日本語クエリでは通常どおりRelevanssiのインデックスが使われるため、影響はない。万が一、正常な検索がブロックされていると感じたら、relevanssi_tokenize()の結果をエラーログに出力して確認する。

Relevanssi以外の全文検索プラグインでもこの問題は起こるのか

起こりうる。特にPHPベースのトークナイザに依存するプラグインでは、CJK文字の分割に失敗すると同様の空クエリ問題が発生する可能性がある。検索プラグインを選定する際は、形態素解析(MeCabなど)に対応しているか、もしくは外部の検索エンジン(Elasticsearch、Algoliaなど)と統合できるかを基準にするとよい。

大量のクローラーからCJKクエリを繰り返し受けている場合の対策は

検索クエリが空になるパターンは、ボットがランダムな文字列や日本語の記事タイトルを検索ボックスに投げ込むことで頻発する。コードによる早期リターンでサーバー負荷は防げるが、さらにCloudflareやWAFのレート制限で同一IPからの過剰な検索リクエストを制限すると、クローラー起因のリソース浪費全体を抑えられる。

functions.php を触れない環境で他にできることはあるか

管理画面のRelevanssi設定で「検索を許可する最低文字数」を意図的に上げる(例: 3文字)方法がある。ただし、これは短い日本語の単語が検索できなくなる副作用を伴う。根本解決にはならないが、緊急のパフォーマンス低下を抑える応急処置としては有効だ。

この記事のポイント

  • 日本語のみの検索クエリでRelevanssiが全テーブルスキャンに陥る根本原因は、トークナイズ結果が空になりSQLが常に真になるため
  • カスタムコードでSQL実行前に空トークンを検出し、早期リターンさせることでデータベース負荷を回避できる
  • インデックスの最小文字数制限や対象投稿タイプの絞り込みをCJK向けに最適化すると、さらなるパフォーマンス改善につながる
  • コード追加後も通常の英数字検索には影響を与えず、安全に運用できる
  • クローラーからの大量アクセスに対してはWAFやレート制限との併用が効果的
CSSスクロールトリガーアニメーション入門、Chrome 146で実装

CSSスクロールトリガーアニメーション入門、Chrome 146で実装

Chrome 146で、CSSによるスクロールトリガーアニメーションが実装された。これは要素がビューポート内に入ったことをきっかけに、指定した時間だけアニメーションを再生する仕組みだ。従来のスクロール駆動アニメーションとは動作原理が異なる。

スクロール駆動アニメーションが「スクロール位置に合わせてアニメーションの進行度が変化する」のに対し、スクロールトリガーアニメーションは「特定のスクロール地点でアニメーションを発火させる」点が特徴だ。JavaScriptのIntersection Observer APIをCSSで再現したような動きになる。

この記事では、両者の違いを比較したうえで、スクロールトリガーアニメーションの基本的な使い方から応用的なテクニックまでを解説する。複数要素の連動やタイムライン範囲の調整など、実践で役立つ手法をまとめた。

スクロールトリガーアニメーションとスクロール駆動アニメーションの違い

スクロールトリガーアニメーションとスクロール駆動アニメーションの違い

まず、両者の動作の違いを明確にしておく。混同しやすい概念だが、設計思想が根本的に異なる。

スクロール駆動アニメーションの基本動作

スクロール駆動アニメーションは、animation-timeline: view() や animation-timeline: scroll() を使って、スクロール量や要素の交差度合いにアニメーションの進行を同期させる。スクロールが進むほどアニメーションも進み、戻せばアニメーションも戻る。再生時間という概念はなく、ユーザーのスクロール操作がそのままタイムラインになる。

たとえば、画面下から現れた要素が完全に見えるまでフェードインする、といった表現が得意だ。スクロールに吸い付くような動きで、ユーザーに自然なフィードバックを返せる。

スクロールトリガーアニメーションの基本動作

一方、スクロールトリガーアニメーションは、要素が特定のスクロール位置に達した瞬間にアニメーションを開始する。キーになるのは timeline-trigger: view() プロパティだ。これは「要素がビューポート内にどの程度入っているか」を監視し、指定したしきい値を超えた時点でアニメーションを発火させる。

重要なのは、アニメーションが固定の再生時間を持つことだ。たとえば300msかけて背景色を変える、といった指定ができる。スクロール量に進行が左右されないため、発火後の動きは常に一定になる。これにより、スクロール駆動アニメーションでは実現が難しかった「要素が現れた瞬間に一瞬だけフラッシュさせる」といった演出も容易になる。

スクロール駆動アニメーション
スクロール量 → アニメーション進行度
スクロールに比例して0%〜100%まで連続的に変化。時間の概念はない。
↓
スクロールトリガーアニメーション
しきい値到達 → アニメーション発火 → 固定時間で再生
指定したしきい値を超えたら300msなどの固定時間でアニメーションを再生。スクロール量に比例しない。

この概念図では、両者のトリガー条件と進行方法の違いを示している。スクロール駆動は連続的、スクロールトリガーは離散的という理解で問題ない。

基本構文とアニメーションアクション

基本構文とアニメーションアクション

スクロールトリガーアニメーションの最小構成は、@keyframes でアニメーションを定義し、timeline-trigger と animation-trigger で発火条件を指定する、という流れになる。

基本例とプロパティの役割

たとえば、正方形の要素が完全にビューポートに入った瞬間に、背景色が300msかけてフェードインするアニメーションを考える。コードの基本形は以下のようになる。

/* アニメーションの定義 */
@keyframes fade-bg-in {
  to {
    background: currentColor;
  }
}

.square {
  /* アニメーションの宣言 */
  animation: fade-bg-in 300ms;

  /* 発火条件の定義 */
  timeline-trigger: --trigger view() entry 100% exit 0%;

  /* 発火時の動作設定 */
  animation-trigger: --trigger play-forwards;
}

timeline-trigger の値で指定している entry 100% exit 0% はタイムライン範囲と呼ばれる。これは「要素の下端がビューポートに入った瞬間(entry 100%)から、上端がビューポートから出るまで(exit 0%)を発火可能な範囲とする」という意味だ。この範囲内に要素が入っているあいだ、アニメーションの再生が許可される。

animation-trigger に指定した play-forwards は、要素が完全に見えるたびにアニメーションを順方向(0%→100%)で再生するキーワードだ。ただし、このままではアニメーション終了後に背景色が元に戻ってしまう。スタイルを保持するには animation-fill-mode を併用する必要がある。

fill-mode と action の組み合わせ

CSS-Tricksの著者Carlo Daniele氏によると、fill-modeとアニメーションアクションの組み合わせが、スクロールトリガーアニメーションの挙動を大きく左右する。主な選択肢は以下の3パターンだ。

① フラッシュ型(fill-modeなし)
最初のデモのように、アニメーション終了後に元に戻る。一瞬の強調表示に向く。
animation: fade-bg-in 300ms;
② ロックイン型(forwards + play-once)
アニメーションが一度だけ再生され、その後スタイルが保持される。要素が出入りしても再発火しない。
animation: fade-bg-in 300ms forwards;
animation-trigger: --trigger play-once;
③ 往復型(forwards + play-forwards play-backwards)
要素が見えている間は順方向、見えなくなったら逆方向にアニメーション。チラつきなく自然な切り替えが可能。
animation: fade-bg-in 300ms forwards;
animation-trigger: --trigger play-forwards play-backwards;
■ フラッシュ型  ■ ロックイン型  ■ 往復型

往復型の play-forwards play-backwards は特に実用的だ。要素がビューポート外に出る際にアニメーションが逆再生されるため、ちらつきが発生しない。fill-modeを forwards にしていても、最終キーフレームが0%でも100%でも「完了時のスタイルを保持する」というルールが適用されるため、自然に動作する。

アクションキーワード一覧

animation-trigger に指定できるアクションキーワードは以下の表にまとめた。設計の幅を広げるために把握しておきたい。

アクション
効果
play-forwards
アニメーションを順方向(0%→100%)で再生
play-backwards
逆方向(100%→0%)で再生
play-once
順方向または逆方向のどちらか最初の一度だけ再生
play
最後に指定された方向で再生(未指定時は順方向)
pause
アニメーションを一時停止
reset
一時停止し、進行度を0にリセット
replay
進行度を0にリセットするが、一時停止はしない

これらのアクションを組み合わせることで、「スクロールに応じてアニメーションを途中で反転させる」「一度だけ発火させて二度と動かさない」といった細かな制御が可能になる。

複数要素への適用とスタッガー効果

複数要素への適用とスタッガー効果

スクロールトリガーアニメーションの真価は、複数要素を連動させた演出で発揮される。アクションやfill-modeが独立しているため、共通のトリガー設定を使い回しながら個別のアニメーションを割り当てられる。

CSSカスタムプロパティで設定を再利用する

たとえば、3つの正方形が順番に回転しながら拡大・背景変化する例を考える。各要素に個別のスタイルを書くのではなく、カスタムプロパティで共通設定をまとめると保守性が高まる。

.square {
  scale: 70%;
  --base-animation: intensify;
  animation: var(--base-animation) 300ms forwards;
  --animation-trigger: --trigger play-forwards play-backwards;
  animation-trigger: var(--animation-trigger), var(--animation-trigger);
  timeline-trigger: --trigger view();
  timeline-trigger-active-range-end: normal;
}

.square.rotate-left {
  animation-name: var(--base-animation), rotate-left;
}

.square.rotate-right {
  animation-name: var(--base-animation), rotate-right;
}

このコードでは、--animation-trigger に play-forwards play-backwards を格納し、animation-trigger でカンマ区切りによって2つのアニメーションに同じトリガー設定を適用している。これにより、メインのアニメーション(intensify)と回転アニメーションの両方が同じタイミングで発火する。

sibling-index() と sibling-count() による自動スタッガー

スクロールトリガーアニメーションでは、sibling-index() と sibling-count() という2つのCSS関数を使って、兄弟要素のインデックスと数を動的に取得できる。これを利用すると、各要素の発火タイミングを自動的にずらす「スタッガー」が実装可能だ。

.square {
  --stagger-interval: calc(100% / sibling-count());
  --entry: calc(sibling-index() * var(--stagger-interval));
  timeline-trigger: --trigger view() entry var(--entry) exit 0%;
}

sibling-count() で親要素内の.squareの数を取得し、それを100%で割ることで1要素あたりの間隔を算出する。次に sibling-index() で現在の要素が何番目かを取得し、間隔を掛け算して各要素の entry 値を動的に決定する。この仕組みがあれば、HTMLの要素数が変わっても手作業で値を調整する必要はない。

ただし、sibling-index() と sibling-count() はFirefoxで未サポートの点に注意が必要だ。プロダクションで使う場合は、フォールバックの指定を検討したい。

特定の要素をトリガーとして他を連動させる

さらに高度な使い方として、最初の要素だけをトリガーにして、残りの要素はアニメーション遅延で続けて発火させる方法がある。トリガー条件を1箇所に集約できるため、管理がしやすくなる。

.square:first-child {
  timeline-trigger: --trigger view() entry 50%;
  timeline-trigger-active-range-end: normal;
}

.square {
  --stagger-interval: calc(300ms / sibling-count());
  --animation-delay: calc(sibling-index() * var(--stagger-interval));
  animation: var(--base-animation) 300ms var(--animation-delay) forwards;
}

最初の要素がビューポートに50%入った時点でトリガーが発火し、残りの要素は animation-delay で順番にアニメーションを開始する。この方法なら、トリガー設定は最初の要素にだけ書けばよい。

ただし、CSS-Tricksの記事では play-backwards 状態のときに遅延が意図通り動作しない可能性が指摘されている。逆再生時にはdelayが含まれてしまい、スタッガーが崩れるようだ。今後のブラウザ実装の改善が待たれる。

タイムライン範囲の理解とカスタマイズ

タイムライン範囲の理解とカスタマイズ

スクロールトリガーアニメーションには、アクティベーション範囲(発火可能な範囲)とアクティブ範囲(発火後に有効であり続ける範囲)という2つのタイムライン範囲が存在する。この概念を理解しておくと、より精密なトリガー制御が可能になる。

アクティベーション範囲とアクティブ範囲の違い

アクティベーション範囲は「アニメーションが発火できるスクロール区間」を定義する。例えば entry 100% exit 0% は、要素が完全に見えてから完全に隠れるまでを発火可能区間とする。アクティブ範囲は「一度発火したアニメーションが、たとえアクティベーション範囲を外れても有効であり続ける区間」を指す。

アクティベーション範囲(発火可能区間)
アニメーションのトリガーが許可されるスクロール範囲。
例: entry 100% exit 0% は、要素の下端が入ってから上端が出るまで。
アクティブ範囲(有効区間)
アニメーションが発火したあとに、その状態が保持されるスクロール範囲。
timeline-trigger-active-range-end: normal; で制御可能。
■ 発火可能区間  ■ 有効区間

実際のところ、大半のユースケースでは view() entry 100% exit 0%(要素が完全に見える間)か view() contain(要素がビューポートより大きい場合も含めて交差している間)で十分だ。タイムライン範囲の詳細な制御が必要になるのは、特殊な演出や複雑なレイアウトに限られる。

view() 関数とオフセットの調整

view() 関数はビューポートを基準にしたタイムライン範囲を定義する関数だ。固定ヘッダーなどでビューポートの実質的な領域が狭まっている場合、view(y 0 5rem) のようにオフセットを指定できる。これにより、ヘッダーに隠れる部分を除いた「実際に見えている領域」を基準にできる。

たとえば、上部に高さ5remの固定ヘッダーがあるページでは、view(y 0 5rem) と書くことで、ヘッダーの裏に入った要素はまだトリガー範囲内と見なされない。この調整は、UIコンポーネントとスクロール演出を正確に同期させる際に役立つ。

この記事のポイント

  • スクロールトリガーアニメーションは、スクロール駆動アニメーションと異なり、固定時間のアニメーションを特定のスクロール地点で発火させる仕組みである
  • fill-modeとanimation-actionの組み合わせで、往復・ロックイン・フラッシュなど多彩な演出が可能
  • sibling-index()とsibling-count()を使えば、要素数に依存しない自動スタッガーを実装できる
  • 実用上はview() entry 100% exit 0%の指定で十分だが、固定ヘッダーがある場合はview()のオフセット調整を検討する
WooCommerce 11.0が商品オブジェクトキャッシュを標準化!新規ストアは自動有効

WooCommerce 11.0が商品オブジェクトキャッシュを標準化!新規ストアは自動有効

WooCommerce 11.0がリリースされ、商品オブジェクトキャッシュが新規ストア向けにデフォルトで有効化された。この機能は、商品ページやチェックアウト処理で同じ商品データを何度もデータベースから取得する無駄を省き、ECサイトの表示速度を底上げする。

可変商品がある製品ページでは約9〜12%、バンドル商品を含むチェックアウト処理では6〜12%の処理速度改善が報告されている。今回の変更は、WooCommerce 10.5で実験的導入が始まったキャッシュ機構が安定動作の段階に達したことを示している。

新規にWooCommerce 11.0以上をインストールしたストアには自動で適用されるが、アップグレードした既存ストアの設定は一切変更されない。必要に応じて管理画面から手動でオンにできる仕組みだ。

商品オブジェクトキャッシュの仕組みとパフォーマンス改善の数字

商品オブジェクトキャッシュの仕組みとパフォーマンス改善の数字

リクエスト内で商品データを使い回すメモリ内キャッシュ

このキャッシュは、一度のHTTPリクエストの間だけ生きている、揮発性のメモリ内キャッシュだ。wc_get_product(123)が呼ばれると、キャッシュに保存されていればデータベースに問い合わせず、すぐに商品オブジェクトの複製を返す。リクエストが終わればキャッシュは完全に消去されるため、次のリクエストで古い情報が残る心配はない。

特に、wc_get_product()を同じIDで何度もコールするパターンが多いテーマやプラグインで効果が大きい。各呼び出しが独立したオブジェクトのクローンを返すため、意図せず商品データの状態を共有してしまうバグも防げるようになった。

キャッシュなし(従来)
1回目 wc_get_product(123) → DBから取得(遅い)
2回目 wc_get_product(123) → DBから再取得(まだ遅い)
3回目 wc_get_product(123) → DBからまた取得
↓
キャッシュあり(WC 11.0)
1回目 wc_get_product(123) → DBから取得(初回のみ)
2回目 wc_get_product(123) → メモリ内キャッシュ(即返却)
3回目 wc_get_product(123) → メモリ内キャッシュ(高速)
※各呼び出しで返されるのは常に商品オブジェクトのクローン(複製)。呼び出し元どうしで状態が共有されることはない。

このデモは、同じ商品IDに対する繰り返し呼び出しがキャッシュによってどれだけ無駄を省けるかを示している。実際のECサイトでは、商品ループやセール情報の取得、決済フローの中で wc_get_product() が頻繁に呼ばれるため、体感速度の改善が期待できる。

実測値として9〜12%の高速化

WooCommerce 10.5の実験的導入時に公表されたパフォーマンス測定値は、今回の正式適用後も同じだ。可変商品(サイズや色のバリエーションがある商品)の製品ページでは、読み込み時間が9〜12%短縮された。バンドル商品を含むチェックアウト処理では6〜12%高速化されている。

この改善幅は、商品データを繰り返し取得する重いクエリがページ表示のボトルネックになっている状況で顕著だ。小規模なサイトでは効果が体感しにくいケースもあるが、商品数が多いストアや複雑な製品構成のサイトでは、目に見える速度向上が得られる。

WooCommerce 10.5から11.0への段階的な導入プロセス

WooCommerce 10.5から11.0への段階的な導入プロセス

10.5で実験的機能として登場、10.6で互換性の宣言が「互換」に

商品オブジェクトキャッシュは、WooCommerce 10.5で「実験的機能」として初めて公開された。当時はデフォルトで無効であり、ストア運営者が手動でオンにする必要があった。機能自体は、wc_get_product()の呼び出しをインターセプトし、リクエスト単位のメモリ内キャッシュからデータを返す仕組みだ。

WooCommerce 10.6では、この機能のプラグイン互換性宣言が「非互換」から「互換」に変更された。実験期間中に拡張機能エコシステム全体で互換性の問題が一切報告されなかったため、明示的に互換性を宣言していない拡張機能も、デフォルトで互換とみなされるようになった。

もし拡張機能が明示的に「この機能とは非互換」と宣言している場合は、WooCommerceの機能画面に従来通り非互換の通知が表示される。しかし、そのような宣言が必要になった拡張機能は見つかっていない。

11.0で新規ストアへの自動有効化を実装

WooCommerce 11.0のクリーンインストール時には、インストールプロセスの一環として商品オブジェクトキャッシュが自動で有効になる。機能登録自体は enabled_by_default => false のまま変更されていないが、新規インストール時に明示的に有効化が書き込まれる仕組みをとっている。

これは、HPOS(High-Performance Order Storage)など、他の機能がオプトインから新規インストール時デフォルトへ移行した際と同じパターンだ。バージョンアップだけでは既存ストアの設定を変更しない、慎重な設計が貫かれている。

既存ストアの挙動と手動有効化の手順

既存ストアの挙動と手動有効化の手順

アップグレードしても設定は一切変わらない

WooCommerce 11.0より前に構築されたストアは、11.0へアップグレードしても既存のキャッシュ設定がそのまま維持される。もし以前に無効だった(それが11.0以前のストアのデフォルト設定だ)なら、アップグレード後も無効のままだ。すでに手動で有効にしていたストアは、そのまま有効が継続される。

つまり、次の3パターンに整理できる。

  • WooCommerce 11.0以降を新規インストール → 自動的に有効(操作不要)
  • 既存ストアで機能が無効だった → アップグレード後も無効のまま(手動で有効にできる)
  • 既存ストアで機能が有効だった → アップグレード後も有効のまま(操作不要)

手動で有効化する方法

既存ストアでこの機能を試したい場合、管理画面の WooCommerce → 設定 → 詳細設定 → 機能 にアクセスし、「商品オブジェクトをキャッシュする(Cache Product Objects)」のトグルをオンにすればよい。ただし、設定変更後にサイト全体の動作を一通りチェックしておくことが推奨される。

手動有効化の流れ
STEP 1 WooCommerce → 設定 へ移動
↓
STEP 2 詳細設定 → 機能タブを開く
↓
STEP 3 「Cache Product Objects」をオンにする
↓
STEP 4 変更を保存して動作確認

トグルをオンにすると、その瞬間からリクエスト単位の商品キャッシュが働き始める。とくに、複数の拡張機能が同じ商品データにアクセスする大規模ストアでは、即効性のある改善が期待できるだろう。

拡張機能開発者への影響と注意点

拡張機能開発者への影響と注意点

標準APIを使っていればコード変更は不要

wc_get_product() やその他 WooCommerce 標準 API を通じて商品を取得している拡張機能は、このキャッシュの影響をまったく受けない。キャッシュは内部で透過的に動作し、呼び出し元には変わらず正しい商品オブジェクトが返る。

キャッシュから返されるのは、あくまで独立したクローンなので、取得した商品オブジェクトを編集しても他の処理に副作用が及ぶことはない。したがって、従来のコーディング規約に従っている拡張機能は、そのまま動作し続ける。

直接SQLを実行する拡張機能が注意すべきポイント

注意が必要なのは、WooCommerceのメタフックを経由せずに、商品データに対して直接SQLクエリを発行している拡張機能だ。これらのクエリはキャッシュの無効化フックを迂回するため、更新後のデータがキャッシュに反映されず、古い情報が返ってしまう可能性がある。

この問題は、商品オブジェクトキャッシュに限った話ではなく、WooCommerceのデータ整合性全般に関わる設計課題だ。該当する拡張機能を開発している場合は、標準の wc_get_product() やメタデータ更新用のAPIを使うことで、キャッシュの恩恵を受けつつ、データ不整合も回避できる。

今後のロードマップと全ストアへの有効化計画

今後のロードマップと全ストアへの有効化計画

データ蓄積後に全ストアで有効化へ

今回のリリースは通過点であり、最終的にはすべてのストア(既存ストアも含む)で商品オブジェクトキャッシュを有効化する計画が示されている。現時点で具体的な実施時期は明言されていないが、十分なストアでの稼働データが蓄積された段階で判断される。

すでに実験期間で問題が報告されていないこと、新規インストールのデフォルト有効化でさらなる実績が積み上がることを踏まえると、早ければ数バージョン後には全ユーザー対象の強制有効化に踏み切る可能性が高い。

問題が発生した場合の報告先

もし商品オブジェクトキャッシュに関連して予期せぬ挙動が見つかった場合、WooCommerceのGitHubリポジトリでIssueを報告してほしいと開発チームは呼びかけている。拡張機能開発者やストア運営者からのフィードバックが、今後の安定化に直結する。

この記事のポイント

  • WooCommerce 11.0 で商品オブジェクトキャッシュが新規ストア向けに自動有効化された
  • 可変商品の製品ページ読み込みは 9〜12% 高速化、バンドル商品のチェックアウトは 6〜12% 改善
  • 既存ストアはアップグレードしても設定変更なし、管理画面から手動でオンにできる
  • 標準の WooCommerce API を使う拡張機能はコード変更不要で動作する
  • 最終的には全ストアで有効化される予定で、Issue 報告を募っている
WooCommerceにEU契約撤回ボタンを無料で追加する方法

WooCommerceにEU契約撤回ボタンを無料で追加する方法

2026年6月19日からEU消費者へ販売するオンラインショップには、契約を撤回する「離脱ボタン」をストアフロントに設置する義務が発生する。WooCommerceには標準でこの機能がないため、無料の専用プラグインを見極めて導入すれば、技術的な難しい変更なしに対応できる。

なぜ2026年6月からEU向けWooCommerceに契約撤回ボタンが必要なのか

なぜ2026年6月からEU向けWooCommerceに契約撤回ボタンが必要なのか

EU指令2023/2673(従来の消費者権利指令に第11a条を追加)が、2026年6月19日以降にEU在住の消費者を対象に販売するすべての事業者に対して、契約を撤回するための「明確に表示されたワンクリック機能」の提供を義務付けている。これは商品の返品とは別に、契約そのものから離脱する手段を消費者に与えるものだ。

日本からEUへ越境ECを行う事業者も、現地の消費者をターゲットにしている限り例外ではない。WooCommerce単体ではこの離脱機能に対応しておらず、公式要望トラッカー上で議論は続いているものの、すぐに実装される見込みはない。そのためプラグインによる早期の対応が欠かせない状況になっている。

WooCommerce向け離脱ボタンプラグインで絶対に押さえるべき機能

WooCommerce向け離脱ボタンプラグインで絶対に押さえるべき機能

多数の無料プラグインが出回っているが、法令を満たすために最低限チェックするポイントは変わらない。見落としを防ぐために、以下の基準を事前にリストアップしておくことが大切だ。

ワンクリックで契約撤回が完了する仕組み

消費者がボタンを押すだけで、追加のフォーム入力や本人確認なしに撤回の意思表示が完了しなければならない。撤回の受付通知が自動的にメールで送られる仕組みも必須になる。

わかりやすく目立つボタン表示

「契約を撤回する」といったボタン文言が、注文確認画面やマイアカウントページなど、消費者が容易に見つけられる位置に常に表示される必要がある。テーマのスタイルに埋もれず、かつ法的に十分な表示であることが求められる。

GDPRおよび個人データ取り扱いへの配慮

離脱ボタンの動作に伴って取得される個人データ(注文ID、メールアドレスなど)の取り扱いがGDPRに準拠しているかも確認する。プラグインが不要なデータを保存していないか、またデータ保持期間の設定ができるかが重要な判断材料になる。

多言語対応と日本向けの翻訳品質

EU圏内で複数言語のサイトを運営する場合、ボタン文言や通知メールを各国語に切り替えられる多言語対応が必須になる。日本語で運用しているサイトでも、管理画面表示が適切に翻訳されているか、表示されるフロント文言が自然かを確かめておきたい。

更新の継続性とエコシステムとの相性

WordPress本体やWooCommerceのアップデートに追従しているか、アクティブインストール数や最終更新日を確認する。法典の変更に応じて仕様が変わる可能性もあるため、活発にメンテナンスされているプラグインを選ぶことで将来のリスクを抑えられる。

無料のEU契約撤回プラグインを安全に選んで導入する流れ

無料のEU契約撤回プラグインを安全に選んで導入する流れ

実際にプラグインを選ぶ際には、機能のチェックリストをクリアするだけでなく、自分のサイト環境で競合なく動作するかのテストがとても重要だ。以下の手順で進めれば、手戻りなく導入できる。

STEP 1 公式リポジトリで「withdrawal button」などのキーワードで複数の無料プラグインをリストアップする
↓
STEP 2 前述の必須機能を満たしているか、説明文とスクリーンショットで下調べする
↓
STEP 3 テスト環境またはステージングサイトでプラグインをインストールし、有効化する
↓
STEP 4 ボタンの表示位置や文言、撤回後の自動メール通知を確認し、必要に応じて外観やフックを調整する

上図は一般的な導入手順を示したイメージで、実際のプラグインによって設定画面の構成は異なる。

プラグイン導入後に必ずチェックする項目と表示カスタマイズのコツ

プラグイン導入後に必ずチェックする項目と表示カスタマイズのコツ

プラグインを有効化しただけでは、テーマの都合でボタンが正しく表示されなかったり、通知メールが迷惑メールに振り分けられたりするケースがある。以下のポイントを必ず実機で確認しておく。

Before(対応前)
注文確認ページに契約撤回の手段が一切表示されない
↓
After(プラグイン導入後)
「契約を撤回する」ボタンが目立つ位置に常時表示され、ワンクリックで撤回完了と通知が飛ぶ
■ 対応前 ■ 対応後

マイアカウントページと注文詳細画面の両方にボタンが現れるか

購入後の消費者がアクセスするマイアカウント内の注文一覧や個別注文画面、そしてゲスト購入者向けの注文確認ページの両方でボタンが機能するかを必ず検証する。プラグインによってはゲスト購入に対応していないこともあるため注意が必要だ。

撤回後のフローがEC事業者側にも通知されるか

消費者が撤回ボタンを押したあと、店舗運営者にメールや管理画面内の通知が届く仕組みになっているかも重要だ。対応が遅れるとトラブルに発展するため、通知が確実に飛ぶ設定になっているかを最初のテストでつかんでおく。

表示をCSSで微調整したい場合の注意

ボタンの色やサイズをテーマに合わせたいときは、追加CSSに直接スタイルを書いて調整するのが現実的な方法だ。ただし、プラグインが出力するHTMLのクラス名やIDはアップデートで変わることがあるため、子テーマのstyle.cssに依存しすぎないようにし、変更後は必ず再テストを行う。

よくある質問

WooCommerce用のEU離脱ボタンプラグインは本当に無料で使えますか

現在、WordPress公式リポジトリで複数の無料プラグインが公開されている。いずれも基本機能は無料で提供されており、有料版で追加機能が解放される場合もあるが、法令要件を満たすだけなら無料で十分対応できる。

ボタンの設置だけでEUの法律要件はすべて満たせますか

離脱ボタンは指令が求める機能の一部だ。合わせて返品ポリシーの明示や、撤回後の返金手続きを整備する必要がある。プラグインはあくまで技術的な「ボタンの提供」部分を解決するものだと理解しておくことが大事だ。

多言語サイトでボタン文言を日本語にしたい場合の対処法は

多くのプラグインは翻訳ファイルを内包しているか、管理画面でボタン文言を自由にカスタマイズできる。日本語の翻訳が不完全な場合はLoco Translateなどの別の翻訳プラグインを併用して、表示テキストだけを書き換えることも可能だ。

プラグインがWooCommerceの今後のアップデートで動かなくなる心配は

定期的に更新されているプラグインを選ぶことでリスクは下げられる。導入前に最終更新日とアクティブインストール数、サポートフォーラムの反応を確認し、万が一に備えてステージング環境を用意しておくのが堅実な運用だ。

この記事のポイント

  • 2026年6月19日からEU向け販売店に契約撤回ボタンの設置が義務化された
  • WooCommerce標準には機能がなく、無料プラグインでの対応が現実的な解決策
  • プラグイン選びではワンクリック完了、明確な表示、GDPR配慮、多言語対応をチェック
  • 導入後は表示場所とゲスト購入時の動作を必ずテストし、通知設定も確認する
  • 定期更新が続いているプラグインを選び、ステージング環境で動作検証を行う
MDN MCPサーバーでAIに正確なCSSブラウザ互換性情報を提供、開発効率が向上

MDN MCPサーバーでAIに正確なCSSブラウザ互換性情報を提供、開発効率が向上

MDN Web DocsがMCP(Model Context Protocol)サーバーを公開した。このサーバーを使うと、AIコーディングアシスタントにMDNの最新ドキュメントとブラウザ互換性データを直接読み込ませられる。CSSの新機能やブラウザサポートを正確に把握できるため、誤ったコード提案を防ぐことが可能だ。

特に、CSSの最新機能(light-dark()画像対応、:buffering疑似クラスなど)はLLMの学習データに含まれていないことが多い。MDN MCPを導入すれば、AIが正しい情報を参照して回答を生成するため、開発者はわざわざブラウザで互換性を調べる手間が省ける。

MDN MCPサーバーとは

MDN MCPサーバーとは
開発者の質問
「light-dark() CSS関数を画像で使う方法とブラウザサポートを知りたい」
↓
MDN MCPサーバーが呼ばれる(計4回)
MDNのドキュメントと互換性テーブルを取得し、AIアシスタントに正しい回答を生成させる
AIが外部の最新データを参照することで、学習データの鮮度不足を補える。

MCPはAIツールが外部データソースに接続するためのオープンスタンダードだ。MDN MCPサーバーはこのプロトコルを使って、MDNの豊富なWebプラットフォーム情報(HTML・CSS・JavaScript・Web APIのリファレンス、ブラウザ互換性データ)をAIエージェントやIDEに提供する。これにより、AIが常に最新のWeb標準に基づいてコードを提案できるようになる。

MCPの基本とMDNの役割

MCP(Model Context Protocol)はAnthropicが中心となって策定したオープンプロトコルで、LLMが外部ツールやデータベースと通信するための共通インタフェースを提供する。MDN MCPサーバーはHTTPトランスポートで動作し、クライアント(VS CodeやClaude Codeなど)がリクエストを送ると、MDNのコンテンツAPIから必要な情報を抽出して返す仕組みだ。

たとえば、AIが「CSSのlight-dark()は画像でも使えるか」と問われた場合、通常のLLMは学習時の知識だけを頼りにする。しかしMDN MCPサーバーが接続されていれば、AIはリアルタイムで正式な仕様とブラウザ実装状況を取得し、誤った回答を防げる。

対応しているツール一覧

MDN MCPサーバーは主要な開発ツールと連携する。エディタではVS Code、Zed、Cursorがサポートされており、AIコーディング支援機能から直接MDNを参照できる。ターミナルベースのエージェントとしてはClaude Code、OpenAI Codex CLI、Google Antigravity CLI(旧Gemini CLI)が対応。チャットアプリではClaude Desktopで利用可能だ。

これらのツールにMCPサーバーを登録する手順は各公式ドキュメントに記載されている。基本はHTTPエンドポイントを指定するだけで、追加のAPIキーなどは不要だ。

なぜ今、MCPが必要なのか

なぜ今、MCPが必要なのか

Webプラットフォームの進化は速い。CSSだけを見ても、light-dark()の画像対応、@view-transition、:buffering疑似クラスなど、直近1年以内に実装が始まった機能は多い。AIの学習データは数カ月から1年以上前の情報で固定されているため、こうした新機能に関する質問には正確に答えられない可能性がある。

MDN Blogの記事では、Claude Code Opus 4.7を用いてテストを行った結果、MCPなしではWeb Serial APIについて「Firefoxでは未実装で、Mozillaの標準ポジションでは有害とされている」と誤った回答をしたと報告されている。実際にはFirefox 151でサポートが開始されており、MCPを有効にすることでこの誤りは解消された。

AIの回答が誤っていると、開発者はブラウザの実装状況を手動で調べ直す必要が生じる。MDN MCPはその手間を省き、AIが確かなソースに基づいて回答する仕組みを提供する。

実際のCSS機能で検証、MCP有無の比較

実際のCSS機能で検証、MCP有無の比較

light-dark()画像対応のブラウザサポート

light-dark()はカラースキームに応じて値を切り替えるCSS関数だが、画像も受け付ける。たとえば次のように書ける。

.profile-avatar {
  background-image: light-dark(url(avatar-light.png), url(avatar-dark.png));
}
ライトモード時の表示イメージ
‘); background-size:cover; border:3px solid #ccc; box-sizing:border-box;”>
明るい背景に合わせた画像が表示される
↓
ダークモード時の表示イメージ
‘); background-size:cover; border:3px solid #666; box-sizing:border-box;”>
暗い背景に合わせた画像が表示される

light-dark()はOSのカラースキームに応じて自動で画像を切り替える。画像以外にもグラデーションやURLが使用可能だ。

このlight-dark()の画像対応について、Claude CodeにMCPなしで質問した場合、色の値に関する説明しか得られず、画像がサポートされていることは明確に示されなかった。一方、MCPを有効にすると、Firefox 150以降、Chrome(フラグ付き)でサポートされていることが即座に回答された。

:buffering疑似クラスとWeb Serial APIの誤情報

:buffering疑似クラスは、メディア要素がバッファリング中であることを検出するため、MCPなしでも正しいブラウザサポート情報が返された数少ない事例だ。しかしshadowrootslotassignment属性やWeb Serial APIについては、MCPなしでは誤った情報が目立った。

MCPなし(Before)
「Web Serial APIはFirefoxで未実装。Mozillaは有害と判断している」
「shadowrootslotassignmentはChrome 120、Safari 18.3でサポート」
※いずれも誤った情報
↓
MCPあり(After)
「Web Serial APIはFirefox 151でサポート開始」
「shadowrootslotassignmentはFirefox 151が初の対応ブラウザ」

MCPを導入すると、最新のブラウザ互換性データが参照されるため、誤情報を防げる。

特にWeb Serial APIのケースでは、MCPなしのAIは「有害」という強い表現を使ってまで非対応と主張しており、誤った知識で開発を妨げるリスクがあった。MDN MCPはこのような誤解を回避し、確かな情報に基づいたコーディング支援を実現する。

導入方法と活用のポイント

導入方法と活用のポイント

Claude Codeでの設定手順

MDN MCPサーバーはHTTPエンドポイントが公開されており、対応クライアントでMCPサーバーとして追加するだけで利用できる。たとえばClaude Codeの場合、次のコマンドをターミナルで実行する。

claude mcp add --transport http mdn https://mcp.mdn.mozilla.net/

この設定後、AIアシスタントがMDNの情報を必要とする質問を受け取ると、自動的にMCPサーバーへリクエストが送られ、最新のドキュメントが参照される。他のエディタやCLIツールでも同様に、MCPサーバーのURLを登録するだけで連携が完了する。

プライバシーと注意点

現在のMDN MCPサーバーは実験的な提供段階であり、使用時にはMDNのプライバシー通知を確認することが推奨されている。サーバーは利用者が送信したクエリを一時的に処理するが、データの取り扱いについては今後アップデートされる可能性がある。

また、MCPが参照するデータはMDNの公式コンテンツとブラウザ互換性テーブルであるため、正確だが、あくまでAIの出力はLLMの生成結果である点に注意が必要だ。複数の情報源と組み合わせながら活用するのが賢い使い方といえる。

この記事のポイント

  • MDN MCPサーバーは、AIツールにMDNの最新ドキュメントとブラウザ互換性データを提供する。
  • CSSの新機能(light-dark()画像対応、:bufferingなど)の正確な情報を得られる。
  • MCPなしではWeb Serial APIのように「未実装」と誤った回答をするケースがあった。
  • VS CodeやClaude Codeなど主要な開発ツールで利用可能。導入はURL登録のみ。
  • AIの回答が古い知識に依存するリスクを減らし、開発効率を高める。
WooCommerce MyParcelで重大エラーが出た時のデフォルト配送業者設定方法

WooCommerce MyParcelで重大エラーが出た時のデフォルト配送業者設定方法

WooCommerce の MyParcel プラグイン使用時に表示される「このサイトで重大なエラーが発生しました」というエラーは、プラグイン内にデフォルトの配送業者が設定されていないことが原因だ。プラグイン設定画面からデフォルトの配送業者を選択すれば、エラーはすぐに解消する。

なぜデフォルト配送業者が未設定だとエラーになるのか

なぜデフォルト配送業者が未設定だとエラーになるのか

このエラーは PHP の致命的エラー(Fatal Error)であり、MyParcel プラグインが「No default carrier available(利用可能なデフォルトの配送業者がない)」という例外を発生させて停止している。スタックトレースを追うと、発端は受注確認ページ(サンキューページ)などで追跡情報を表示しようとする際、プラグインが内部的に呼び出す getDefaultCarrierOrThrow() メソッドで落ちている。

MyParcel は配送ラベル作成や追跡情報の連携を行うプラグインであり、動作には「どの配送業者をデフォルトで使うか」という情報が必須だ。この設定を一度も行っていなかったり、アップデート時に何らかの理由で消えたりすると、サイトの該当ページでエラーが表示される。

≪ エラー発生時 ≫
MyParcel プラグインがデフォルトの配送業者を取得できず、例外をスロー
↓
≪ 設定後 ≫
デフォルト配送業者が設定され、プラグインが正常に動作
■ 設定未完了状態 ■ 設定完了後

デフォルト配送業者を設定する具体的な手順

デフォルト配送業者を設定する具体的な手順
STEP 1 WordPress 管理画面にログインし、左メニューから「WooCommerce」→「MyParcel」を開く
↓
STEP 2 「設定」タブを選択し、「デフォルトの配送業者」項目を探す
↓
STEP 3 プルダウンから利用する配送業者(例: ヤマト運輸や佐川急便など契約中のもの)を選択する
↓
STEP 4 画面下部の「変更を保存」をクリックし、エラーが消えたか確認する

管理画面にアクセスできる状態であれば、この手順だけでエラーは即座に解消する。設定項目の名称はプラグインバージョンによって「デフォルトの配送業者」「Default Carrier」などと表記が異なるが、いずれも一つのプルダウン形式で表示される。

管理画面にすらアクセスできない場合の対処

エラーがサイト全体に影響し、管理画面も真っ白になってしまうケースがある。その場合は FTP またはサーバーのファイルマネージャーを使い、一時的に MyParcel プラグインのフォルダをリネームして無効化する。

  • サーバーに接続し、/wp-content/plugins/ ディレクトリへ移動する
  • woocommerce-myparcel フォルダを woocommerce-myparcel_deactivated などに変更する
  • これでプラグインが停止し、管理画面へアクセスできるようになる
  • 管理画面に入れたら、上の STEP 手順で設定を行い、フォルダ名を元に戻して有効化する

設定を保存してもエラーが再発する場合

設定保存後に再び同じエラーが発生するなら、プラグインまたは関連データベース設定に不整合が起きている可能性が高い。以下の順で追加対応を試す。

  • 一度プラグインを完全に削除し、最新バージョンを再インストールする
  • WooCommerce のシステムステータス画面で、不要なトランジェント(期限付きキャッシュ)をクリアする
  • MyParcel アカウントとの API 接続情報(API キーなど)を再入力する

エラーを未然に防ぐための注意点

エラーを未然に防ぐための注意点

プラグインのメジャーアップデート後や WordPress 本体の自動更新後に、こうした設定がリセットされる事例は珍しくない。MyParcel に限らず、配送系・決済系プラグインは「接続先のデフォルト設定」が必須となるものが多い。アップデート後はテスト環境や低トラフィック時間帯に決済フローとサンキューページの動作を一通り確認する習慣をつけると安心だ。

よくある質問

エラーメッセージが英語で「No default carrier available」と表示されているが日本語環境でも同じ?

日本語環境の WordPress でも管理画面やログに表示されるエラーメッセージは英語のままになる。ただしサイト訪問者には「このサイトで重大なエラーが発生しました」という日本語の汎用エラー画面が表示されるため、管理者はサーバーのエラーログやデバッグモードで英語エラーを確認することになる。

MyParcel 以外の配送プラグインでも同様のエラーは起こる?

配送ラベル生成や追跡機能を持つプラグインは、内部で配送業者を特定する仕組みに依存していることが多く、設定不足で同種のエラーが起きる可能性がある。具体的には「デフォルトの配送業者」「デフォルトの配送方法」が未選択であると、ページ表示時に致命的エラーになる構造は共通している。

Divi テーマを使っていることがエラーと関係ある?

スタックトレースに Divi のパスが含まれているのは、サンキューページを Divi の WooCommerce モジュールで構築しているためだ。エラーの根本原因はあくまで MyParcel プラグイン側の設定不足であり、Divi そのものに問題があるわけではない。

デフォルトの配送業者を設定しても配送ラベルが発行できない

デフォルト配送業者の設定はエラー解消の第一歩だが、実際にラベルを発行するには MyParcel アカウントとの正しい API 接続と、WooCommerce の配送クラスや商品重量の設定が必要になる。エラーが消えた後は、MyParcel の管理画面で接続ステータスが「アクティブ」になっているか確認する。

この記事のポイント

  • PHP の致命的エラーは MyParcel のデフォルト配送業者未設定が原因
  • 管理画面の MyParcel 設定からデフォルト配送業者を選択して保存すれば解決
  • 管理画面に入れない場合はプラグインフォルダのリネームで一時無効化する
  • アップデート後は配送系プラグインの設定リセットに注意が必要