Hatena::ブログ(Diary)

Webデザインの日々日記 RSSフィード

2016-06-19

CSSのネーミングでもう悩まない! BEM+OOCSSのネーミングルール

BEMの利点と落とし穴

BEMは使用箇所が明確で、何に使っているのかがすぐ分かって、関連するほかのクラスもすぐに見つけられて、そのため保守性が高い。

見た目は確かに醜いけれど、それ以上に利点が大きい。使わない手はない。


とはいえ、それなりに経験を積まないとちゃんとしたネーミングができない問題がある。

よくある間違いが、HTMLの構造の通りにCSSにネーミングしてしまうこと。そこまでいかなくても、ネストが深くなりやすい。

Sassなどを使っていればコードを書く負荷は下がるけど、出力されるCSSは肥大化するし、CSSの可読性が大幅に下がる。HTMLもクラス名のせいで読みにくくなる。一回これをやらかした。


本当にこれでいいのか?


よくないに決まっている。そこで一旦BEMから離れた。しかしこれが強力な手法であることに間違いはない。

なぜ正しくないアプローチをしてしまったのか?

BEMは、Block, Element, Modifierの順で名づけを行う。デザインをモジュールで把握して、「Block__Element--Modifier」の順で名前を付ける。

日本語で書くなら、「箱__箱--装飾・状態」である。

さらにBlock用のModifierとElement用のModifierを作ることができてそれらを1つの要素に詰め込むことができる。


これだけでも結構ややこしくなる。

BlockとElementをどこで判別するのか。これはElementだけれども、見方によってはBlockになる、どうすればいい?

また、ウェブページはBlockの入れ子構造になっている。関係性を明確にするのであれば、どのBlockまでさかのぼってネーミングすべきだろうか?


もう一つ。BEMではBlock, Element, Modifierのそれぞれで、ハイフンやアンダースコアを使って単語をいくつも結合できるようになっている。

制限がないので、詳しく書ける。そうすればあとから読む人がすぐに意味を把握できる。もとよりBEMはそこを重視している。

ここに落とし穴があった。


自由度が高すぎるのだ。多すぎる選択肢で悩む。

また、長く、複雑すると名前の重複を避けることができる。利点である一方、同じスタイルを別の名前で再生産するリスクも増える。ページの追加が多いサイトなら、条件次第ではCSSが膨大になる。

これではいけない。何か制限するものが必要である。より良い方法を見つけるための他のCSS設計を調べることにした。

OOCSS、SMACSS、FLOCSS…

プログラミングになじみがないため、オブジェクト指向やプロジェクト、クラスといった用語に戸惑ったが、サイトの構造やモジュールの性質を分類・理解するための助けになった。


ネーミングについては、レイアウトにはl-接頭辞を、モジュールにはm-接頭辞を、などというのはあるのだけど(SMACCS)、微妙に両方の性質を持っているモジュールがあったりして、こちらはむしろ悩みが増えることに。

救世主はBootstrap

今まで使わない機能が9割だったので、グリッドシステムやセマンティックなネーミングを取り入れるだけだったのだけどこれが「これならいけるんじゃね?」という答えをくれた。

col-sm-6

グリッドの列分割で、スモールサイズ以上の画面幅では、6グリッド。


「…なんかこれ、BEMっぽくね?」


なんというか、旅をして帰ってきたら青い鳥がそこにいました的な。

「機能」−「適用場所」−「詳細」

なんかこれがすべてのモジュールに適用できそうな気がした。レスポンシブデザインに最適じゃないか。

実際に検討してみたらそう簡単でもなかったのだけど、以下のように整理することができた。

「役割」−「使用場所または担当範囲」−「詳細」

これを適用すると、

col-sm-6
gnav-item
btn-card-submit

てな形になる。


自由度をなくすために、単語はハイフン一つで結合し、アンダースコアやキャメルケースは禁止。これで名前が冗長にならないようにできる。(ハイフン一つの縛りはWordPressコーディング基準と互換性を持たせるためでもある)


上記の命名ルールを英単語に置き換えると、

Role-Position-Detail

となる。頭文字を拾うとRPD。ほかの設計概念より無味乾燥な感じだけど、強引に「ラピッド」と呼ぶことにした。「RPD-CSSNamig」さっさと決めようクラス名。

さらにOOCSSの概念を導入

実はこれだけではネーミングはできても、サイトは構築できない。

Detailのところに装飾を担わせると、単語数が不足するのである。装飾のバリエーションは広いので1単語では足りない。


とはいえ、ネーミングの問題を検討していた当初から機能と装飾は完全に分離した方がよいと考えていた。

そもそもこの「ネーミングどうすべ?」問題、CSSフレームワークを自作するときに生じたもの。--Modifierでわずかに違うだけの同じスタイルを繰り返し使うと、CSSファイルが肥大化する。Sassを使えば管理は楽だが、Sassを使っていないコーダーがいる場合、編集されるのはCSSの方になる。そうすると同じスタイルが繰り返し出てくると保守性が下がる。

そのためこのフレームワークは主に構造あるいは機能に絞り、装飾は最小限にとどめるようにしていた。スタイルを上書きではなく追記することで、多くのサイトに使いまわせるようにという魂胆である。


当初はフレームワークのクラスに追記すればいいかな?と思っていたが、OOCSSのおかげで装飾専用のクラスを作る方が合理的だと考えなおした。

装飾専用のクラスを作り、モジュールとセットで運用する。


これを「従属セレクタ」と呼ぶことにした。単体ではスタイルを持たず、他のモジュールと組み合わせた時に、その装飾部分のスタイルを担当させるのである。

これなら、HTMLとCSSのどちら側でも装飾の修正や追記を簡単に行える。

また、従属セレクタの名前は、他のモジュールにも使いまわすことができる。


従属セレクタは運用が特殊になるため、他のモジュールとは明確に区別する必要がある。そこで従属セレクタにはdep-(depend)という接頭辞を付けることにした。

モジュールとセットで運用する場面があるのはJavaScriptのセレクタも同様である。そこでこれも従属セレクタとし、接頭辞js-を付けることにした。IDセレクタを使う場合はjs-は要らない。


いずれも接頭辞のあとはRPDのルールを適用する。(とはいえほとんどの場合、役割名だけで済むだろう)

Baseの概念も入れておく

ここまで検討してきたのはすべて何らかの機能を持ったモジュールに関するものになる。

実際にはHTML要素のリセットや、mt-10(margin-top:10px;)などのような微調整用のセレクタも必要になる。FLOCSSでいえばFoundationやUtilityにあたる。

大概1単語で片が付くし、ネーミングは大概決まっているためここまでの検討対象に入れていなかった。

全ページ共通で使いまわすため、これらをBaseとして分類することにした。

おおむね出来上がったので

GitHubにまとめておいた。

ネーミングに使える単語数が制限されているので、モジュールは小さいものから大きいものへとやっていくのがコツではないかと思う。親モジュールに振り回されないため、再利用性は上がるはず。

RPD-CSSNaming

一応、このアイデアはHTML/CSSコーダーにとってはとっつきやすいのではないかと思う。覚える・理解することも少なめで意思統一コストは低いのではないかと。

ただ、BEMの持つ親Blockとの強力なつながりが、RPDでは見えなくなるという欠点がある。モジュールは構造のみを担い、他のBlockでも使える(そのBlock独特の装飾部分は従属セレクタが担うはずである)ので大きな問題ではないと思うが、これはどういうプロパティを従属セレクタに任せるかの判断が重要になってくる。下手に組むと使いにくくなるだろう。


RPD-CSSNamingのアイデアは、プロジェクトによっていろいろカスタマイズできると思う。小規模なサイトであれば装飾セレクタを使わずBEM的なつくりの方が効率的に組めるのではないかと思うし、関わる人が多くて大規模になるのならSMACSSやFLOCSSのルールの方に寄せていった方が管理しやすいと思う。

これでCSSのネーミングに悩む人が減ったらよいなと思う。

2016-06-14

コンポーネント化CSSは簡単ではない

これからのWebデザインは、コンポーネント化を意識しよう | Webクリエイターボックス

上のリンク先で言われていることは大体みんなやってきたことなんじゃないかと思います。一人でやる案件なら別に意識するまでもなくやれるでしょうが、複数名でやると簡単に泥沼になるのがWeb制作の現場なので、単にコンポーネント化といってもどこに気を付けてやるべきかを熟考しなければなりません。

コンポーネント化の範囲をどうするか

今私がやっているのは「機能単位」でのコンポーネント化です。ただ、これが最適解かどうかは結論が出ていません。たぶん、これが最善と思ってはいますが。

コンポーネント化の単位として考えられるのは以下のパターンです。

  1. レイアウト単位
  2. 機能単位
  3. 装飾単位
レイアウト単位のコンポーネント

代表的なものはグリッドレイアウトです。12グリッド、n/mグリッドが主なパターンになるでしょう。12グリッドはカラム分割や複数枚の画像+記事の回り込みなどといったレイアウトには最適ですが、ヘッダーに横並びの等幅分割でグローバルメニューを設置するような場合はあまり向いていません。

機能単位のコンポーネント

横並びグローバルメニューや、カードモジュールのようなあらかじめ決まった形でそこにしか使わないようなものはまとめてしまう。

装飾単位のコンポーネント

色違いのボタンなど

コンポーネント化の落とし穴

全部入りの欠点

上記の3種のコンポーネントは、Bootstrapなどの大規模CSSフレームワークでは最初から入っています。Bootstrapのようなものを自分で作ろうとすると痛感しますが、非常に考え抜かれたコンポーネントであることが分かります。

なら黙って有名どころのフレームワークを使えばいいじゃん、となるのですが、そういうわけにもいかないのがWeb屋のジレンマです。(私もBootstrapは一度だけ試しに使いましたが、以降は自前でグリッドを用意するようになりました)

全部入りの欠点は、CSSファイルの肥大化が挙げられます。Bootstrapの機能の8割は使わない、という人も多いのではないでしょうか。「パフォーマンス」の御旗のもとにCSSやJavaScriptファイルのミニファイなどという涙ぐましい努力を推奨される一方で、こんな無駄が許されるのか、という問題はついて回ります。

レイアウトのみのコンポーネントは無駄がない

一方、グリッドシステムだけが用意されているような場合は、無駄がありませんが、制作時に作らなければならないものが多く、スピードが損なわれます。

レイアウト+機能は比較的バランスが良い

装飾にかかわるプロパティが最小限にとどめられている機能別コンポーネントではレイアウトのみの場合よりも制作スピードは上がります。ただし、その機能で使われる装飾が決まっている場合は、装飾までコンポーネントに入れるのが最適だと思います。機能と装飾を完全に分離してしまうと、セレクタの重複が増え、CSSが肥大化するからです。もっとも、装飾の変更が多い場合は完全分離のほうが管理しやすくなると思います。

装飾単位のみでコンポーネント化するのは避けるべき

スタイルガイドもがっちり作られ、コンポーネント化もされているにも関わらず、レイアウト・機能・装飾の分離がなされていないがためにコンポーネントの無駄な肥大化、同じレイアウトに複数のコンポーネントが割り当てられ、スタイルガイドも追記が頻発、という場面に出会ったことがあります。

主な要因は、レイアウトと機能と装飾を全部同じコンポーネントにまとめようとしていたこと。下線を付けるかつけないかだけでコンポーネントごと新たなセレクタに複製してしまうようでは効率的とは言えません。この辺はCSS設計者の腕の見せ所だと思います。

バランスをどこで見極めるか、が大事

CSSのモジュール化を進めると、必ずどこかで無駄と不足が発生します。不足をなくせばCSSは肥大化し、CSSの無駄と不足を最小にしようとするとクラスが細分化され、今度はHTML側の負担が増えます。これではHTML3の時代と同じじゃないか、ということになりかねません。

上流のCSS設計がまずいとこういう大変なことになるのですが、CSS設計の勘所というのは場数を踏む(そしてあとでまずかったところを把握する)必要があります。

のんびり場数を踏む余裕がない場合は以下の方法が効率的です。

Bootstrapなどのコードを読む

セマンティックな名付け、コーディングテクニックなどを学ぶことができます。フレームワークは大手のウェブサービス会社が公開しているので、いくつか目を通しておくと、いろいろな設計思想が学べて効果的です。特にBootstrapFoundationPureは勉強になります。

BEMを使ってみる

名づけのルールがBase, Element, Modifierとなっており、上記のコンポーネント化の目安となります。

最初のうちは深くしすぎるなどの失敗をするので練習用のサイトを用意して何回か試行錯誤すると勘所がわかるようになります。

BEMのルール上は__,--を何段にしてもよいみたいですが、3段くらいを限度にするとちょうど良いかなー、という印象です。

そして、導入する、ではなく使ってみる、というのがポイント。一度「このあたりがコンポーネントの境界だな」というのがわかれば、名づけをBEM方式にこだわる必要はありません。

Sassはほぼ必須かも

パフォーマンスをよくするためにはCSSファイルは1つにまとめたい。しかしファイルが大きくなると必要となるセレクタがどこにあるのか探すのに苦労する。またコンポーネント化をする上では土台となるCSSは触りたくない、といった面倒を解消してくれるのがSass。よくバグるけどKoalaを使えばコマンドラインを触ることもなく、CSSとほとんど変わらない感覚で編集・デバッグを行えるのでまだの人はすぐにでも導入すべきでしょう。

自分でCSSフレームワークを作ってみる

これをやると「案件ごとに専用コンポーネント作ったほうが楽じゃね?」ってことに気づきます。どの案件でも使いまわせるのはグリッドシステムくらいのものじゃないかと。

この点大規模フレームワークはすごいなと思います。

まとめ

  • コンポーネント化は目的・役割を固めたうえで、ちょうどよいバランスのところを考える必要がある。
  • 有名どころのCSSフレームワークやBEMは、たとえ使わなくても読んでおくほうがいい。設計思想を学ぶことができる。
  • 一度自分でフレームワークを作ってみると良いと思う。

2016-06-02

ヘッダーではなくfunctions.phpでスクリプト、スタイルファイルを読み込ませる

(久しぶりだとテーマのつくり方を忘れてしまう)

WordPressでテーマを作るとき、JavaScriptCSSのファイル読み込みは、headタグ内で

<script src="<?php bloginfo('template_url');?>/js/hoge.js" type="text/javascript"></script>
とか
<link rel="stylesheet" type="text/css" href="<?php bloginfo('template_url');?>/css/hage.css" />

てな具合にやるのがHTML/CSSコーダーにとっては分かりやすい。

ところがWordPressで推奨されているのはfunctions.phpで読み込ませること。プラグインも含めてスクリプトファイルの重複や依存関係も考慮したうえで出力させることができる。

読み込み方法

functions.phpに、テーマ独自の関数を作り、その中で読み込ませ、add_actionで動作させる。add_actionのwp_enqueue_scriptsはスクリプトだけではなくスタイルシートの呼び出しまでやってくれる。

シンプルになるのは以下のような形。

function theme_name_scripts() {
	wp_enqueue_style( 'style', get_stylesheet_uri() );
	wp_enqueue_style( 'custom-style', get_template_directory_uri() . '/css/hage.css' );
	wp_enqueue_script( 'jquery');
	wp_enqueue_script( 'hoge', get_template_directory_uri() . '/js/hoge.js');
}
add_action( 'wp_enqueue_scripts', 'theme_name_scripts' );

ただ、これはかなり省略しまくっている。

よりきめ細かく設定するなら以下のようになる。

wp_enqueue_script()の設定

wp_enqueue_script( '固有名', 'URI', array('依存ファイル'), 'バージョン', true/false );

固有名

読み込むjsファイルを識別するための名前。ファイル名と同じなら判別しやすいが、デフォルトスクリプトの名前と衝突しないようにすることが必要。

ちなみにjQueryの読み込みが

wp_enqueue_script( 'jquery');

だけで事足りるのはデフォルトスクリプトとして登録されているから。

URI

ファイルの場所を示すURL。テーマフォルダにjsフォルダを作っていて、それに入っているファイルであれば

get_template_directory_uri().'/js/hoge.js'

というように書く。get_template_directory_uri()を使っているのが重要で、これを面倒くさがってhttp://example.com/wp-content/theme/...なんて書くとリンク切れリスクを抱え込むことになる。外部リンクでない限り、get_template_directory_uri()関数を使うのがベスト。

ちなみにiPhoneはhead内にリンク切れがあると、サイトをめちゃくちゃにぶっ壊して表示することがあるので十分注意する必要がある。

array('依存ファイル')

例えばjQueryに依存しているときは、'jquery'をこの3番目の引数に入れる。一つだけならarray()を使わなくても認識してくれるが、ここはちゃんと書いた方がいいだろう。

複数入れるのなら、array('A','B','C')とコンマ区切りで羅列する。

バージョン

なにも書かなければWordPressのバージョンが勝手に付与される。1.0とでも入れておくか、nullを指定する。

true/false

ページの末尾で読み込ませるならtrue、head内で読み込ませるならfalseにする。

デフォルトではfalseになっている。

jQuery依存ファイルをラップする方法

ラップしたいプログラム

jQuery(function($){
});
又は
(function($){
})(jQuery);

で囲む。

これが何をやっているのかというと、「即時関数」というやつでラップし、引数に$を指定することで、外部の$と関数内の$を切り離し、即時関数内で自由に使えるようにしている、というもの。「この先の"$"はここでしか使わないよー、他の関数の$とは別物だよー」という宣言ですね。

wp_enqueue_styleの設定

wp_enqueue_style( '固有名', 'URI', array('優先関係'), 'バージョン', 'メディア' );

固有名

JavaScriptファイルの読み込み同様、cssファイルに付ける固有名。

URI

必須となるstyle.cssを読み込ませる場合は、

get_stylesheet_uri()

そのほかのCSSファイルを読み込ませる場合は、例えばテンプレートフォルダにcssという小フォルダを作っていて、そこに入れているCSSファイルを読み込ませたい場合は

get_template_directory_uri().'/css/hage.css'

と書く。

array('優先関係')

CSSの優先順を決める。JavaScriptの時と同様、array()で先に読み込ませたいCSSの固有名を列挙する。

バージョン

これも何もしなければWordPressのバージョンが表示される。自分で作ったものなら適当に1.0とでも入れておくか、nullを指定する。

メディア

そのCSSを適用するメディアを指定する。デフォルトはallで、すべてに適用される。そのほかのメディアは、

braille点字スクリーン

embossed:点字プリンター

handheld:ハンドヘルドデバイス。現在はメディアクエリでの振り分けでカバーしていることが多い。

print:プリンター

screen:パソコンディスプレー

speech:音声読み上げソフト、スクリーンリーダー

tv:テレビモニター。ハイビジョン時代になってパソコンモニターとの差は無くなっているので使う機会はほとんどないだろう。

まとめ

実際に動作を確認したのが次のようなコード

function ki_script() {
	wp_enqueue_style('ki-style', get_stylesheet_uri(), array(), null, 'all');	
	wp_enqueue_script( 'jquery' );
	wp_enqueue_script( 'kcss', get_template_directory_uri().'/js/kcss.js', array('jquery'), null, false);
	wp_enqueue_script( 'togglemenu', get_template_directory_uri().'/js/togglemenu.js', array('jquery'), null, false);
}
add_action('wp_enqueue_scripts','ki_script');

2016-05-01

Flexible Boxとfloatのグリッドを選択できるCSSフレームワークを作りました。

概要

BootstrapやFoundationを参考にしながら(パクりながら、ともいう)CSSフレームワークを作りました。

詳細はKomitsuboshi-cssにまとめています。GitHubでも公開中。

ある程度デバッグもできたので公開しましたが、利用する際はベータ版くらいの感覚で使ってください。バグがあれば教えてください。

名称は小三ツ星インターフェイスという屋号でやっているので「Komituboshi-css」という何のひねりもない名前です。当初kicssという名称で開発していたところ、GitHubに既に同じ名前のフレームワーク作っている人がいて、混乱を招きそうなので急遽変更しました。呼び名が長いんで、とりあえず、K-cssと略しますね。KocssとかKoshicssとかいい感じの略称つけたいなぁ。

作成の経緯

さて、世の優れたエンジニアの人たちがBootstrapとかスゴイの作っている中でなんでわざわざ作ったかというと、使わない機能が9割もあって私にはオーバースペックだったからです。

また、実際の案件ではボタンなどの装飾は全部作り直すのでむしろ邪魔になることもあります。グリッドのところだけコピペして使ったり、なんてことも一時期やってたんですが、数回使って以降はグリッドの作り方をまねてスクラッチで作るようになってしまいました。

大抵一度作ったものを使いまわしたりしてたんですが、その途中でBEMという手法を知ったり、SassやGitを使い始めたり、大規模案件にちょっと関わって大体のページのレイアウトパターンが見えてきたり、Foundationというフレームワークを知ったりと、自分がいろいろアップデートされてきたこともあり、一度まとめたいなと。

工夫したところとか

最初に(パクりながら)と書きましたが、実はパクったというほどには原形をとどめていません。

グリッドの配置方法

Bootstrapはrowのネガティブマージンを子要素のpaddingで相殺するやりかたですが、K-cssは親要素(rowではなく、float,flex,flex-rを指定します)のネガティブマージンを、子要素のmarginで相殺しています。paddingを使うと、background-colorを指定したときに隣の要素と完全に接触しちゃうんで都合が悪かったんです。borderをつけたいときとかも困ったのでこの点はBootstrapとは異なります。

これに伴い、子要素のwidthにcalcを使って、要素の幅はリキッドで、要素間のmarginは固定しています。

子要素間のmarginは、ブレイクポイント毎に違う値に設定できるようにしました。PCサイズの画面では要素間のmarginを20pxに、画面の小さいスマートフォンでは5pxにしてコンテンツの表示領域を広くとることが可能です。

なお、IE8はcalcプロパティおよびメディアクエリ非対応なので、IE8ではmarginも%指定になりウィンドウ幅に応じて縮みます。

グリッドの命名規則

Bootstrapのrowに当たるのがfloat, col-*に当たるのはcol-(画面サイズ)-(占有グリッド数)となります。

Bootstrapでは画面サイズの表記にxs, sm, md, lg がありますが、K-cssは sp, tab, pcの3種類だけです。文字通りスマートフォンサイズ、タブレットサイズ、パソコンモニタサイズを意味します。

ブレイクポイントはデフォルトで480px,768pxの2つで、containerのサイズを980pxにすることが多いので、これ以上細かくする必要はないと考えています。

基本は12グリッドなので、col-sp-4のように表記します。

指定した画面サイズ未満になると縦並びとなります。

12グリッド+2

12グリッドに加え、N/5, N/7の分割比も用意しました。col-sp-2by5のように表記します。

12グリッドだけで等分割パターンは1,2,3,4,6,12をカバーできますが、これに5と7を加えてより細かくカバーできるようにしました。

これに8から11を加えるかどうかは検討中です。拡張コンポーネントとして作るかもしれません。

子要素の右詰め

Foundationの場合、右端の子要素のみ、float:right;がかかるようになっているみたいです。これにヒントを得て、子要素のクラス名の末尾にrをつけるとその要素にはfloat:right;がかかるようにしました。表記はcol-sp-4rのようになります。

また、使い道は思いつきませんがrのあるものとないものを混ぜることも可能です。

オフセットは未対応

Bootstrapでは子要素の配置をオフセットして表示場所を入れ替えることができますが、その機能は今のところありません。

flexboxレイアウト対応

親要素にflexまたはflex-rをつけると、子要素の高さをそろえることができます。flexが左詰めの横並び、flex-rが右詰めの横並びです。

子要素の表記はfloatの場合と全く同じです。ただし、親要素がflexの場合は子要素にrがついていても左詰め、flex-rの場合は逆に子要素にrがなくても右詰めになります。

ただし、flexboxに非対応のブラウザではfloat同様floatによる配置になるため、親要素flexの場合はrなし、flex-rの場合はrをつける必要があります。非対応のブラウザでもjquery.matchHeight.jsを使って高さがそろうようにしています。(わざわざflex使う必要があったのかどうか悩むところです。)

flex等幅分割

親要素にflex-(画面サイズ)-eqを指定すると、子要素が等幅分割されます。このとき子要素にはクラス名をつけなくてもOK。数が増減しても等幅分割になります。

IE8と10ではtableレイアウトを使っています。

画像キャプション対応

写真の下にキャプションを別途つけられるクラス名を標準で入れました。ただし画像の幅を計算するためのJavaScriptファイルを読み込む必要があります。

変数の管理

このフレームワークはSassを使って書いています。主な変数は_parameter.scssにまとめているので、これを編集してコンパイルすると各案件に合わせたCSSを得ることができます。

課題と今後の展開

解説ページを見ればわかりますが、導入が少しばかり面倒です。読み込むスタイルはstyle.cssのほか、ie8,ie9,ie10用のスタイル、さらにjQueryライブラリ、標準のjsファイル(kcss.js)、旧ブラウザ対応のためにhtml5shiv, jQuery.machHeigt.jsを各ブラウザ向けに読み込ませる必要があります。読み込みも、IE用の振り分けのほか、ユーザーエージェントを判別しての読み込みがあってややこしいことになってます。

よく使う機能についてはcomponentとして随時追加していく予定です。

また、カスタマイズにはSassを使える必要があります。もともとCSS使える人向けに作ったのでこの点はご容赦を。Sassの使い方がわからないという人は下のSassの教科書が1冊あればどうにかなります。

今後追加予定の機能
  1. サイドバーを固定幅にするレイアウトを標準機能として追加する予定です。コンテンツファーストで3カラムまで対応させる予定です。
  2. ハンバーガーボタンのコンポーネント
  3. グローバルナビのコンポーネントを数種類
  4. テーブルレイアウトのコンポーネントを数種類
  5. フォーム用のコンポーネント
  6. いわゆるJumbotronのコンポーネント
  7. アコーディオンメニューのコンポーネント

フォーム用のコンポーネントができたらバージョンを1に上げる予定です。

2016-04-23

中の画像の幅に応じて親要素の幅を調整するjQuery

ようやく目的の情報が見つかったのでメモ。元情報はこちら。

画像の幅を指定し、親要素のwidthに代入し、さらに画像にあてた説明文を画像のaltとして入れたい。 - dentaq log

やりたいこと

  • 量産を前提とする静的なサイトで、画像にキャプションをつけたい。
  • 一枚の画像の下に、画像と同じ幅のキャプションテキストを入れる。
  • キャプションテキストはaltなどから持ってくるのではなく、本文中にキャプションのテキストを入れる。
  • 2枚の画像を横に並べ、その下に2枚分の幅を持つ1つのキャプションテキスト、というレイアウトもある。(下図)

f:id:k3akinori:20160423093441p:image

HTML
<div class="caption">
<img alt="" src="https://placehold.jp/100x40.png" class="caption-img" />
<p class="caption-text">キャプションテキストは画像の幅で折り返す</p>
</div>
<div class="caption">
<div class="caption-img"><img src="https://placehold.jp/100x40.png"> <img src="https://placehold.jp/100x40.png"></div>
<p class="caption-text">2つの画像に対して1つのキャプションテキストを入れることもある。</p>
</div>
<p class="clear"> test</p>
jQuery
jQuery(document).ready(function(){
	$('.caption').each(function(i){
		var captionimg = $('.caption > .caption-img').eq(i).outerWidth();
		$('.caption').eq(i).css('max-width',captionimg);
	});
});

これが前出の元情報の記事をもとにして作ったコード。他の情報源では.eq(i)が抜けていて、そのためページ内のすべてのキャプションの幅が同じになってしまうという問題に直面していた。

.cssに'max-width'を使っているのは、レスポンシブ対応するため。(imgタグにはwidth:auto; max-width:100%;のCSSをかけていて、画面幅が画像より狭くなってもはみ出さないようにしている。

CSS
.caption {
    max-width: 100%;
    box-sizing: content-box;
    line-height: 1.2;
    display: block;
}
.caption-img {
    display: inline-block;
    max-width: 100%;
}
.caption-img > img {
    max-width: 100%;
}
.caption-text {
    display: inline;
    font-size: 14px;
}

その他

キャプションをつける画像が1枚だけの場合、jQueryを使うまでもなく、画像の親要素である.captionに display: table; width: 10px; というCSSだけでキャプション用のボックスを作ることができる。親要素のテーブルよりもコンテンツの画像の幅が大きいとき、テーブルのほうが広げられるという性質を利用している。

ただ、かなり無理やり感のあるやりかただし、複数枚の画像に対して一つのキャプションテキストをつけたい場合には使えなかった。(ボックス内で、最大の幅を持つ画像の幅までしか親要素のtableは広がらない)


Firefox45, IE8〜11(10以下は11の開発者モードによるエミュレーション)で表示の確認済み。Macではどうなるかわからない。