[CSS in JS] styled関数で拡張したコンポーネントの命名ルールを考える
styled関数とは
この記事でstyled
関数は、CSS in JSライブラリ(Styled ComponentsやEmotionなど)で提供される関数を指す。styled
関数は、Reactコンポーネントに対してスタイルを適用する目的で使用される。
styled
関数の基本的な使用法は、引数にHTMLタグ名を渡し、テンプレートリテラルもしくはオブジェクトスタイル記法を用いてCSSのルールを記述する。
例として、div
要素にスタイルを適用する場合のコードは以下のようになる。
// template literal
const StyledDiv = styled.div`
background-color: black;
color: white;
padding: 20px;
`;
// or
// object style
const StyledDiv = styled.div({
backgroundColor: 'black',
color: 'white',
padding: '20px',
});
ここで定義されたStyledDiv
は、Reactコンポーネントとして指定されたスタイルが適用される。
また、styled
関数を用いたコンポーネントの拡張も可能である。既存のスタイル付きコンポーネントをstyled
関数の引数として渡すことで、そのスタイルに新たなスタイルを追加や上書きできる。これにより、コンポーネントの再利用性が高まり、プロジェクト全体の一貫性を保ちつつ、必要に応じてカスタマイズを行うことが容易になる。
// 拡張した例
const StyledDiv2 = styled(StyledDiv)`
background-color: white;
color: black;
`;
拡張する際の命名について
拡張自体(const StyledDiv2 = styled(StyledDiv)
)は方法に違いがあるわけではない。方法は1つしかないが、命名方法が書き手によって変わってくる。
以下、いくつか案を挙げてみる。
案1
import { Foo } from 'Foo';
const StyledFoo = styled(Foo)`
// 元のコンポーネントの定義を上書きするスタイル
`;
/** 接頭辞ではなくコンポーネントの目的を反映した命名にする */
const BoldFoo = styled(Foo)`
// 元のコンポーネントの定義を上書きするスタイル
`;
評価
- 長所: 明確にスタイルが拡張されたことを示すことができる。拡張する際にはStyledのような接頭辞は避け、「数値や状態を含む命名」や「コンポーネントの目的を反映した命名」を前提としておけば、拡張の目的や特徴を明確に表現できる。
Styledのような接頭辞を避ける理由は、拡張したものをさらに拡張したケースで、命名が冗長になるリスクがあるためである。 - 短所: 接頭辞だけの命名ではスタイルが複数回拡張される場合、命名が冗長になるリスクがあるため、この短所はあらためて述べた前提により緩和される。
案2
import { Foo as _Foo } from 'Foo';
const Foo = styled(_Foo)`
// 元のコンポーネントの定義を上書きするスタイル
`;
評価
- 長所: 元のコンポーネント名をそのまま利用でき、スタイルの拡張する際の一貫性を保つことが可能である。さらなるスタイルのカスタマイズが必要な場合も、元のコンポーネント名をもとにした命名で行えるため、規則性が保たれる。
- 短所: アンダースコア(_)を使用した命名は一般的に内部変数や未使用変数に使われることが多く、この利用方法に不自然さを感じさせる場合がある。また、拡張前のコンポーネントを指す際の明確さに欠ける。
案3
import { Foo as Component } from 'Foo';
import { Bar as BarComponent } from 'Bar';
const Foo = styled(Component)`
// 元のコンポーネントの定義を上書きするスタイル
`;
const Bar = styled(BarComponent)`
// 元のコンポーネントの定義を上書きするスタイル
`;
評価
- 長所:
Component
という一般的な名前を使うことで、任意のコンポーネントを抽象的に示すことができる。これにより、コンポーネントの具体的な名前に依存しない柔軟な命名が可能になる。 - 短所:
Component
という名前が一般的すぎるため、複数のコンポーネントを同時に扱う場合には区別がつきにくい(**Component
のように変える)。
総評
- 案1:スタイルが拡張されたことを明示的に示すことができ、拡張の度合いやコンポーネントの目的を明確に表すために「数値や状態を含む命名」「コンポーネントの目的を反映した命名」を採用する前提であればバランスの取れた選択肢である。
- 案2:元のコンポーネント名を保持しつつ、スタイルの拡張を示すことができるが、アンダースコアを使用する命名はこの文脈でやや不自然に感じられる。一定の規則性を維持しつつ拡張性を提供する選択肢としては良い。
- 案3:任意のコンポーネントを抽象的に示しつつ、スタイル拡張する柔軟性を提供するが、「Component」という一般的な名前の使用は複数のコンポーネントを同時に扱う際の区別に難しさをもたらす。しかし、目的に基づいた命名を採用することで、この問題は緩和される。
各案にはそれぞれメリットとデメリットが存在するため、プロジェクトの状況(要件やチーム内の合意)に基づいて、それぞれの案を採用するのが一番である。