この記事の概要
ある箇所のCSSを変更したら、意図しない箇所にまで影響が及んでしまった経験はありませんか?
CSSを書いたことがある人ならほぼ全員が遭遇する事象だと思います。
そんなCSSリファクタリングをするにあたって、あまり話題に出ないけど個人的に大事だと思っている観点を記事にしてみました。
この記事を読みさえすればリファクタリングが上手くいく、というものではありません。
しかし、考慮に入れておくとリファクタリングが頓挫・中止になる可能性が減る気がします。
スタンス
今より良い見た目を作ろうと思わない
おそらく1番大事な点です。
CSSのリファクタリングが話題に上がる時点で、大なり小なり見た目も古めかしくなっているのでしょう。
ここはグッとこらえて「見た目は変えず、コードの作りを良くするだけ」に絞ってください。
「普通に考えて、リファクタリングの中にアップデートを入れるわけないじゃない」と思われる方もいるかもしれません。
しかし、何故か多くの人は「ここの色、もうちょっとこうしたいなあ」なんて触りだしてしまうのです。
どこかの見た目をアップデートしようものなら、いつの間にかUIリニューアルプロジェクトのような空気になってしまいます。
もう一度書きますが、グッとこらえて「見た目は変えず、コードの作りを良くするだけ」に絞ってください。
既存のコードを無理に活かそうと思わない
つらく苦しいですが、活かそうと思わないでください。
既存CSSはあくまで参考資料であり、リファクタリングが終わったらすべて捨てる、くらいの気概で丁度良いと思います。
私の経験でいうと、短めの期間で効果の高かったときほど「1から書き直し」に近いやり方をしています。
乱暴な言い方ですが「リファクタリングしたいと思うCSS」ですから、どうにか活かしたとて大したメリットはありません。
古めのコードを悪としない
「未だにfloat
のレイアウトかー、Gridに置き換えよう」と思うのは否定しませんし、叶うならそちらの方が良いでしょう。
しかし、CSSのリファクタリングで得られる効果のうち、大きいのは「コードを触った箇所だけ見た目が変更される」状態を作ることだと思っています。
そのため、無理をして沼にハマるよりは「思った通りに動く状態を作る」だけに専念し、フェーズ2としてモダンな書き方へ移行する方が良いでしょう。
テクニック
上の階層から触る
CSSとはCascading Style Sheetsの略です。
その名の通りスタイルをカスケーディングしているので、下の階層の要素ほど色々なオーバーライドの結果に成り立っています。
そのため、下の階層の要素を先に直しても、後から上の階層を触ると崩れてしまうかもしれません。
掃除をする場合、埃が上から下に落ちてくるので、高い場所からはじめて段々低い場所へ移っていきます。
似たようなイメージではないでしょうか。
例えば、以下のような構成だとします。
- html
- head
- body
- div(全体のレイアウトを決めるwrapper)
- header
- main
- aside
- footer
- div(全体のレイアウトを決めるwrapper)
この場合、いきなりheader
やmain
に手をつけず、html
やbody
にかかっているスタイルに手を入れます。
reset.cssの類を導入している場合、全称セレクタによるbox-sizing
指定やbody
へのfont-family
指定があるでしょうか。
歴史が積み重なった結果なのでしょうが、body
にメインカラーであろうcolor
を当てている……とかも見たことがあります。
こういうレイヤーから丁寧に処理します。
なお、お察しの通り上の階層のスタイルをいじるのでときにはページ全体が目も当てられないほど崩れます。
しかしそこで挫けてはいけません。
大きく崩れない要素≒下の階層の要素なので、先ほど記載したように後から上の階層の要素を触ったら結局崩れます。
ページごとのCSSを書いて、後からモジュールに分割する
モジュールごとに美しく分割できていて、綺麗な作りになっているのが理想です。
同じスタイルを2度も3度も書かない方が効率が良いのは当たり前でしょう。
しかし、リファクタリングの最中にそれを求めると苦戦しがちな気がします。
変な話、現在表示されているページにちゃんとしたスタイルが当たっていれば良いのです。
違うページにも全く同じスタイルで名前だけが違うクラス
があったとして、顧客からしたら関係ありません。
1つのページに1つのCSSファイルが対応している状態を作った後、共通して登場しているものを切り出す、という進め方の方が早すぎる抽象化も防げる気がします。
ロジック込みでリファクタリングする
リファクタリングの例としては微妙なのですが、イメージしやすいと思う内容で説明します。
<p className="paragraph">何かの説明</p>
<ul className="unordered-list">
{items.map((item) => (
<li>{item}</li>
))}
</ul>
<p className="paragraph">何かの説明</p>
.unordered-list {
padding: 1em;
}
.paragraph {
margin-top: 1em;
}
item
が無い場合もul
は描画されるのでpadding
が適用されてしまい、p
要素同士がやたら離れてしまいます。
これをCSSだけで改善しようとした結果、何かしらの打ち消し用スタイルが書かれているとしましょう。
どこか別の場所では打ち消して欲しくないため更に上書きして……と苦しい世界が見えるのではないでしょうか。
CSSだけのリファクタリングでこれを解消するのは結構つらい気がします。
というわけで、この場合は以下のように変えます。
<p className="paragraph">何かの説明</p>
{items.length > 0 && (
<ul className="unordered-list">
{items.map((item) => (
<li>{item}</li>
))}
</ul>
)}
<p className="paragraph">何かの説明</p>
ul
はitem
があれば描画される、なければ描画されない、とスッキリしました。
これでCSSのリファクタリングに集中できます。
ロジックはアンタッチャブルだと感じてる人もいそうなのですが、手を入れた方が効果的な場面もあります。
周りと相談しながらにはなると思いますが、CSSだけで解決しようとしない方が良いでしょう。
最後まで読んでくださってありがとうございます!
Twitterでも情報を発信しているので、良かったらフォローお願いします!