<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>yuheijotaki.com</title><description>主にウェブデザインや技術についてのブログサイトです。</description><link>https://yuheijotaki.com/</link><language>ja</language><item><title>Vertex AI Search でサイト内検索を実装してみる</title><link>https://yuheijotaki.com/blog/2026022001_vertex-ai-search/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2026022001_vertex-ai-search/</guid><description>Google Cloud の Vertex AI Search（Discovery Engine API）を使い、Astro でサイト内検索デモを実装してみる。</description><pubDate>Tue, 24 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;Google Cloud の &lt;a href=&quot;https://docs.cloud.google.com/generative-ai-app-builder/docs?hl=ja&quot;&gt;Vertex AI Search&lt;/a&gt;（Discovery Engine API）を使ったサイト内検索を作ってみた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/demo/vertex-ai-search/&quot;&gt;デモ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/commit/ceb6c4df2c8c68f3cc17414659a2a7bb164b572b&quot;&gt;コミット&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;構成&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;フロント
&lt;ul&gt;
&lt;li&gt;Astro SSG のページで &lt;code&gt;/api/search&lt;/code&gt; を叩く&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;バックエンド
&lt;ul&gt;
&lt;li&gt;Vercel Functions（&lt;code&gt;api/search.ts&lt;/code&gt;） が認証トークンを取得して Discovery Engine API に POST&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;認証
&lt;ul&gt;
&lt;li&gt;Google Cloud サービスアカウントの JSON 鍵を Vercel 環境変数に保存し、&lt;code&gt;google-auth-library&lt;/code&gt; でアクセストークンを取得&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Google Cloud 側の準備&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Discovery Engine API を有効化する
&lt;ul&gt;
&lt;li&gt;Google Cloud コンソールの API ライブラリから有効化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;データストアを作成する
&lt;ul&gt;
&lt;li&gt;ウェブサイトクロール型を選択し、クロール対象を &lt;code&gt;yuheijotaki.com/*&lt;/code&gt; に設定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;検索アプリを作成する
&lt;ul&gt;
&lt;li&gt;データストアと接続し、プロジェクト ID を控えておく&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;サービスアカウントを作成する
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;roles/discoveryengine.viewer&lt;/code&gt; ロールを付与し、JSON 鍵をダウンロード&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Vercel 環境変数に登録する
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GOOGLE_SERVICE_ACCOUNT_KEY&lt;/code&gt;（JSON 鍵の中身）と &lt;code&gt;VERTEX_AI_SEARCH_ENGINE_ID&lt;/code&gt;（プロジェクト ID）を設定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;所感など&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ウィジェット埋め込みと API 2種類の統合形式がある&lt;/li&gt;
&lt;li&gt;ウェブクロール後（インデックス作成後）に検索が可能となる。だいたい8時間ほどかかる&lt;/li&gt;
&lt;li&gt;ページの取得件数は上限は100件まで（&lt;a href=&quot;https://docs.cloud.google.com/retail/docs/reference/rest/v2/projects.locations.catalogs.placements/predict#request-body&quot;&gt;参考&lt;/a&gt;）
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;filter&lt;/code&gt; 使えば特定階層のみに絞ったクエリも投げれそう&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ページの取得順はデフォルトで関連度順になる。ランク付けをしたりすることも可能&lt;/li&gt;
&lt;li&gt;サイト内検索の場合の料金（&lt;a href=&quot;https://cloud.google.com/generative-ai-app-builder/pricing?hl=ja&quot;&gt;参考&lt;/a&gt;）
&lt;ul&gt;
&lt;li&gt;データストアの容量は月 10 GiB まで無料&lt;/li&gt;
&lt;li&gt;Standard Edition ではなく Enterprise Edition（$4.00 / 1,000 クエリ）が必須。月 10,000 クエリまで無料&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;データソースは今回はウェブサイトを選択しているが、BigQuery や Cloud Storage も選択可能で、データソースの種類に合わせてAIを使った検索や会話機能を作れるAPIといったものらしい&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>pitcms を試してみる</title><link>https://yuheijotaki.com/blog/2026020901_pitcms/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2026020901_pitcms/</guid><description>pitcms を試した雑感です。</description><pubDate>Mon, 09 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;pitcms とは&lt;/h2&gt;
&lt;p&gt;GitHub と連携してコンテンツを管理できる日本製ヘッドレスCMS&lt;br /&gt;
公式サイト：&lt;a href=&quot;https://pitcms.net/&quot;&gt;pitcms&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;導入から設定まで&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pitcms.net/docs/getting-started/installation&quot;&gt;導入する | pitcms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pitcms.net/docs/getting-started/project&quot;&gt;各機能の設定 | pitcms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;入稿から反映まで&lt;/h2&gt;
&lt;p&gt;今回はデプロイ先、プレビュー環境を Cloudflare Pages にした。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;pitcms の管理画面で「編集セッション」を作成&lt;/li&gt;
&lt;li&gt;コレクション内の記事を編集&lt;/li&gt;
&lt;li&gt;記事の保存後にプレビューURLが発行されるので確認（ &lt;code&gt;https://pitcms-***.***.pages.dev/&lt;/code&gt; など ）&lt;/li&gt;
&lt;li&gt;確認後、編集セッションの「変更を反映」&lt;/li&gt;
&lt;li&gt;本番環境にデプロイされる&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;git の動きとしては、3. の段階でプレビューブランチが作成、5.の段階で main ブランチへマージされる&lt;/p&gt;
&lt;h2&gt;デモ&lt;/h2&gt;
&lt;p&gt;Astro の Content Collections（SSG）と組み合わせて使ってみた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;デモサイト：&lt;a href=&quot;https://pitcms-sample.pages.dev/&quot;&gt;pitcms-sample.pages.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;リポジトリ：&lt;a href=&quot;https://github.com/yuheijotaki/pitcms-sample&quot;&gt;yuheijotaki/pitcms-sample&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;分かったこと・所感&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;コレクションのスキーマはルートに置く pitcms.jsonc ファイルで定義する&lt;/li&gt;
&lt;li&gt;プレビュー環境の対応は Cloudflare Pages の他に、Vercel、Netlify、Cloudflare Workers が選択できる。1クリックで設定できるので楽&lt;/li&gt;
&lt;li&gt;GitHub のコンテンツをデータソースとするため、例えばローカルで記事編集してプッシュすると pitcms の管理画面に反映される仕組み&lt;/li&gt;
&lt;li&gt;編集セッションの概念が最初はとっつきにくいが、使って理解すると理にかなっているように思えた&lt;/li&gt;
&lt;li&gt;Astro の Content Collections との相性がよさそう&lt;/li&gt;
&lt;li&gt;TinaCMS（TinaCloud）に近い感じがする&lt;/li&gt;
&lt;li&gt;プランはコレクション（API）3つ、メンバー3人などの制限がある Free プラン、それらの数が無制限の Proプラン（¥980/月）がある&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Astro Live Content Collections を試してみる</title><link>https://yuheijotaki.com/blog/2026011501_live-content-collections/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2026011501_live-content-collections/</guid><description>Astro 5.10 で追加された Live Content Collections の実験的機能を試した雑感です。</description><pubDate>Thu, 15 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;Astro 5.10 で追加された &lt;a href=&quot;https://docs.astro.build/en/reference/experimental-flags/live-content-collections/&quot;&gt;Live Content Collections&lt;/a&gt; を試してみた。Live Content Collections はビルド時ではなくリクエスト時にデータを取得できる機能（v5 系だと要 experimental フラグ）。&lt;/p&gt;
&lt;h2&gt;Live Content Collections とは&lt;/h2&gt;
&lt;h3&gt;従来の Content Collections&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;データはビルド時に取得される&lt;/li&gt;
&lt;li&gt;データストアに保存される&lt;/li&gt;
&lt;li&gt;静的なコンテンツに最適&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Live Content Collections&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;データはリクエスト時に取得される&lt;/li&gt;
&lt;li&gt;データストアには保存されない&lt;/li&gt;
&lt;li&gt;常に最新のデータを取得できる&lt;/li&gt;
&lt;li&gt;頻繁に更新されるコンテンツに最適&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;詳細： &lt;a href=&quot;https://astro.build/blog/live-content-collections-deep-dive/&quot;&gt;Live Content Collections: A Deep Dive | Astro&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;環境構築&lt;/h2&gt;
&lt;p&gt;SSR アダプターとして今回は Vercel を使用する。&lt;/p&gt;
&lt;h3&gt;設定&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;astro.config.mjs&lt;/code&gt; に実験的フラグを追加する。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export default defineConfig({
  adapter: vercel(),
  experimental: {
    liveContentCollections: true,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/blob/main/src/live.config.ts&quot;&gt;src/live.config.ts&lt;/a&gt; にライブコレクションを定義する。（従来の &lt;code&gt;src/content.config.ts&lt;/code&gt; とは別ファイル）&lt;/p&gt;
&lt;p&gt;ポイントいくつか&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;defineLiveCollection()&lt;/code&gt; を使用&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type: &apos;live&apos;&lt;/code&gt; を指定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;loader&lt;/code&gt; に &lt;code&gt;loadCollection&lt;/code&gt; と &lt;code&gt;loadEntry&lt;/code&gt; を実装&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Content Collections と Live Content Collections の比較&lt;/h2&gt;
&lt;p&gt;今回は従来のビルド時 Content Collections と Live Content Collections の両方を実装して比較した。&lt;/p&gt;
&lt;h3&gt;デモページ、ソースコード&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;静的版（従来の Content Collections）
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/demo/live-content-collections/static/&quot;&gt;デモページ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/blob/main/src/content/config.ts&quot;&gt;src/content.config.ts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/tree/main/src/pages/demo/live-content-collections/static&quot;&gt;src/pages/demo/live-content-collections/static/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;動的版（Live Content Collections）
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/demo/live-content-collections/dynamic/&quot;&gt;デモページ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/blob/main/src/live.config.ts&quot;&gt;src/live.config.ts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/tree/main/src/pages/demo/live-content-collections/dynamic&quot;&gt;src/pages/demo/live-content-collections/dynamic/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;静的版（Content Collections）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;src/content.config.ts&lt;/code&gt; で定義する。ページコンポーネントでは &lt;code&gt;getCollection()&lt;/code&gt; を使用。&lt;/p&gt;
&lt;h3&gt;動的版（Live Content Collections）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;src/live.config.ts&lt;/code&gt; で定義する。ページコンポーネントでは &lt;code&gt;getLiveCollection()&lt;/code&gt; を使用。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
export const prerender = false;

import { getLiveCollection } from &apos;astro:content&apos;;
const { entries, error } = await getLiveCollection(&apos;liveBlog&apos;);
---
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;従来の fetch（SSR）との比較&lt;/h2&gt;
&lt;h3&gt;従来の fetch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;手動で型の定義が必要&lt;/li&gt;
&lt;li&gt;バリデーションは自分で実装&lt;/li&gt;
&lt;li&gt;エラーハンドリングも自分で実装&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Live Content Collections&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;スキーマから自動的に型が推論される&lt;/li&gt;
&lt;li&gt;Zod による自動バリデーション&lt;/li&gt;
&lt;li&gt;エラーハンドリングが統一される&lt;/li&gt;
&lt;li&gt;ローダーとして再利用や配布可能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Live Content Collections は SSR の上に構築された抽象化レイヤーという扱いらしい（よく分からない）&lt;/p&gt;
&lt;h2&gt;所感&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;割とシンプルなデータでも Live Content Collections のページは重いので使い所は気をつけないと&lt;/li&gt;
&lt;li&gt;記事のプレビュー環境で使うのとかはいいかも&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Astro で CSS ファイル名を固定する</title><link>https://yuheijotaki.com/blog/2025112306_css-filename/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2025112306_css-filename/</guid><description>Astro で生成される CSS ファイル名を固定する方法を試した雑感です。</description><pubDate>Sun, 23 Nov 2025 00:00:05 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/ymnkx/articles/12b45b8e06e5eb&quot;&gt;ビルド後に組み込み作業アリ用のAstro開発環境&lt;/a&gt; という記事で Astro の CSS ファイル名を固定する方法が紹介されていた。CSS ファイル名の固定はできないと思ってたので実際に試してみた。&lt;/p&gt;
&lt;h2&gt;Astro での CSS ファイル名の扱い&lt;/h2&gt;
&lt;p&gt;通常 Astro でビルドすると CSS ファイルにハッシュが付与される。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;_astro/_slug_.a1Wq-uq3.css
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ハッシュはファイルの内容が変わるたびに異なる値になる。キャッシュ戦略として有効だがバックエンドへの組み込み作業がある場合やクライアントのガイドラインでファイル名が制限される場合など固定のファイル名にしたいケースがある。&lt;/p&gt;
&lt;p&gt;固定化すると以下のようなファイル名になる。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;_astro/common.css
_astro/styles.css
_astro/styles2.css
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;CSS カスタムプロパティを使った固定化&lt;/h2&gt;
&lt;h3&gt;仕組み&lt;/h3&gt;
&lt;p&gt;Vite の &lt;code&gt;rollupOptions.output.assetFileNames&lt;/code&gt; で CSS のソースコードから特定のカスタムプロパティを抽出してそれをファイル名として使用する。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/ymnkx/articles/12b45b8e06e5eb&quot;&gt;ビルド後に組み込み作業アリ用のAstro開発環境&lt;/a&gt; では以下の2つのカスタムプロパティが使われている。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--output-file-name-important&lt;/code&gt; - 優先度が高い（全ページ共通 CSS やページ固有 CSS で使用）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--output-file-name&lt;/code&gt; - 優先度が低い（複数ページ用 CSS で使用）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;設定方法&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;astro.config.mjs&lt;/code&gt; に以下を追加する。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineConfig } from &apos;astro/config&apos;;

export default defineConfig({
  build: {
    inlineStylesheets: &apos;never&apos;,
  },
  vite: {
    build: {
      rollupOptions: {
        output: {
          assetFileNames: (assetInfo) =&amp;gt; {
            if (assetInfo.name &amp;amp;&amp;amp; assetInfo.name.endsWith(&apos;.css&apos;)) {
              // --output-file-name-important: filename.css を優先
              const importantMatch = String(assetInfo.source).match(
                /--output-file-name-important:\s*([^;}\s]+)/,
              );
              if (importantMatch) {
                return `_astro/${importantMatch[1].trim()}`;
              }

              // --output-file-name: filename.css を次に確認
              const matches = [
                ...String(assetInfo.source).matchAll(/--output-file-name:\s*([^;}\s]+)/g),
              ];
              if (matches.length &amp;gt; 0) {
                const fileName =
                  matches.map((m) =&amp;gt; m[1].trim().replace(/\.css$/, &apos;&apos;)).join(&apos;-&apos;) + &apos;.css&apos;;
                return `_astro/${fileName}`;
              }

              // カスタムプロパティがない場合はデフォルト名
              return &apos;_astro/styles.css&apos;;
            }
            return &apos;_astro/[name].[hash][extname]&apos;;
          },
        },
      },
    },
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;build.inlineStylesheets: &apos;never&apos;&lt;/code&gt; - CSS をインライン展開せず外部ファイルとして出力&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assetFileNames&lt;/code&gt; 関数内で &lt;code&gt;assetInfo.source&lt;/code&gt; から正規表現でカスタムプロパティを抽出&lt;/li&gt;
&lt;li&gt;CSS ファイル以外のアセット（画像など）はハッシュ付きのままにする&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;CSS への記述&lt;/h3&gt;
&lt;p&gt;Astro コンポーネントの style タグに &lt;code&gt;is:global&lt;/code&gt; を付けて、カスタムプロパティを記述する。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;style is:global&amp;gt;
  :root {
    --output-file-name-important: common.css;
  }
&amp;lt;/style&amp;gt;

&amp;lt;style lang=&quot;scss&quot;&amp;gt;
  /* 通常のスタイル */
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;実際に試してみる&lt;/h2&gt;
&lt;p&gt;全ページで使われる Layout.astro などのコンポーネントに &lt;code&gt;--output-file-name-important: common.css&lt;/code&gt; を追加する。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;style is:global&amp;gt;
  :root {
    --output-file-name-important: common.css;
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;ビルド結果&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;_astro/common.css
_astro/styles.css
_astro/styles2.css
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;common.css&lt;/code&gt; が生成された。中身を確認すると Layout コンポーネントと全ページで使われている他のコンポーネントの CSS がまとめられていた。&lt;/p&gt;
&lt;h2&gt;Astro の CSS 分割の仕組み&lt;/h2&gt;
&lt;p&gt;Astro はコンポーネントの使用状況に応じて CSS を自動的に分割する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全ページで使われるコンポーネント - 1つの CSS ファイルにまとめられる&lt;/li&gt;
&lt;li&gt;一部のページでのみ使われるコンポーネント - 別の CSS ファイルとして分割される&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;複数のコンポーネントが1つの CSS ファイルにまとめられる場合そのファイル内には複数の &lt;code&gt;--output-file-name&lt;/code&gt; カスタムプロパティが含まれる可能性がある。その場合は優先度の高い &lt;code&gt;--output-file-name-important&lt;/code&gt; が使用される。&lt;/p&gt;
&lt;h2&gt;Vite と Rollup の役割&lt;/h2&gt;
&lt;p&gt;Astro はビルドツールとして Vite を使用しており CSS の出力は Rollup によって処理される。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vite - モジュールのバンドルと最適化を担当&lt;/li&gt;
&lt;li&gt;Rollup - &lt;code&gt;output.assetFileNames&lt;/code&gt; で出力されるアセットファイルの命名規則を制御&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://docs.astro.build/en/reference/configuration-reference/#vite&quot;&gt;Vite Configuration Reference&lt;/a&gt; / &lt;a href=&quot;https://rollupjs.org/configuration-options/#output-assetfilenames&quot;&gt;Rollup - output.assetFileNames&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;assetInfo.source&lt;/code&gt; には CSS の内容が文字列として渡される。この文字列から正規表現でカスタムプロパティを抽出することでファイル名を制御できる。&lt;/p&gt;
&lt;h2&gt;その他の固定化方法&lt;/h2&gt;
&lt;p&gt;CSS カスタムプロパティを使う以外にも設定ファイルでマッピングを定義する方法がある。&lt;/p&gt;
&lt;h3&gt;設定ファイルでのマッピング&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;astro.config.mjs&lt;/code&gt; で明示的にファイル名のマッピングを定義する方法。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const cssMapping = {
  Layout: &apos;common.css&apos;,
  Header: &apos;common.css&apos;,
  Footer: &apos;common.css&apos;,
  index: &apos;top.css&apos;,
  about: &apos;about.css&apos;,
};

export default defineConfig({
  build: {
    inlineStylesheets: &apos;never&apos;,
  },
  vite: {
    build: {
      rollupOptions: {
        output: {
          assetFileNames: (assetInfo) =&amp;gt; {
            if (assetInfo.name &amp;amp;&amp;amp; assetInfo.name.endsWith(&apos;.css&apos;)) {
              // names から元のファイル名を推測
              const baseName = assetInfo.names[0];
              const mappedName = cssMapping[baseName] || &apos;styles.css&apos;;
              return `_astro/${mappedName}`;
            }
            return &apos;_astro/[name].[hash][extname]&apos;;
          },
        },
      },
    },
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;デメリット&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Astro が複数のコンポーネントの CSS を1つのファイルに最適化する際 &lt;code&gt;assetInfo.names&lt;/code&gt; に含まれる情報が限定的で元のファイルを正確に特定できないことがある&lt;/li&gt;
&lt;li&gt;マッピングの管理が煩雑になる（コンポーネントが増えると設定も増える）&lt;/li&gt;
&lt;li&gt;CSS とマッピング定義が離れているためメンテナンス性が低い&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CSS カスタムプロパティを使う方法は CSS の中で完結してコンポーネント単位で管理できる点で優れている。&lt;/p&gt;
&lt;h2&gt;分かったこと・所感&lt;/h2&gt;
&lt;p&gt;バックエンドへの組み込みなどに有効だがフレームワークの設計を壊してる気もするので罪悪感が残る。&lt;/p&gt;
</content:encoded></item><item><title>Astro SVG components を試してみる</title><link>https://yuheijotaki.com/blog/2025112305_svg-components/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2025112305_svg-components/</guid><description>Astro の SVG components 機能を試した雑感です。</description><pubDate>Sun, 23 Nov 2025 00:00:04 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;Astro 5.0 以降で追加された SVG components 機能を使って従来の astro-icon との違いを試してみた。&lt;/p&gt;
&lt;h2&gt;SVG components とは&lt;/h2&gt;
&lt;p&gt;SVG ファイルを直接インポートして Astro コンポーネントとして使える機能。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import StarIcon from &apos;./icons/star.svg&apos;;
---

&amp;lt;StarIcon width=&quot;48&quot; height=&quot;48&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このようにインポートすると、SVG の内容が HTML にインラインで埋め込まれる。&lt;/p&gt;
&lt;p&gt;公式ドキュメント：&lt;a href=&quot;https://docs.astro.build/en/guides/images/#svg-components&quot;&gt;SVG components - Astro Docs&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;SVG components の処理の仕組み&lt;/h3&gt;
&lt;p&gt;Astro は SVG ファイルをインポートするとビルド時に props を受け取れる Astro コンポーネントに変換する。&lt;/p&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://github.com/withastro/astro/blob/main/packages/astro/src/assets/utils/svg.ts#L1-L50&quot;&gt;astro/packages/astro/src/assets/utils/svg.ts#L1-L50&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;変換処理では SVG ファイルの内容を読み取って &lt;code&gt;Astro.props&lt;/code&gt; で属性を受け取れる形に整形される。これにより SVG がそのままインラインで HTML に展開される。&lt;/p&gt;
&lt;h3&gt;生成される HTML&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- SVG components の生成HTML --&amp;gt;
&amp;lt;svg viewBox=&quot;0 0 24 24&quot; width=&quot;48&quot; height=&quot;48&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot;&amp;gt;
  &amp;lt;path
    d=&quot;M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z&quot; /&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同じアイコンを複数回使うと、その都度 SVG がインラインで展開される。&lt;/p&gt;
&lt;h2&gt;astro-icon との比較&lt;/h2&gt;
&lt;h3&gt;astro-icon の仕組み&lt;/h3&gt;
&lt;p&gt;astro-icon は SVG sprite を生成して最適化する仕組み。同じアイコンを複数回使う場合は &lt;code&gt;&amp;lt;symbol&amp;gt;&lt;/code&gt; と &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; で参照する形になる。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import { Icon } from &apos;astro-icon/components&apos;;
---

&amp;lt;Icon name=&quot;star&quot; width=&quot;48&quot; height=&quot;48&quot; class=&quot;custom-class&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://github.com/natemoo-re/astro-icon/blob/main/packages/core/src/loaders/loadLocalCollection.ts&quot;&gt;astro-icon/packages/core/src/loaders/loadLocalCollection.ts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SVG ファイルを読み込む際 &lt;code&gt;@iconify/tools&lt;/code&gt; を使って SVG の最適化や色の変換（&lt;code&gt;currentColor&lt;/code&gt; への変換など）を行う。同じアイコンが複数回使われる場合は &lt;code&gt;&amp;lt;symbol&amp;gt;&lt;/code&gt; 定義を一度だけ生成して &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; で参照することで HTML サイズを削減する。&lt;/p&gt;
&lt;h3&gt;生成される HTML&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- astro-icon の生成HTML --&amp;gt;
&amp;lt;svg data-icon=&quot;star&quot; width=&quot;48&quot; height=&quot;48&quot; class=&quot;custom-class&quot;&amp;gt;
  &amp;lt;symbol id=&quot;ai:local:star&quot; viewBox=&quot;0 0 24 24&quot;&amp;gt;
    &amp;lt;path
      d=&quot;M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z&quot; /&amp;gt;
  &amp;lt;/symbol&amp;gt;
  &amp;lt;use href=&quot;#ai:local:star&quot;&amp;gt;&amp;lt;/use&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;主な違い&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;機能&lt;/th&gt;
&lt;th&gt;SVG components&lt;/th&gt;
&lt;th&gt;astro-icon&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;インポート&lt;/td&gt;
&lt;td&gt;&lt;code&gt;import Icon from &apos;./icon.svg&apos;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Icon name=&quot;icon&quot; /&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML出力&lt;/td&gt;
&lt;td&gt;インラインSVG&lt;/td&gt;
&lt;td&gt;SVG sprite（symbol + use）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;最適化&lt;/td&gt;
&lt;td&gt;なし&lt;/td&gt;
&lt;td&gt;同じアイコンの重複を自動削減&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ファイル管理&lt;/td&gt;
&lt;td&gt;SVGファイルを直接管理&lt;/td&gt;
&lt;td&gt;アイコンディレクトリで一元管理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;デモ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/demo/svg-components/&quot;&gt;デモ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/blob/main/src/pages/demo/svg-components.astro&quot;&gt;コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;デモでは astro-icon と SVG components を並べて、生成される HTML の違いを確認できる。&lt;/p&gt;
&lt;h2&gt;分かったこと・所感&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;SVG components はシンプルな実装で追加のライブラリなしで SVG を扱える&lt;/li&gt;
&lt;li&gt;どちらも props（width や height や class など）は渡せる&lt;/li&gt;
&lt;li&gt;SVG components はインライン展開されるため同じアイコンを複数回使う場合は HTML サイズは増えそう&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>使っていいのか迷う機能 2025</title><link>https://yuheijotaki.com/blog/2025112304_new-features-2025/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2025112304_new-features-2025/</guid><description>新しい Web 標準機能のブラウザ対応状況を整理した雑感です。</description><pubDate>Sun, 23 Nov 2025 00:00:03 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;新しい CSS や HTML の機能が次々と追加されているが実際に実務で使っていいのか判断に迷う。ここ1〜2年で使えるようになったものとまだ使えないものを整理してみた。&lt;/p&gt;
&lt;h2&gt;判断基準&lt;/h2&gt;
&lt;h3&gt;Baseline とは&lt;/h3&gt;
&lt;p&gt;Baseline は主要なブラウザで機能が利用可能になったことを示す指標。MDN や web.dev で表示される。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Newly available - すべての主要ブラウザで利用可能になってから30ヶ月未満&lt;/li&gt;
&lt;li&gt;Widely available - すべての主要ブラウザで利用可能になってから30ヶ月以上経過&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;クライアントワークでの基準&lt;/h3&gt;
&lt;p&gt;Web 制作会社でのクライアントワークでは Chrome、Safari、Firefox、Edge、iOS Safari、Android Chrome の全てで利用可能でないと「使えない」という基準で判断する。&lt;/p&gt;
&lt;p&gt;Baseline の「Newly available」であれば基本的には使えるが一部のブラウザでのみ実装されている機能はフォールバックを用意しない限り使用を控える。&lt;/p&gt;
&lt;h2&gt;使える機能&lt;/h2&gt;
&lt;p&gt;全ブラウザで利用可能になった機能。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/CSS_nesting&quot;&gt;CSS Nesting&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sass や SCSS で使われていたネスト構文がネイティブ CSS で利用可能になった。&lt;/p&gt;
&lt;p&gt;Baseline: Widely available（2023年8月）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/Popover_API&quot;&gt;Popover API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JavaScript を使わずに HTML 属性だけでポップオーバーを実装できる。Anchor Positioning と組み合わせることで柔軟な配置が可能だが Anchor Positioning が未対応のブラウザでは位置調整が必要。&lt;/p&gt;
&lt;p&gt;Baseline: Newly available（2024年4月）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/@starting-style&quot;&gt;@starting-style&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;display: none から display: block への切り替え時にトランジションを適用できる。これまで opacity や transform のトランジションは可能だったが display の変更時にはトランジションが効かなかった。&lt;/p&gt;
&lt;p&gt;Baseline: Newly available（2024年5月）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/color_value/light-dark&quot;&gt;light-dark() 関数&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;ライトモードとダークモードで異なる色を1行で指定できる。prefers-color-scheme のメディアクエリを書く必要がなくなった。&lt;/p&gt;
&lt;p&gt;Baseline: Newly available（2024年3月）&lt;/p&gt;
&lt;h2&gt;まだ使えない機能&lt;/h2&gt;
&lt;p&gt;一部のブラウザでのみ実装されているか実装途中の機能。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/CSS_anchor_positioning&quot;&gt;CSS Anchor Positioning&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;ツールチップやポップオーバーをアンカー要素に対して正確に配置する機能。Chrome と Edge のみ対応で Safari と Firefox は未対応。Popover API と組み合わせて使うことが多いが Anchor Positioning が使えないブラウザでは JavaScript での位置調整が必要になる。&lt;/p&gt;
&lt;p&gt;対応状況: Chrome 125+, Edge 125+（Safari と Firefox 未対応）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/View_Transitions_API&quot;&gt;View Transitions API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;ページ遷移時にスムーズなアニメーションを実現する API。Chrome と Edge のみ対応。SPA だけでなく MPA（マルチページアプリケーション）でも使える。&lt;/p&gt;
&lt;p&gt;対応状況: Chrome 111+, Edge 111+（Safari と Firefox 未対応）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/CSS_scroll-driven_animations&quot;&gt;Scroll-driven Animations&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;スクロール位置に連動したアニメーションを CSS だけで実装できる。Safari が未対応。&lt;/p&gt;
&lt;p&gt;対応状況: Chrome 115+, Edge 115+, Firefox 114+（Safari 未対応）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/field-sizing&quot;&gt;field-sizing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;textarea や input 要素のサイズを内容に応じて自動調整する機能。Chrome のみ対応。&lt;/p&gt;
&lt;p&gt;対応状況: Chrome 123+（他ブラウザ未対応）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/interpolate-size&quot;&gt;interpolate-size&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;height: auto や width: auto でもアニメーションを可能にする機能。Chrome のみ対応。これまで height: 0 から height: auto へのトランジションができなかったがこの機能で可能になる。&lt;/p&gt;
&lt;p&gt;対応状況: Chrome 129+（他ブラウザ未対応）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/reading-flow&quot;&gt;reading-flow&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;CSS Grid や Flexbox で配置した要素の読み上げ順序を制御する機能。まだ実装されているブラウザはない。視覚的な順序とスクリーンリーダーでの読み上げ順序を一致させることができる。&lt;/p&gt;
&lt;p&gt;対応状況: すべてのブラウザで未対応（仕様策定中）&lt;/p&gt;
&lt;h2&gt;分かったこと・所感&lt;/h2&gt;
&lt;p&gt;CSS Nesting みたく使えるけど設計難しいとか &lt;code&gt;light-dark()&lt;/code&gt; みたく使えるけどどこでとか &lt;code&gt;field-sizing&lt;/code&gt; や &lt;code&gt;reading-flow&lt;/code&gt; みたく使えてもいやだなとか、そういうのも多いがまあ知っておくのは大事ということで。&lt;/p&gt;
</content:encoded></item><item><title>axe-core の Best Practice ルールを理解する</title><link>https://yuheijotaki.com/blog/2025112303_axe-best-practice/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2025112303_axe-best-practice/</guid><description>axe-core の Best Practice ルールについて調べた雑感です。</description><pubDate>Sun, 23 Nov 2025 00:00:02 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;axe DevTools で Web サイトのアクセシビリティチェックをしていると WCAG の達成基準とは別に「Best Practice」という項目が検出される。どのような基準で Best Practice なのか WCAG とどう違うのかを調べてみた。&lt;/p&gt;
&lt;h2&gt;axe-core の Best Practice ルールとは&lt;/h2&gt;
&lt;p&gt;axe-core の Best Practice ルールは WCAG の達成基準には直接該当しないがアクセシビリティ向上に寄与する推奨事項を含むルールセット。Deque Systems が独自に定義している。&lt;/p&gt;
&lt;p&gt;WCAG の達成基準は A、AA、AAA の3つのレベルに分類されるが Best Practice はこれらのレベルとは別にユーザビリティの向上を目的とした項目が含まれる。&lt;/p&gt;
&lt;h2&gt;主な Best Practice ルール&lt;/h2&gt;
&lt;p&gt;axe-core の Best Practice タグで検出される主な項目：&lt;/p&gt;
&lt;h3&gt;ページ構造&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;page-has-heading-one&lt;/code&gt; - ページに h1 見出しが存在するか&lt;/li&gt;
&lt;li&gt;&lt;code&gt;region&lt;/code&gt; - コンテンツがランドマークに含まれているか&lt;/li&gt;
&lt;li&gt;&lt;code&gt;landmark-one-main&lt;/code&gt; - メインランドマークが1つだけ存在するか&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;見出し構造&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;heading-order&lt;/code&gt; - 見出しレベルが正しい順序で使われているか（h1 の次が h3 ではなく h2 など）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;リンク&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;link-name&lt;/code&gt; - リンクにアクセシブルな名前が付いているか&lt;/li&gt;
&lt;li&gt;&lt;code&gt;link-in-text-block&lt;/code&gt; - テキストブロック内のリンクが識別可能か&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;画像&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;image-redundant-alt&lt;/code&gt; - 画像の alt テキストが冗長でないか（「画像」「写真」などの不要なテキストを含まない）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;フォーム&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;label&lt;/code&gt; - フォーム要素に適切なラベルが付いているか（これは WCAG の達成基準にも含まれることがある）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;WCAG との関係&lt;/h2&gt;
&lt;p&gt;Best Practice ルールは WCAG の達成基準とは独立している。WCAG の達成基準を満たしていても Best Practice で指摘されることがある。&lt;/p&gt;
&lt;p&gt;例えば h1 見出しの存在は WCAG の達成基準には含まれていないがページの主要なトピックを明確にするために推奨される。&lt;/p&gt;
&lt;p&gt;axe-core ではテスト時にタグを指定することで実行するルールを制御できる。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// WCAG 2.1 レベル A, AA のみをテスト
.withTags([&apos;wcag2a&apos;, &apos;wcag2aa&apos;, &apos;wcag21a&apos;, &apos;wcag21aa&apos;])

// Best Practice も含めてテスト
.withTags([&apos;wcag2a&apos;, &apos;wcag2aa&apos;, &apos;wcag21a&apos;, &apos;wcag21aa&apos;, &apos;best-practice&apos;])
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Best Practice の位置づけ&lt;/h2&gt;
&lt;p&gt;WCAG の達成基準はアクセシビリティの最低限または推奨される基準を定めている。Best Practice はそれらを補完する形でより良いユーザー体験を提供するための指針となる。&lt;/p&gt;
&lt;p&gt;WCAG レベルでいうと：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;レベル A - 達成が比較的容易で重篤な問題を引き起こしやすい基準&lt;/li&gt;
&lt;li&gt;レベル AA - より高度なアクセシビリティを実現する基準（多くの組織が目指すレベル）&lt;/li&gt;
&lt;li&gt;レベル AAA - 最も厳格な基準&lt;/li&gt;
&lt;li&gt;Best Practice - WCAG の達成基準とは独立したユーザビリティ向上のための推奨事項&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;実務での扱い方&lt;/h2&gt;
&lt;p&gt;axe DevTools でチェックする際 Best Practice の項目は Issue として検出されるが WCAG 違反とは別に考える必要がある。&lt;/p&gt;
&lt;p&gt;例えば WCAG レベル AA の準拠を目指すプロジェクトであれば Best Practice の項目は必須ではない。ただし Best Practice の項目を改善することでユーザー体験の向上につながることが多い。&lt;/p&gt;
&lt;p&gt;また Best Practice で指摘された項目が実際にはプロジェクトの要件や文脈では適切でない場合もある。例えばランディングページではメインコンテンツをランドマークで囲まない設計も考えられる。&lt;/p&gt;
&lt;h2&gt;分かったこと・所感&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Best Practice は WCAG の達成基準とは独立したユーザビリティ観点でのチェック項目&lt;/li&gt;
&lt;li&gt;ページ構造（h1 やランドマーク）や見出し順序などコンテンツの構造に関する項目が多い&lt;/li&gt;
&lt;li&gt;WCAG の達成基準を満たしていても Best Practice で指摘されることがある&lt;/li&gt;
&lt;li&gt;必須ではないが改善することでユーザー体験の向上が期待できる&lt;/li&gt;
&lt;li&gt;プロジェクトの要件や文脈によっては Best Practice の項目を対応しないという判断もある&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;参考記事&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://accessible-usable.net/2022/07/entry_220701.html&quot;&gt;axe-core ルールと WCAG 2.1 達成基準の対照表 | Accessible &amp;amp; Usable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://azukiazusa.dev/blog/axe-core-playwright/&quot;&gt;@axe-core/playwright によるアクセシビリティテストの自動化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dequelabs/axe-core-npm/tree/master/packages/playwright&quot;&gt;axe-core-npm/packages/playwright at master · dequelabs/axe-core-npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.deque.com/axe/core-documentation/api-documentation/&quot;&gt;axe-core Rules | Deque University&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>フォーカス制御のパターンを整理する</title><link>https://yuheijotaki.com/blog/2025112302_focus-management/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2025112302_focus-management/</guid><description>UI パターンごとのフォーカス管理の違いを整理した雑感です。</description><pubDate>Sun, 23 Nov 2025 00:00:01 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;モーダルやメガメニューなど UI によってフォーカスの制御方法が異なる。キーボード操作時にフォーカスが抜けられる／抜けられない UI の違いを整理してみた。&lt;/p&gt;
&lt;h2&gt;フォーカス管理とは&lt;/h2&gt;
&lt;p&gt;キーボード操作でウェブページを利用する際は Tab キーでフォーカスを移動していく。このとき特定の UI 内にフォーカスを留めるか自由に移動させるかを制御する。&lt;/p&gt;
&lt;h2&gt;主なフォーカス制御の方法&lt;/h2&gt;
&lt;h3&gt;tabindex&lt;/h3&gt;
&lt;p&gt;HTML 要素のフォーカス順序を制御する属性。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tabindex=&quot;0&quot;&lt;/code&gt;: 通常のフォーカス順序に含める&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tabindex=&quot;-1&quot;&lt;/code&gt;: Tab キーではフォーカスできないが、JavaScript の &lt;code&gt;focus()&lt;/code&gt; では可能&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tabindex=&quot;1&quot;&lt;/code&gt; 以上: フォーカス順序を指定&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;inert 属性&lt;/h3&gt;
&lt;p&gt;要素とその子要素すべてを不活性化する HTML 属性。フォーカス移動とクリックイベントを無効化してアクセシビリティツリーからも除外する。&lt;/p&gt;
&lt;p&gt;モーダル表示時に背後のコンテンツを完全に操作不可にする場合に使う。&lt;/p&gt;
&lt;h3&gt;フォーカストラップ&lt;/h3&gt;
&lt;p&gt;JavaScript でフォーカスを特定の範囲内に留める実装。モーダルやドロワーなど開いている間は背後のコンテンツを操作させたくない UI で使う。&lt;/p&gt;
&lt;h2&gt;UI パターンごとの実装&lt;/h2&gt;
&lt;h3&gt;モーダルダイアログ&lt;/h3&gt;
&lt;p&gt;背後のコンテンツは操作できずフォーカスはモーダル内に留まる。ESC キーで閉じて元の要素にフォーカスを戻す。&lt;/p&gt;
&lt;p&gt;実装は背後のコンテンツに &lt;code&gt;inert&lt;/code&gt; 属性を付与してモーダル内でフォーカストラップを実装する。&lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; 要素を使うと標準で実現できる。&lt;/p&gt;
&lt;p&gt;関連する WCAG 達成基準は &lt;a href=&quot;https://waic.jp/translations/WCAG22/#no-keyboard-trap&quot;&gt;2.1.2 キーボードトラップなし（レベル A）&lt;/a&gt; と &lt;a href=&quot;https://waic.jp/translations/WCAG22/#focus-order&quot;&gt;2.4.3 フォーカス順序（レベル A）&lt;/a&gt;。&lt;/p&gt;
&lt;h3&gt;メガメニュー&lt;/h3&gt;
&lt;p&gt;背後のコンテンツも操作可能でフォーカスがメニュー外に移動したら自動的に閉じる。マウスホバーでも開閉することが多い。&lt;/p&gt;
&lt;p&gt;実装は &lt;code&gt;inert&lt;/code&gt; 属性を使わず &lt;code&gt;focusin&lt;/code&gt; イベントでフォーカス位置を監視してメニュー外にフォーカスが移動したら閉じる処理を実装する。&lt;/p&gt;
&lt;p&gt;関連する WCAG 達成基準は &lt;a href=&quot;https://waic.jp/translations/WCAG22/#on-focus&quot;&gt;3.2.1 フォーカス時（レベル A）&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;パターンの使い分け&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;UI&lt;/th&gt;
&lt;th&gt;フォーカストラップ&lt;/th&gt;
&lt;th&gt;背後を操作&lt;/th&gt;
&lt;th&gt;閉じる条件&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;モーダルダイアログ&lt;/td&gt;
&lt;td&gt;必要&lt;/td&gt;
&lt;td&gt;不可&lt;/td&gt;
&lt;td&gt;明示的な操作 or ESC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;メガメニュー&lt;/td&gt;
&lt;td&gt;不要&lt;/td&gt;
&lt;td&gt;可&lt;/td&gt;
&lt;td&gt;フォーカスが外れる or ESC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ツールチップ（Popover）&lt;/td&gt;
&lt;td&gt;不要&lt;/td&gt;
&lt;td&gt;可&lt;/td&gt;
&lt;td&gt;フォーカスが外れる or ESC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;APG パターンとの対応&lt;/h2&gt;
&lt;p&gt;ARIA Authoring Practices Guide (APG) では、各 UI パターンのキーボード操作が定義されている。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/&quot;&gt;Modal Dialog&lt;/a&gt;: フォーカストラップを実装&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/ARIA/apg/patterns/menubar/&quot;&gt;Navigation Menubar&lt;/a&gt;: フォーカスは自由に移動可能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;APG のコードを見ると、モーダル系の UI はフォーカストラップを実装していて、メニューバー系はフォーカスの移動制限をしていない。&lt;/p&gt;
&lt;h2&gt;分かったこと・所感&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;モーダル系（背後を操作させない UI）はフォーカストラップを実装する&lt;/li&gt;
&lt;li&gt;メニュー系（背後も操作可能な UI）はフォーカスが外れたら閉じる実装が多い&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inert&lt;/code&gt; 属性を使うと背後のコンテンツを完全に不活性化できる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; 要素はフォーカストラップを標準で実装してるのでモーダルが楽&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;参考記事&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/ARIA/apg/&quot;&gt;ARIA Authoring Practices Guide (APG)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/&quot;&gt;Modal Dialog Pattern | APG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/ARIA/apg/patterns/menubar/&quot;&gt;Navigation Menubar Pattern | APG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/inert&quot;&gt;inert - HTML | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>CSS scroll-state() を試してみる</title><link>https://yuheijotaki.com/blog/2025112301_scroll-state/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2025112301_scroll-state/</guid><description>CSS の scroll-state() を試した雑感です。</description><pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;Chrome 131 で実装された CSS scroll-state() を使い、スクロール位置に応じたスタイリングを試してみた。&lt;/p&gt;
&lt;h2&gt;scroll-state() とは&lt;/h2&gt;
&lt;p&gt;CSS でスクロール状態をクエリできる機能。
&lt;code&gt;@container&lt;/code&gt; と組み合わせて要素のスクロール状態に応じたスタイリングができる。&lt;/p&gt;
&lt;p&gt;検出できる状態は主に3つ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;stuck&lt;/code&gt; - 要素が sticky 状態かどうか&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snapped&lt;/code&gt; - スクロールスナップ位置に停止しているか&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scrollable&lt;/code&gt; - スクロール可能な状態か（縦横や両方向を指定可能）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;container-type: scroll-state&lt;/code&gt; は &lt;code&gt;position: sticky&lt;/code&gt; を持つ要素自体に設定する。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.header-wrapper {
  position: sticky;
  top: 0;
  container-type: scroll-state;
}

@container scroll-state(stuck: top) {
  .header {
    background: tomato;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;ブラウザ対応状況&lt;/h2&gt;
&lt;p&gt;Chrome 131 以降でサポート。Safari と Firefox は現状未サポート。&lt;br /&gt;
参考：&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/Guides/Conditional_rules/Container_scroll-state_queries&quot;&gt;MDN - コンテナースクロール状態クエリーの使用&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://caniuse.com/?search=scroll-state&quot;&gt;Can I use...&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;デモ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/demo/scroll-state/&quot;&gt;デモ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yuheijotaki/yuheijotaki.com/blob/main/src/pages/demo/scroll-state.astro&quot;&gt;コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;デモでは次のパターンを試した：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;stuck&lt;/code&gt; - ヘッダーがスティッキー状態でスタイル変更&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snapped&lt;/code&gt; - スナップしたカードの強調表示&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scrollable&lt;/code&gt; - スクロール可能/不可能の状態表示&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;分かったこと・所感&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Intersection Observer や scroll イベントを JS で書いていた処理が CSS だけで実現できる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stuck&lt;/code&gt; はスティッキーヘッダーのシャドウ表示など定番パターンがシンプルに実装できる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snapped&lt;/code&gt; はカルーセルやスクロールスナップ UI で現在アクティブな要素を視覚的に示すのに使える&lt;/li&gt;
&lt;li&gt;&lt;code&gt;container-type: scroll-state&lt;/code&gt; は &lt;code&gt;position: sticky&lt;/code&gt; を持つ要素自体に設定する（子要素ではない）&lt;/li&gt;
&lt;li&gt;Chrome 131 以降で動作するが他ブラウザは未対応&lt;/li&gt;
&lt;li&gt;Scroll-driven Animations と併用するとより高度なスクロール連動 UI が作れそう&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;参考記事&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/Guides/Conditional_rules/Container_scroll-state_queries&quot;&gt;コンテナースクロール状態クエリーの使用 - MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ics.media/entry/250602/&quot;&gt;スクロールの状態変化でスタイル切替が可能に！ scroll-state()入門 - ICS MEDIA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/css-scroll-state-queries?hl=ja&quot;&gt;CSS Scroll State Queries | Chrome for Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://drafts.csswg.org/css-contain-3/#scroll-state-container&quot;&gt;CSS Containment Module Level 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>prefers-reduced-motion で制御する/しないアニメーション</title><link>https://yuheijotaki.com/blog/2025050701_prefers-reduced-motion/</link><guid isPermaLink="true">https://yuheijotaki.com/blog/2025050701_prefers-reduced-motion/</guid><description>CSSの `prefers-reduced-motion` メディアクエリを使ったアニメーション制御のポイントを考えてみた記事です。</description><pubDate>Wed, 07 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;概要&lt;/h2&gt;
&lt;p&gt;CSSの &lt;code&gt;prefers-reduced-motion&lt;/code&gt; メディアクエリを使う際のアニメーション制御のポイントを考えてみた。&lt;/p&gt;
&lt;h2&gt;prefers-reduced-motionとは&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;prefers-reduced-motion&lt;/code&gt; はユーザーが「動きを減らす」とOS等で設定したかどうかを検出するメディアクエリ。&lt;br /&gt;
CSS（ &lt;code&gt;@media (prefers-reduced-motion: reduce)&lt;/code&gt; ）やJavaScript（ &lt;code&gt;window.matchMedia(&apos;(prefers-reduced-motion: reduce)&apos;)&lt;/code&gt; ）で検出可能。&lt;/p&gt;
&lt;p&gt;前庭障害や偏頭痛で大きく動くアニメーションによるめまいや吐き気を感じる方がいるため、&lt;a href=&quot;https://waic.jp/translations/WCAG21/#animation-from-interactions&quot;&gt;WCAG 2.1 2.3.3（AAA）&lt;/a&gt; でも機能や情報伝達に必須でないアニメーションをオフにできるよう求められている。&lt;/p&gt;
&lt;h2&gt;OSごとの設定項目&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;macOS
&lt;ul&gt;
&lt;li&gt;設定 &amp;gt; アクセシビリティ &amp;gt; ディスプレイ &amp;gt; 視差効果を減らす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;iOS
&lt;ul&gt;
&lt;li&gt;設定 &amp;gt; アクセシビリティ &amp;gt; 動作 &amp;gt; 視差効果を減らす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Windows（&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/@media/prefers-reduced-motion&quot;&gt;MDN&lt;/a&gt; による）
&lt;ul&gt;
&lt;li&gt;設定 &amp;gt; 簡単操作 &amp;gt; ディスプレイ &amp;gt; アニメーションを表示する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Android（&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/@media/prefers-reduced-motion&quot;&gt;MDN&lt;/a&gt; による）
&lt;ul&gt;
&lt;li&gt;設定 &amp;gt; ユーザー補助 &amp;gt; アニメーションの削除&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;その他ブラウザ、各アプリケーション内での設定が可能でそれらが反映されることもある。&lt;/p&gt;
&lt;h2&gt;実装アプローチ&lt;/h2&gt;
&lt;h3&gt;1. 基本的に全て消す（完全無効化）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;:root {
  --transition-duration: 0.2s;

  @media (prefers-reduced-motion: reduce) {
    --transition-duration: 0s;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 代替アニメーションに置き換え&lt;/h3&gt;
&lt;p&gt;大きい動きをフェードやディゾルブなどのシンプルなエフェクトに変更する&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.box {
  animation: bounce 1s infinite;
}

@media (prefers-reduced-motion: reduce) {
  .box {
    animation: fade 0.5s both;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. カスタムトグルを用意&lt;/h3&gt;
&lt;p&gt;OS設定に加えサイト独自のトグルUIで切り替えを行う。&lt;br /&gt;
&lt;a href=&quot;https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/&quot;&gt;Smashing Magazine&lt;/a&gt; の記事では Animal Crossing 公式サイトの例が紹介されており、このサイトではトグルUIのON/OFFで代替アニメーションを切り替えている。&lt;/p&gt;
&lt;h2&gt;制御する/しないアニメーション&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;残すべき（機能的）
&lt;ul&gt;
&lt;li&gt;ローディングのインジケーター&lt;/li&gt;
&lt;li&gt;状態変化のトランジション&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;削るべき（装飾的）
&lt;ul&gt;
&lt;li&gt;ループするオブジェクトアニメーション&lt;/li&gt;
&lt;li&gt;パララックススクロール&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;所感&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://accessible-usable.net/2021/09/entry_210919.html&quot;&gt;ユーザーのプリファレンスに応じて過度なアニメーションを無効にする「prefers-reduced-motion」 | Accessible &amp;amp; Usable&lt;/a&gt; にある通り、「必要であれば保険的」程度のものと考える。&lt;br /&gt;
そのうえで、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主に自分が実装するときに 1. の完全無効化を選択しがちだが、本質的には代替のアニメーションを行うほうが良い気もしてくる&lt;/li&gt;
&lt;li&gt;ブランディング的な観点での折り合いも考え所で、ニュアンスを残しつつ代替を提示するのが正解の場合もあるかもしれない&lt;/li&gt;
&lt;li&gt;macOS/iOS と比べて Windows/Android の設定は、動きが全くなくなるという言葉のニュアンスなのでユーザーからするとその違いも捉え方が変わってくるのでは&lt;/li&gt;
&lt;li&gt;Xを検索すると、iPhoneのバッテリー省エネ方法として「視差効果を減らす」のオンが紹介されているため、無意識的に設定している人も少なからずいそう&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/@media/prefers-reduced-motion&quot;&gt;MDN: &lt;code&gt;@media (prefers-reduced-motion)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/&quot;&gt;Smashing Magazine: Designing With Reduced Motion For Motion Sensitivities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/punitsonime/how-to-make-your-website-more-accessible-with-prefers-reduced-motion-do3&quot;&gt;How to Make Your Website More Accessible with prefers-reduced-motion - DEV Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item></channel></rss>