JNTZN

CSSフォーマッター

// DOM要素の取得 const cssInput = document.getElementById(‘cssInput’); const output = document.getElementById(‘output’); const formatBtn = document.getElementById(‘formatBtn’); const copyBtn = document.getElementById(‘copyBtn’); const downloadBtn = document.getElementById(‘downloadBtn’); const fileInput = document.getElementById(‘fileInput’); const toast = document.getElementById(‘toast’); // すべてのオプション要素を取得 const options = { sortProperties: document.getElementById(‘sortProperties’), removeComments: document.getElementById(‘removeComments’), alignColons: document.getElementById(‘alignColons’), compressOutput: document.getElementById(‘compressOutput’), vendorPrefix: document.getElementById(‘vendorPrefix’), removeEmptyRules: document.getElementById(‘removeEmptyRules’), convertRGBToHex: document.getElementById(‘convertRGBToHex’), removeLastSemicolon: document.getElementById(‘removeLastSemicolon’), indentSize: document.getElementById(‘indentSize’) }; // トースト通知を表示する関数 function showToast(message, isError = false) { toast.textContent = message; toast.classList.toggle(‘error’, isError); toast.classList.add(‘show’); setTimeout(() => toast.classList.remove(‘show’), 3000); } // パーティクルエフェクトを作成する関数 function createParticles(x, y) { const particleCount = 15; for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); const size = Math.random() * 8 + 4; particle.style.width = `${size}px`; particle.style.height = `${size}px`; particle.style.left = `${x}px`; particle.style.top = `${y}px`; const angle = Math.random() * Math.PI * 2; const distance = Math.random() * 100; document.body.appendChild(particle); const animation = particle.animate( [ { transform: 'translate(0, 0)', opacity: 1 }, { transform: `translate(${Math.cos(angle) * distance}px, ${Math.sin(angle) * distance}px)`, opacity: 0 } ], { duration: 800, easing: 'ease-out' } ); animation.onfinish = () => { particle.remove(); }; } } // RGBをHEXカラーに変換する関数 function rgbToHex(rgb) { const match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); if (!match) return rgb; const r = parseInt(match[1]); const g = parseInt(match[2]); const b = parseInt(match[3]); const toHex = (n) => { const hex = n.toString(16); return hex.length === 1 ? ‘0’ + hex : hex; }; return `#${toHex(r)}${toHex(g)}${toHex(b)}`; } // CSSをフォーマットする関数 function formatCSS(css) { // コメントを削除(オプションがチェックされている場合) if (options.removeComments.checked) { css = css.replace(/\/\*[\s\S]*?\*\//g, ”); } // ルールに分割 let rules = css.split(‘}’) .filter(rule => rule.trim()) .map(rule => { let [selector, properties] = rule.split(‘{‘); if (!properties) return ”; // セレクタの整理 selector = selector.trim(); // 空のルールをスキップ(オプションがチェックされている場合) if (options.removeEmptyRules.checked && !properties.trim()) { return ”; } // プロパティを配列に分割 let propsArray = properties .split(‘;’) .filter(prop => prop.trim()) .map(prop => prop.trim()); // ベンダープレフィックスを並べ替え if (options.vendorPrefix.checked) { propsArray.sort((a, b) => { const aPrefix = a.match(/^-\w+-/) || [”]; const bPrefix = b.match(/^-\w+-/) || [”]; return aPrefix[0].localeCompare(bPrefix[0]); }); } // プロパティの並べ替え(オプションがチェックされている場合) if (options.sortProperties.checked) { propsArray.sort((a, b) => { const aProp = a.split(‘:’)[0].trim(); const bProp = b.split(‘:’)[0].trim(); return aProp.localeCompare(bProp); }); } // RGBをHEXに変換(オプションがチェックされている場合) if (options.convertRGBToHex.checked) { propsArray = propsArray.map(prop => { const [name, value] = prop.split(‘:’); if (value && value.includes(‘rgb(‘)) { return `${name}: ${rgbToHex(value.trim())}`; } return prop; }); } // コロン揃えのためにプロパティ名の最大長を検索 let maxPropLength = 0; if (options.alignColons.checked) { propsArray.forEach(prop => { const propName = prop.split(‘:’)[0]; maxPropLength = Math.max(maxPropLength, propName.trim().length); }); } const indent = ‘ ‘.repeat(parseInt(options.indentSize.value)); // プロパティのフォーマット let formattedProps = propsArray.map((prop, index) => { let [propName, propValue] = prop.split(‘:’); propName = propName.trim(); propValue = propValue ? propValue.trim() : ”; if (options.alignColons.checked) { const padding = ‘ ‘.repeat(maxPropLength – propName.length); return `${indent}${propName}${padding}: ${propValue}`; } else { return `${indent}${propName}: ${propValue}`; } }); // 最後のセミコロンを削除(オプションがチェックされている場合) if (options.removeLastSemicolon.checked && formattedProps.length > 0) { formattedProps[formattedProps.length – 1] = formattedProps[formattedProps.length – 1].replace(‘;’, ”); } // プロパティを結合 let result = formattedProps.join(‘;\n’); if (!options.removeLastSemicolon.checked) { result += ‘;’; } // セレクタとプロパティを結合 if (options.compressOutput.checked) { return `${selector}{${formattedProps.join(‘;’)}}`; } else { return `${selector} {\n${result}\n}`; } }) .filter(rule => rule); // 空のルールを削除 return options.compressOutput.checked ? rules.join(”) : rules.join(‘\n\n’); } // ファイルインポートハンドラー fileInput.addEventListener(‘change’, (e) => { const file = e.target.files[0]; if (file && file.type === ‘text/css’) { const reader = new FileReader(); reader.onload = (event) => { cssInput.value = event.target.result; showToast(‘CSSファイルが正常にインポートされました’); }; reader.onerror = () => { showToast(‘ファイルの読み込み中にエラーが発生しました’, true); }; reader.readAsText(file); } else { showToast(‘有効なCSSファイルを選択してください’, true); } }); // フォーマットボタンハンドラー formatBtn.addEventListener(‘click’, (e) => { const css = cssInput.value.trim(); if (!css) { showToast(‘CSSコードを入力してください’, true); return; } try { const formattedCSS = formatCSS(css); output.value = formattedCSS; copyBtn.disabled = !formattedCSS; downloadBtn.disabled = !formattedCSS; const rect = e.target.getBoundingClientRect(); createParticles(e.clientX, rect.top); showToast(‘CSSが正常にフォーマットされました’); } catch (error) { showToast(‘CSSのフォーマット中にエラーが発生しました’, true); console.error(error); } }); // コピーボタンハンドラー copyBtn.addEventListener(‘click’, async () => { try { await navigator.clipboard.writeText(output.value); showToast(‘CSSがクリップボードにコピーされました’); const originalText = copyBtn.textContent; copyBtn.textContent = “コピー完了!”; setTimeout(() => { copyBtn.textContent = originalText; }, 2000); } catch (error) { showToast(‘クリップボードへのコピー中にエラーが発生しました’, true); } }); // ダウンロードボタンハンドラー downloadBtn.addEventListener(‘click’, () => { try { const blob = new Blob([output.value], { type: ‘text/css’ }); const url = URL.createObjectURL(blob); const a = document.createElement(‘a’); a.href = url; a.download = ‘formatted.css’; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); showToast(‘CSSファイルがダウンロードされました’); } catch (error) { showToast(‘ファイルのダウンロード中にエラーが発生しました’, true); } }); // 入力変更ハンドラー cssInput.addEventListener(‘input’, () => { copyBtn.disabled = true; downloadBtn.disabled = true; }); // 初期化 copyBtn.disabled = true; downloadBtn.disabled = true;

CSSフォーマッターとは何ですか?

CSSフォーマッターは、適切なインデント、スペース、改行を追加してCSSコードを整理・美化するツールです。CSSファイルの読みやすさと一貫性を向上させます。

なぜCSSフォーマッターを使うべきですか?

CSSフォーマッターを使うと、コードが読みやすくデバッグしやすくなり、チームやプロジェクトでのフォーマットの一貫性を保てます。また、文法エラーや冗長なコードを見つけやすくなり、大きなCSSファイルの保守性も向上します。

CSSフォーマッターは無料ですか?

はい、当社のCSSフォーマッターは無料で利用できます。

CSSフォーマッターはどのように動作しますか?

CSSフォーマッターはCSSコードを構造的な要素(セレクター、プロパティ、値)に解析し、インデント、改行、スペースを一貫して整え、機能を損なわずにフォーマット済みのCSSを出力します。

フォーマットのルールをカスタマイズできますか?

はい、CSSの圧縮や縮小、プロパティの並べ替え、コロンの位置揃え、コメントの削除、インデントスタイルなど、複数のフォーマットオプションとルールから選べます。

CSSフォーマッターはコードの機能に影響しますか?

いいえ、当社のCSSフォーマッターはコードの見た目だけを変更し、動作には影響しません。CSSは有効で機能的なままです。

CSSフォーマッターは大きなファイルを処理できますか?

はい、大きなファイルも処理可能です。ただし非常に大きなファイルの場合、パフォーマンスはブラウザやシステムリソースによって異なる場合があります。

フォーマットとミニファイの違いは何ですか?

フォーマットはインデントやスペースを適切に使ってコードの読みやすさを向上させ、ミニファイは不要な文字(空白、コメントなど)を削除してファイルサイズを削減しますが、どちらも機能は変わりません。