🎨

React & Recoil でフォント サイズを動的に変更する

2023/09/05に公開

TL;DR

recoilのselectorを使用してフォントサイズを動的に変更します。
https://recoiljs.org/docs/introduction/core-concepts#selectors

ソースコード
https://github.com/neco3s/dynamic-font-size

まずは<RecoilRoot>で囲んでこのスコープ内でrecoilが使用できるようにします。

index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import {
  RecoilRoot,
} from 'recoil';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <RecoilRoot> 💡
      <App />
    </RecoilRoot>
  </React.StrictMode>
);

textFontSizeStateの状態をtextStateの文字列の長さに応じて変化させるselectorを定義します。
あとはtextFontSizeStateの値を取得してfontSize変数に割り当てます。
<span style={{fontSize: ${fontSize}}}>{text}</span>
でstyleを適用することで動的に文字の大きさを変化させることができました🎉

App.tsx

import './App.css';
import {
  atom,
  selector,
  useRecoilState,
  useRecoilValue,
} from 'recoil';

const textState = atom({
  key: 'textState',
  default: '',
})

const textFontSizeState = selector({
  key: 'textFontSizeState',
  get: ({get}) => {
    const text = get(textState) 💡
    const textLength = text.length
    if (textLength <= 8) {
      return "2rem";
    } else if (textLength <= 16) {
      return "1.5rem";
    } else if (textLength <= 24) {
      return "1rem";
    } else {
      return "0.8rem";
    }
  }
})

function App() {
  const [text, setText] = useRecoilState(textState)
  const fontSize = useRecoilValue(textFontSizeState) 💡

  const addA = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
    if (text.length > 27) {
      alert('Too long!')
      return
    }
    setText(text + 'A')
  }

  return (
    <div className="App">
      <div className="container">
        <span style={{fontSize: `${fontSize}`}}>{text}</span> 💡
      </div>
      <button onClick={addA}>A</button>
    </div>
  );
}

export default App;

小話

remでfont-size指定するのが好きです

index.css
html {
  font-size: 16px;
}

@media screen and (max-width: 600px) {
  html {
    font-size: 10px;
  }
}

remだとhtmlに指定したサイズを基準にしてfont-sizeを指定してくれます。
以下の記事がとてもよく説明してくれています。

https://www.pc-koubou.jp/magazine/23912

個人的には以下の2つの利点が大きいなと感じています。

  • レスポンシブサイトにおける端末ごとの文字サイズ設定がしやすい
  • アクセシビリティ(この場合は小さい文字が読めない人等)に考慮した文字サイズの切り替えに対応しやすい => サイト全体でrem指定していれば文字の大きさ切り替えの際にhtml { font-size: 個人で切り替え } この値を調整するだけで、サイト全体に反映することができます。
export const currentFontSizeState = selector({
  key: "currentFontSizeState",
  get: ({ get }) => {
    const currentStateValue = get(currentState);
    const currentStateLength = currentStateValue.length;
    if (currentStateLength <= 8) {
      return "2rem";
    } else if (currentStateLength <= 16) {
      return "1.5rem";
    } else if (currentStateLength <= 24) {
      return "1rem";
    } else {
      return "0.8rem";
    }
  },
});

それではまた明日!🐈

Discussion