「入力欄(input)の右端に『年』や『円』などの単位を固定したい」というような UI を作る際、Panda CSS の _focus と _focusWithin の使い分けが重要になります。
違いを一番シンプルなコード例で解説します。
1. 概念の違い
-
_focus(自分自身が対象)その要素自体(
inputなど)が直接クリックされたり、選択されたときにスタイルを適用します。 -
_focusWithin(子要素のどれかが対象)その要素の内側にある子要素にフォーカスが当たっているとき、親要素(外枠)に対してスタイルを適用します。
2. 最もシンプルなコード例
「入力欄(input)と単位(span)を1つの外枠(div)で包み、入力欄がアクティブになったら外枠全体の線を青くする」という実装です。
スタイル定義
import { css } from "@panda/css";
// ① 外枠(親要素):子要素がフォーカスされたら全体の枠線を青くする
const boxWrapper = css({
display: "flex",
border: "1px solid gray",
padding: "2",
width: "60",
// 💡 中のinputがアクティブになったら、この外枠を青にする
_focusWithin: {
borderColor: "blue.500",
},
});
// ② 入力欄(子要素):デフォルトの枠線を消す
const textInput = css({
border: "none",
outline: "none",
width: "full",
// 💡 自分自身がアクティブになったとき、文字色を黒にする
_focus: {
color: "black",
},
});
export const SimpleInput = () => {
return (
<div className={boxWrapper}>
<input type="text" className={textInput} />
<span>年</span>
</div>
);
};
3. メリットとデメリット
メリット
-
JavaScript(State)が不要
「今フォーカスされているか」を React の
useStateで管理する必要がありません。CSS の標準機能だけで完結するため、コードが非常にシンプルになります。 -
デザインの自由度が高い
input自体の枠線を消して親のdivに枠線を持たせるため、アイコンや単位が内側に入り込んだモダンな入力欄が簡単に作れます。
デメリット
-
階層が1つ深くなる
input要素を必ずラッパー(div)で囲む必要があるため、HTML の構造が1階層増えます。