こんにちは!株式会社プロットハブのエンジニア、山名です。
皆さんはコーディングを行う際、vwやclampは使用されていますか?
特にClamp!あれ、便利ですよね?
vwは流動的でレスポンシブな制作が行いやすいですが、ウィンドウサイズに合わせてどこまでも拡大/縮小してしまいます。
その点Clampは最小値と最大値を決めれるのでvwがとても使いやすくなります。
弊社のホームページ制作ではTailwindCSSを使う事が多いのですが、ある時「TailwindCSSでvwやclampが指定できればめっちゃ使い勝手いいのでは?」と考えました。
ただTailwindCSSにはvwやclampは用意されておらず、JITモードで直接記述するにも計算ツールなどを使用して数値の算出が必要だったりしてめんどくさい…
ならば自分で作ってしまおう!
と言う考えに至った結果、作成したプラグインのご紹介です。
JSファイルを作成
まずはvwやclampを算出する処理を行うためのjsファイルを作成しましょう。
ファイル名は何でもいいですが、ここでは単純に「fluidUtilityPlugin.js」と命名します。
処理の記述
vwはそんなに難しくないと思うのでClampの処理の説明を行います。
[Clamp処理の流れ]
- ビューポート,最小値,最大値,max or minの指定を行う
- ビューポートとmax(最大値) or min(最小値)を元にvw値を算出
- 最小値と最大値を使いclmapを作成
// `clamp` 関数を使って最小値、適応可能な可変値(vwベース)、最大値を指定。
const getClampSize = (viewportWidth, minSize, maxSize, sizeType = "max") => {
// sizeTypeが"max"の場合はmaxSizeを、"min"の場合はminSizeをvalueSizeとして使用
const valueSize = sizeType === "max" ? maxSize : minSize;
const v = valueSize / (viewportWidth / 100);
return `clamp(${minSize}px, ${v}vw, ${maxSize}px)`;
};
// ビューポート幅に対する値の割合を計算してvw単位で返す
const getVWSize = (viewportWidth, valueSize) => {
const vw = valueSize / (viewportWidth / 100);
return `${vw}vw`;
};
各プロパティに適用させる処理
TailwindCSSで用意されたプロパティ名に「-clamp-[ビューポート,最小値,最大値,maxもしくはmin]」を指定できるようにしています。
vwに関しても同じように「-vw-[ビューポート,指定値]」と記述します。
const fluidUtility = plugin(function ({ matchUtilities }) {
matchUtilities({
// --- Clamp処理--- //
// --- ここから --- //
// --- font-size --- //
'text-clamp': (value) => {
const parts = value.split(',');
const viewportWidth = Number(parts[0]);
const minSize = Number(parts[1]);
const maxSize = Number(parts[2]);
const sizeType = parts[3]; // sizeType は数値ではなく文字列として扱う
return {
fontSize: getClampSize(viewportWidth, minSize, maxSize, sizeType),
};
},
// --- ここまで --- //
// 同じようにコピペする場合、returnの'fontSize'の部分を任意のプロパティに変えてください。
// --- VW処理--- //
// --- ここから --- //
// --- font-size --- //
'text-vw': (value) => {
// 引数で受け取った値(ビューポート幅とフォントサイズ)を分割し、数値に変換します。
const [viewportWidth, valueSize] = value.split(',').map(Number);
// getVWSize関数を使用して計算されたvw単位のフォントサイズを設定します。
return {fontSize: getVWSize(viewportWidth, valueSize)};
},
// --- ここまで --- //
// 同じようにコピペする場合、returnの'fontSize'の部分を任意のプロパティに変えてください。
});
});
module.exports = fluidUtility;
実際の記述例
元々は指定したビューポートと最大値を元にclamp算出していましたが、それだけだとレスポンシブ対応の際に想定したスマホサイズ(375pxなど)の数値が指定しづらかったので、最大値と最小値のどちらを元に算出するか決めれるようにしました。
例1 : text-clamp-[1920,20,22,max]
=>ウィンドウサイズが1920pxの時に22pxになるようにvwを算出し、最小20px、最大22pxになるようにclampを作成する。
例2 : text-clamp-[375,16,24,min]
=>ウィンドウサイズが375pxの時に16pxになるようにvwを算出し、最小16px、最大24pxになるようにclampを作成する。
全体の記述
const plugin = require('tailwindcss/plugin');
// `clamp` 関数を使って最小値、適応可能な可変値(vwベース)、最大値を指定。
const getClampSize = (viewportWidth, minSize, maxSize, sizeType = "max") => {
// sizeTypeが"max"の場合はmaxSizeを、"min"の場合はminSizeをvalueSizeとして使用
const valueSize = sizeType === "max" ? maxSize : minSize;
const v = valueSize / (viewportWidth / 100);
return `clamp(${minSize}px, ${v}vw, ${maxSize}px)`;
};
// ビューポート幅に対する値の割合を計算してvw単位で返す
const getVWSize = (viewportWidth, valueSize) => {
const vw = valueSize / (viewportWidth / 100);
return `${vw}vw`;
};
const fluidUtility = plugin(function ({ matchUtilities }) {
matchUtilities({
// --- Clamp処理--- //
// --- ここから --- //
// --- font-size --- //
'text-clamp': (value) => {
const parts = value.split(',');
const viewportWidth = Number(parts[0]);
const minSize = Number(parts[1]);
const maxSize = Number(parts[2]);
const sizeType = parts[3]; // sizeType は数値ではなく文字列として扱う
return {
fontSize: getClampSize(viewportWidth, minSize, maxSize, sizeType),
};
},
// --- ここまで --- //
// 同じようにコピペする場合、returnの'fontSize'の部分を任意のプロパティに変えてください。
// --- VW処理--- //
// --- ここから --- //
// --- font-size --- //
'text-vw': (value) => {
// 引数で受け取った値(ビューポート幅とフォントサイズ)を分割し、数値に変換します。
const [viewportWidth, valueSize] = value.split(',').map(Number);
// getVWSize関数を使用して計算されたvw単位のフォントサイズを設定します。
return {fontSize: getVWSize(viewportWidth, valueSize)};
},
// --- ここまで --- //
// 同じようにコピペする場合、returnの'fontSize'の部分を任意のプロパティに変えてください。
});
});
module.exports = fluidUtility;
tailwind.config.jsに作成したJSファイルの読み込みを追記
const fluidUtility = require('./fluidUtilityPlugin');
module.exports = {
// purgeやthemeなど記述
plugins: [
fluidUtility,
],
};
いかがだったでしょうか?
これを使うようになってからブレイクポイントの細かい指定が減ったり、「どのウィンドウサイズで見ても可能な限りレイアウト崩れを起こさない」というある意味フロントエンジニアの理想に少し近づけた気がしています。
単純に作業工数も減っているとかいないとか(信じるか信じないかは…以下略)
TailwindCSSをよく使用されてる方もそうでない方も、一度試していただき感想をいただければ幸いです。
それではまた次の記事か、はたまた実際の案件でお会いしましょう!笑
ご覧いただきありがとうございました!
コメント