TODO: SkipNavigation

【Astro】コンポーネントのスタイルを親から制御する方法

Vue のようにコンポーネントに class を付けようとしたら、適用されませんでしたのでその解決法を案内します。

青文字の Button コンポーネントを例に

次の Button コンポーネントは、デフォルトで青色のテキストを持ちます。
親で指定された class を反映させるために class:list を使用します。

html
---
const { class: className } = Astro.props;
---
<button class:list={['Button', className]}>
  <slot />
</button>

<style>
  .Button {
    color: blue;
  }
</style>

このボタンのテキストを赤文字にしたい

しかし、次のように index.astro でこのボタンを赤色にしようとしても期待通りには動作しません。

html
---
import Layout from '../layouts/Layout.astro';
import Button from '../components/Button.astro';
---
<Layout title="トップページ">
  <Button class="red">ボタン</Button>
</Layout>

<style>
  .red {
    color: red;
  }
</style>

この方法では、ボタンは赤くなりませんでした。

解決策

解決策は英語版のドキュメントにありました。
Passing a class to a child component

スプレッド構文 (...rest) を使用してすべての属性を受け取ることで、親の data-astro-cid も子コンポーネントに渡され同一スコープとなることで親で定義したスタイルが適用されるようになります。

html
---
const { class: className, ...rest } = Astro.props;
---
<button class:list={['Button', className]} { ...rest }>
  <slot />
</button>

<style>
  .Button {
    color: blue;
  }
</style>

注意点

日本語版のドキュメントは古い情報のまま掲載されていました(2024/4/4現在)。
そこでは、「classを渡してclassNameで受け取る」と簡単に説明されていますが、英語版のドキュメントとは内容が異なりますので注意が必要です。

このパターンでは、子コンポーネントに直接スタイルを設定できます。Astroは、親のスコープ付きクラス名(例:astro-hhnqfkh6)をclassプロパティを通して自動的に渡し、その子を親のスコープに含めます。

子コンポーネントへのclassの受け渡し

簡単にまとめると...

  • Astroでは、デフォルトでコンポーネント間で class 属性は自動的に渡されません。
  • 子コンポーネントにスタイルを適用するには、class 属性とその他の必要な属性を明示的に渡す必要があります。
  • スプレッド構文 (...rest) を使用することで、親コンポーネントの data-astro-cid と共にスタイルを子コンポーネントに適用できます。
  • 日本語版ドキュメントは古い情報を含む可能性があるため、最新の情報は英語版ドキュメントを参照することが重要です。
お役立ち男

フロントエンド専門。フリーランスで10年以上活動しています。