CSSって実はモジュールシステムが表現できるって話
前置き
css....
エンジニアは大嫌いですよね。
今でこそ、UIフレームワークがあるからいいですが
昔、自分で書くってことをやっていた時は、
本当IEに匹敵するほど嫌いでした。
さて、そんなエンジニアに嫌われ者なCSSですが
実は、node.jsやpythonの
importだとかexportだとかプログラミング言語にある
モジュールシステムのような物を表現する事ができるんです。
と大層なことを言いましたが
UIフレームワークが数数多存在している昨今
もはや、ネタです。
へぇ、なるほどCSSってこんな事も表現できたんだくらいに受け止めて下さい。
CSSのクラス名がプログラミング言語の関数の様だったらいいのに...
CSSを自力で書いていくような案件がある度に思います。
「この、今htmlタグのclass属性に
書いているクラス名がプログラミング言語の関数の様だったら...」
こんな感じに
<div class="grid(4,10px,30px)"></div>
ん?待てよ
出来ないのか?
そりゃCSSはプログラミング言語では無いから
sassでループさせて必要なパターンを全て書き出しておく必要はあるんだろうけど...
そもそもCSSのクラス名で使える文字、使えない文字ってどういう感じなんなんだろうか?
CSSのクラス名って大概どんな文字でも使える!?
そう思って色々調べてみることに
するとこんな記事が
https://iwb.jp/css-id-class-name-zenkaku-kigou/
なんと、CSSのクラス名って日本語も使えるんだとか
マジか...
そんで記事を読み進めると
一つの希望の光が
.C\+\+ { color: #F00; font-size: 3em; }
なんと「+」などの記号も「\」をつけてやると使えるとのこと
CSSのクラス名に記号を使ってみる
それじゃ早速CSSのクラス名に記号使ってみよう
とりあえずhtml用意
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>demo</title> <link rel="stylesheet" href="./main.css"> </head> <body> <h1>テスト</h1> </body> </html>
すると現時点でこんな感じ
これをとりあえず赤文字に変えてみる
クラス名はまぁオブジェクト指向っぽく
desktop.text(red,5rem)とかでいってみようかと
.desktop\.text\(red\,5rem\){ color: #f00; font-size: 5rem; }
さて、ではこのクラスを
htmlタグに適応させます。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>demo</title> <link rel="stylesheet" href="./main.css"> </head> <body> <h1 class="desktop.text(red,5rem)">テスト</h1> </body> </html>
ブラウザで確認して見ると...
おぉ!見事スタイルが適応されています。
ということはCSSはオブジェクト指向や関数の形式で書こうと思えば書ける
と言うことです。
モジュールシステムを再現してみる
ここまでくればプログラミング言語のモジュールシステムを再現するのも
そう無理な発想でも無いです。
まず、node.jsとかのimport
import hoge from 'hoge'
これは、まぁCSSファイルでimportするという訳ではなく
htmlにimportするという発想ですね。
これは単純にlinkタグで読み込むだけです。
最後のまとめのところで紹介しているサンプルから抜粋ですが
こんな感じ
<link rel="stylesheet" type="text/css" href="/assets/css/modules/index.css"> <link rel="stylesheet" type="text/css" href="/assets/css/modules/desktop/grid.css" media="screen and (min-width: 768px)"> <link rel="stylesheet" type="text/css" href="/assets/css/modules/desktop/spacer.css" media="screen and (min-width: 768px)"> <link rel="stylesheet" type="text/css" href="/assets/css/modules/mobile/grid.css" media="screen and (max-width: 767px)"> <link rel="stylesheet" type="text/css" href="/assets/css/modules/mobile/spacer.css" media="screen and (max-width: 767px)">
ルールとしては
modules/パッケージ/モジュール
っていう感じです。
パッケージは必ずデバイスになります。
デバイス共通はmodules/index.cssに入れる
また、モジュール.css内では一切メディアクエリを使ってはいけないというのもルールです。
必ず、linkタグの方で設定します。
余談ですが
昔は、grid.col()とかgrid.gutter()とか
デバイス以外をオブジェクトとするアイディアも考えてましたが
結局、cssというのはオブジェクト指向よりも関数形式の方が相性が良く
デバイス以外でオブジェクト指向で書くと整理がつかなくなり、
結局カオスになるという事が分かったので
最終的にデバイス区切りになりました。
続いてモジュール.cssの書き方ですが下記の様に先頭には必ずデバイス名(パッケージ名)を付けます。
modules/desktop/grid.css
.desktop\.grid\(#{$cols}\,#{$cgap}\,#{$rgap}\){ }
marginとかpaddingはspacerという名前でまとめてしまってもいいので
デバイス名の後は必ずモジュール名でなければならないという事ではないですね。
ですがオブジェクト名は必ずデバイスです。
.desktop\.margin\(top\,#{$i * 5}\){ margin-top: #{$i * 5}px; } .desktop\.padding\(top\,#{$i * 5}\){ padding-top: #{$i * 5}px; }
これらは、あえてnode.jsで書くとこんな感じですかね?
export const desktop = { margin(){}, padding(){} }
まとめ
以上、CSSでモジュールシステムを再現してみるとこんな感じですかね。
命名規則とかルールが書いている内に崩壊するのが
CSSと言うものですが、モジュールシステムで書くとこうも整理がつきます。
ルールも破り用がないほど堅牢です。
実際、書くときはsassのループを使うのがオススメですね。
とは言え、冒頭でも述べたように
UIフレームワークが様々あるこのご時世
所詮、ただのネタです!www
なので試してみたい方は
まぁ、こんな発想もあるんや程度に面白半分で試してみてください。
サンプルリポジトリあります。
依存関係インストールして
npm startでOK!