CSSガイドラインを翻訳してみた

Harry Roberts氏によるCSSガイドライン(High-level guidelines from writing manageable, maintainable CSS)のドキュメントが素晴らしすぎたので、勢いで翻訳してみました。(ロシア語、中国語、フランス語に引き続いて4番目...)

個人的な主観で見所を選んでみると、以下のような感じです。

  • クラスの名前付け方法(ネーミングルール)
  • セレクターの設計、考え方
  • !importantの使い所

最近見るようになって来たBEM命名法についても説明してあります。

そもそもWebのデザインをどうするかという問題は置いておくと、CSSを書くという事は、どうやってそのデザインを実現するかというHowTo的なものと、どうのように名前付けやエレメントの設計を行なってメンテナンス可能にするかというノウハウ的なものという技術が必要とされると思っています。

前者のコーディングHowTo的なものは山のように記事や本があるのですが、後者のドキュメントはあまり見たことがありません。枝葉的なCSSのコーディング規約だと、以下のようなものがあります。

これらよりも、もっと設計レベルのノウハウをずっと探していたのですが、著名なデザイナーから盗めみたいな感じでしかなかったので(自分がCSSコミュニティにあまり詳しくなかったというのもあるかもしれません)、CSSの設計は確立されてないみたいなので難しいなと思っていました。

そんな時、このドキュメントとSMACSSを見て大変感動しました。

まさにこれが欲しかったものでした。待ってたらそのうちネタ帳みたいな人が翻訳してくれるかなと期待していたのですが、BEMについても一向に広まる気配がなかったので、出張の移動時間などで適当に翻訳してみました。

low specificity など適当な日本語が見つからないものもあったり、日本語の変なところもあると思いますので、ご意見やプルリクをいただけると大変嬉しいです。(原文チェック用に日本語・英語併記のものもあります)

コメントでspecificityについて教えてもらいました。 (2013/09/05 追記)

Chrome用 Backlog Wiki and Autofilter 拡張 / あるいは Firefox GM から Chrome 拡張への書き換えメモ

Backlog というチーム向けのバグ・タスク管理 ASP サービスがあるのですが、このタスク一覧を Excel のようにリアルタイムに絞り込んだりソートしたり、まとめて処理をしたり、 Wiki を勝手に拡張する Chrome Extension を作りました。各 OS の Chrome で無料で使えます。

ちなみに、以前作った Firefox GreaseMonkey 拡張の移植版です。

見た目や動作はほぼ一緒です。

Chrome だとクリック一発で入って、またアップデートも確実に行えるのが良いです。

Firefox GreaseMonkey から Chrome Extension へ

個人的なブラウザ環境は、Ubuntu 上の Firefox がうまく動かない時期があったので、 1年以上前に Firefox から Chrome に乗り換えていました。特にヘビーに使う拡張もなかったので移行はすんなりいきました。

GreaseMonkey のような仕組みは Chrome 拡張で出来るということは知っていましたが、まだ絶賛開発中のような状況だったので本格導入はせずに、しばらく様子を見ていました。どうしても調整しないと困るサイトだけ、 GreaseMonkey 互換の範囲で書いてはいました。

そのうちに、何人かの Autofilter のユーザーから Chrome 対応の声がだんだん上がるようになってきました。 Chrome 拡張も安定してさらに Web Store も開店したので、このタイミングなら良いだろうと言うことで、本格導入することにしました。

まず取りかかりとしては、 os0x さんの 続・先取り! Google Chrome Extensions が大変参考になりました。後は、本家ドキュメント(英語) がとてもよくまとまっていますので、一通り読めば大抵のことが出来るようになります。

後は、 GreaseMonkey からの非互換部分を頑張って修正するという作業でした。

コード量の少ない Wiki 拡張(300行弱)を書き直してみたところ、 manifest.json を追加する程度でほとんど動いてしまいました。やっててよかった! Web 標準万歳です。

これにとても encourage されまして、 Autofilter (約3600行)も同じような気持ちで取り組みました。結果、全体の1割程度の修正で動いたのですが、大変苦労しました。ということで、以下はそのときのメモです。

E4X の書き直し

Firefox では、 E4X という XML 構築や操作をリテラルで書けるシンタックスをサポートしています。慣れるとこれが大変便利で、式展開も出来るためコードが分かりやすくなります。 Rhino でも使えるので業務でもよく利用しています。

Autofilter や Wiki 拡張では、 XMLRPC の XML 構築や解釈、あとはヒアドキュメントとして使っていました。これらを E4X を使わない形に書き換えることが修正の主な作業でした。

ヒアドキュメントの書き直し

以下のようなコードを

var str = <>
ABCD
EFGH
</>.toString();

以下のようなコードに書き換えます。

var str = "ABCD\nEFGH";

GreaseMonkey では、追加の CSS はヒアドキュメントで書いて GM_addStyle で入れていましたが、 Chrome では manifest.json に書けば CSS は別ファイルに出来るので楽になりました。

XML リテラルの書き直し

以下のようなコードを

var xml = <a><b>cde</b></a>;

以下のようなヘルパー関数を使ったコードに書き換えます。

var xml = TAG("a",TAG("b","cde"));

function TAG(tag,content) { // E4X like helper
	if (content instanceof Array) {
		content = content.join("");
	}
	return "<"+tag+">"+content+"</"+tag+">";
}

大変そうでしたが、 XML 構築は単純な書き換えだったので楽でした。

DOM 操作の書き直し

以下のような E4X のコードを

function(response) { // XML object
   var struct = response..struct;
   :
}

以下のような XPATH コードに書き直します。

function(response) { // XML object
   var struct = $X("/methodResponse/params/param/value/struct",response);
   :
}

$X は以下のような XPATH のヘルパーです。よくあるコードです。

function $X(xpath, node) {
	node = node || document;
    var res = node.evaluate(xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    var copy = [];
    for (var i=0, j=res.snapshotLength; i<j; i++) {
        copy.push(res.snapshotItem(i));
    }
    return copy;
}

隣接するノードは、childNodes などの DOM 関数で取得するようにしたのですが、そうすると意図しない位置に空白文字があると TextNode が入って来てしまうので、うまくスキップさせたり、逆に必要な TextNode を判定するのが面倒でした。

これまでは E4X がうまく空気を読んでくれていたのだと思います。やはり E4X は偉大です。

XMLRPC 書き直し

ここも E4X のコードをひたすら書き直すだけでした。

Chrome 用の XMLRPC の先行実装をいくつか見たのですが、いまいちだったのでやっぱり自前で XMLRPC を書きました。オブジェクトと XML の変換がちょっと書いてて楽しかったです。

ここの部分は切り出して使えば、汎用の Backlog API コードとして使えそうかもしれません。

JavaScript 仕様

Firefox には 「for each」というループ構文があったのですが、 Chrome には無かったので、単純な for 文に書き直しました。

GreaseMonkey 仕様・GM関数の書き直し

いくつかの GreaseMonkey 仕様を書き直しました。これも対策が本家も含めて多く出回っているので対応は楽でした。

unsafeWindow の削除

GreaseMonkey では問題の多い「unsafeWindow」を使っていました。 Autofilter の場合は、単純に表のページのカレンダーのライブラリを読んでいるだけだったので、カレンダーのライブラリを同梱することにして解決しました。

manifest.json によるパッケージングは便利です。

GM_setValue, getValue

ローカルストレージで書き直しました。

Autofilter ではドメイン間のデータのやりとりはないので、 background.html や メッセージ通信は使っていません。

GM_xmlHttpRequest

こちらも通信先ドメインが同じなので単純に XMLHttpRequest のインタフェースを合わせて自前実装しました。 GET, POST しています。

複数非同期の待ち合わせで JSDeferred を導入し用かどうか悩んだのですが、まずは自前待ち合わせコードで済みそうだったので、導入は見送りました。ただ、これ以上複雑なことをする場合は導入しようと思っています。

CSS, HTML

CSS, HTML はブラウザが変わるとそもそも挙動が変わってしまうので、試行錯誤しながら一つ一つ元の動きになるように直していきました。

セレクタ

Firefox ではいい加減なセレクタを書いていても動いていたのですが、 Chrome だとうまくいかないことが多かったです。

おそらく、隣接セレクタの挙動が何か違っているような気がしました。

tbody がスクロールできない

今回一番苦労した部分です。

Firefox だと、 table の thead, tfoot は固定にして、tbody だけスクロールするということが出来たのですが、 Webkit 系では出来ないようです。

検索して解決方法を探したり、そういうプラグインのコードを読んだりしてみたのですが、 Autofilter で必要な機能を実現する根本的な解決方法は見つかりませんでした。

ということで、もうテーブルによる自動レイアウトはやめて、 tbody, thead, tfoot の display:block にして JS で幅を制御することにしました。個人的にはまだまだ不満点が多いのですが、ユーザーが Firefox との使用感の違いをすぐには認識できないくらいには、うまく動いているようでした。

その他

パッケージングにより、 loading のくるくる回るアイコンが出せるようになりました。



Chrome 拡張はとても面白かったので、今後も Backlog に欲しい機能や、 UI の実験などで積極的に使っていこうと思っています。

Emacsでスムーズに図形編集ができるようになるcacoo.elを作ってみた

Cacoo(http://cacoo.com/)というWeb上の図形描画ツールを、Emacsからシームレスに使える cacoo.el を作りました。
Emacsユーザーにとっては他のWordやExcelなどのアプリを超える文書作成環境になるのではないかと、勝手に妄想しています。

Cacooについては以下のサイトを見てください。自分はCacooで方眼紙Excelをやめることが出来ました。

インストール方法

必要なものは、Emacs22以上(たぶん)、ImageMagickwgetです。Mac, Linuxだとあまり問題ないと思います。Windowsの場合は、Cygwinなどと組み合わせることになるかと思いますが、今のところconvertのバージョンが古いとpngの透過色をうまく扱えない問題があります。

auto-install.elを持っている人は、以下の式を評価することで取って来れます。

(auto-install-from-url "http://github.com/kiwanami/emacs-cacoo/raw/master/cacoo.el")

手動で入れる場合は、以下のリンク先をload-pathに保存してください。

あとは、以下のような呼び出しの内容を .emacs などに書きます。

(require 'cacoo)
(global-set-key (kbd "M--") 'toggle-cacoo-minor-mode)

この場合、Altキーを押しながら「-(ハイフン)」を押すとOn/Offが切り替わるようになります。

使い方流れ

まず、Cacooにログインして絵を描きます。

この図を公開の設定で保存して右上の「戻る」ボタンを押すと詳細画面に来ます。(2010/05/08 追記)

ここで右上の「リンク」をクリックすると画像のURLが出ますので、クリックしてクリップボードにコピーします。

今度はEmacs上での作業です。Cacooモードを有効にします(上の設定であれば、Altキーを押しながらハイフンを押す)。有効になるとモードラインに「Cacoo」と出てきます。

ここで「C-c , y」と打つか、クリップボードのテキストを貼り付けて手で以下のように入力します。

[img:https://cacoo.com/diagrams/6m4ATG1ddlUiHPqd-0FAF7.png]

最後に「C-c , D」と入力してしばらく待つとテキストが図に置き換わります。

またテキストに戻したい場合は、もう一度「Alt+-」でCacooモードをOffにするか、「C-c , T」でテキストに戻ります。

図をクリックするとCacooの編集画面が開きますので、すぐに編集できます。編集した図は、「C-c , R」でリロードすることで即座に反映させることが出来ます。

Cacooの絵以外でも、Web上でアクセスできる図であれば大抵表示できます。以下、可能なURLの例です。もちろん編集はできません。

[img:http://example.com/xxx.jpg]
[img:file:///ローカルのファイルへのフルパス]
[img:ローカルのファイルへの相対パス]

以上が簡単な使用の流れです。

活用方法

マイナーモードですのでどのメジャーモードとも組み合わせて使えます。

個人的にはhatenaやwikiの下書きをhowmで書くことが多いのですが、そこで絵を表示させることでイメージを確認しながら書くことができます。特に、スクリーンショットを取るときにCacooが便利です。また、すぐに図を修正できるので、ちょっとした修正でも思いついたときに作業できます。

ソースコードにコメントだけでなく、Cacooの絵を貼ることによってクラス図などの絵をメンテナンス可能な形で貼ることができるようになります。詳細なコメントとしてBacklogなどのBTSWikiのURLを貼っておくことは良くやっていたのですが、絵がはれるとさらに分かりやすくなると思います。(ただし、Emacsに限りますが。。。)

キーバインド

以下はデフォルトの挙動です。使いやすいようにcacoo-minor-mode-keymapをカスタマイズしてください。

  • バッファ全体に対して
    • C-c , T : バッファのすべての図をテキストに戻す
    • C-c , D : バッファのすべての図を表示する(キャッシュがあればネットワークに接続しない)
    • C-c , R : バッファのすべての図を取得し直す
  • カーソール直後の図に対して
    • C-c , t : テキストに戻す
    • C-c , d : 図を表示する(キャッシュがあればネットワークに接続しない)
    • C-c , r : 図を取得し直して表示する
    • C-c , e : 図の編集画面を表示する
    • C-c , v : 図の詳細画面を表示する
    • C-c , V : ローカルの図を外部ビューアーで開く
  • Cacooの機能に対して
    • C-c , N : 新規図の作成画面をブラウザで開く
    • C-c , l : 図の一覧画面をブラウザで開く
  • ナビゲーション、編集
  • その他
    • C-c , C : キャッシュディレクトリを空にする
    • 図のクリック : 図の編集画面を表示する

動作詳細、カスタマイズなど

図はローカルにキャッシュされます。キャッシュは現在のディレクトリ(バッファが保存されるディレクトリ)のなかの「.cimg」というディレクトリに保存されます。オリジナルの図とリサイズされた図が保存されます。

キャッシュがあればネットワークに接続にいきません。リロードするとキャッシュを消して取りに行きます。リサイズもこのときに行われるので、サイズを変えたいときはリロードしてください。

非同期で取りに行ったり縮小したりするため、Emacsはそれほど固まらないはずだと思います。ただ、あまり賢い制御をしていないため、同一バッファで同一画像は複数回表示することができません。(2010/05/08追記)

convertでエラーが出たり、図の背景が黒くなってしまう場合は、以下の設定を入れてください。convertで新しい設定を使うのを止めて、強引に背景を白く塗りつぶします。(2010/05/08追記)

(setq cacoo:png-background "white")

ブラウザーEmacsで設定してあるデフォルトブラウザーを使います。うまく開かない場合は browse-url-browser-function 周辺を設定してみてください。

正規表現で図のマークアップを調べます。cacoo:img-regexp, cacoo:img-pattern を変更することで、Wiki記法などにあわせることができます。

キャッシュ用のディレクトリ名は cacoo:img-dir で指定します。いちいちディレクトリ作成で確認が必要なければ、 cacoo:img-dir-ok を t に設定してください。

画像の縮小サイズは cacoo:max-size で指定します。以下のようにスペース区切りで書くことで画像ごとにも指定できます。

[img:file:///xxx/yyy/zzz.png 600]

外部画像ビューアーのプログラムは cacoo:external-viewer で指定します。nilに設定するとEmacsのimage-modeで開こうとします。

自分のところでは、以下のような感じで .emacs に書いています。

(require 'cacoo)
(global-set-key (kbd "M--") 'toggle-cacoo-minor-mode)
(setq cacoo:img-dir-ok t)
(setq cacoo:max-size 450)
(setq cacoo:external-viewer nil)

いろいろ

別のエントリーを書こうとしていて、スクリーンショットや図の編集をしていたのですが、いちいちCacooの画面をブラウザで開くのが面倒になったので作りました。もともと昨年のCacooリリース後から構想はあって、仕様だけはメモしていたので、技術検証だけでわりと早くできました。

似たようなものに、iimageという標準添付のelがあります。これを改造することも考えたのですが、リサイズができなかったので、w3mやその他の画像を扱うelを参考にしていちから作ることにしました。

特に自分は仕事柄オフライン環境も多いため、ローカルにCacooの絵が残ることが重要でした。いままではいちいち名前をつけて保存していました。

個人的にはEmacsとCacooの組み合わせは、かなり破壊力のある環境ではないかなと思っています。Wordやほかの文書作成ツールやドローツールの組み合わせでは、ここまで快適に編集はできなかったです。Cacooの方でAPIとか提供してもらえると、画像の一覧をAnythingで絞り込んだりできたりするので、さらに便利になりそうだなーと思っています。

ということで、ぜひどうぞ。

※今のところ、Windowsなどで古いImageMagick(6.3.x以前など)を使うとエラーになる問題があります。後ほど修正する予定です。修正しました。

(2010/05/07 追記:rubikitchさんにご指摘いただき、キーバインドを修正しました。ありがとうございました。)
(2010/05/08 追記:いくつか機能追加、修正しました。エラーの箇所に色が付いたり、処理状況を表示するようにしました。本文に現状の制限などを追記しました。)

WEB+DB PRESS Vol.53 に記事を書きました

WEB+DB PRESS Vol. 53 にて、「JavaScript/Flash/HTML 5 でスパゲッティコードにならないためのモダン設計入門」というタイトルで記事を書きました。tenjin.webプロデュースという形です。


以下、あとがきです。

この記事の対象は、Web周辺(イントラの業務システム含む)のプログラマのうち、良くできる人と勉強始めたばかりの人を除いた、真ん中あたりの人です。なので、はてななどでblogを書いているような人にとっては物足りない内容かもしれません。

「モダン設計」についてすこし説明が必要かもしれません。これまで仕事やtenjin.webでクライアント側の実装状況を見てきた実感としては、イベントハンドラに設計無しでがりがり書くような状況が多く、HOWTO本をコピペして書くようなケースが圧倒的多数でした。そこで、そういう「脇役JavaScript」の延長でアプリケーションを構築してしまう方法に対して、JavaScriptの機能をフルに使って設計して実装する方法を「モダン設計」と呼ぼうというのがタイトルの由来です。モダーンクライアントサイドアプリケーション設計だと長いので。

今回取り上げた題材についてですが、いろいろ考えてMVCと状態管理にしました。どちらも大局的な設計方法です。サーバー側のMVCの情報はかなり多いのですが、ブラウザ側でのMVCや状態管理について入門的に触れた情報はほとんどありません。一方で、JavaScriptでのOOP技術やライブラリなどのミクロレベルの実装・設計、非同期の扱いについてはそれらに比べて数多くの情報がありますので、これらは含めないことにしました。さらにオブジェクト指向設計についても良書がいっぱいありますので、今回の記事には含めていません。そういう情報が必要になるところまで来てもらうことが今回の特集の役目かなと思っています。他にもいろいろ加えたい内容はあったんですが、書くパワーと割ける時間、ページの制限もあるところが難しいところでした。

という感じで読んだり、近所に紹介してもらえるとうれしいです。

tenjin.webで一度やった内容とはいえ、最新技術の紹介ではなくて考え方を伝えようとした内容だったので、下調べや全体の構成がすごく難しかったです。もちろんこういった雑誌に記事を書くのは初めてですし、どんな内容でも大変だとは思いますので気のせいかもしれません。

仕事が詰まっているうえに、仕事以外は全部こっちに時間を割いたので、各方面にご迷惑をおかけしたと思います。ごめんなさい。ごめんなさい。また、編集の稲尾さんには大変お世話になりました。プロの編集の威力に感動しました。一緒に書いたあがたさんにも大変助けてもらいました。一緒に仕事が出来て良かったです。ありがとうざいました。

なお、最近発生していたMVC祭りと今回の記事とは、自分の知る限り全く怪しい繋がりはないようです。でも、内容も含めて大変タイムリーな盛り上がりだと思いました。

5章サンプルコード(2009/12/25 追記)

4章まで読んだ後、5章を読んであれって思われた皆さん、ごめんなさい。記事の5章は設計だけで終わっているのですが、実際には完成一歩手前のほとんど動くコード(クライアントとサーバー)があります。以下のサポートページからダウンロードできます。

サーバー側のコードはJavaTomcat+Cubby)、クライアント側はJavaScriptで作ってあります。完全に完成させると細かいコードがふくれあがってしまい、かえって大局的な設計が見えにくくなるため、意図的に完成させてなかったり、抽象化を止めてベタな実装にしているところがあります。もちろん時間や工数的な問題もあったのですが、これ以上細かいところを完成させることはサンプルコードとして意味がないと判断して止めてます。もし興味がある人は、この先を実装してみたり、サーバーの実装をJava以外に取り替えてみたり、改良を重ねて実際に使えるアプリケーションにするのも面白いと思います。

紙面にサンプルコードがあることをお知らせする文章を書いていたつもりなのですが、漏れていました。ごめんなさい。ごめんなさい。

tenjin.web ユーザーインターフェース勉強会 第1回

  • 日時:2009/9/19(土) 13:00〜19:00
  • 場所:株式会社ヌーラボ(福岡市博多区中洲川端
  • 内容:「誰のためのデザイン」の1章読む、UIについて語る
  • 対象:UIについてすごく考えている人、いろいろ知ってる人
  • 参考:http://d.hatena.ne.jp/brazil/20090907/1252304113
  • 参加方法:tenjin.webのMLで自己紹介と参加表明をお願いします

tenjin.webシリーズは第2シーズンに突入しました。これまでの第1シーズンはJavaScriptなどWeb開発の技術でした。今回からのシリーズは、その技術を使ってどんな可能性があるか、どの方向に技術を向けるべきかを勉強し合う会になります。

ユーザーインタフェースというとかなり広いのですが、この会ではかなり深い分野を追求してみます。既存のWeb技術を使いやすくするというよりも、コンピューター以外の分野や論文などからUIの研究結果などを掘り起こし、全く新しいUIの可能性を検証してまわります。

何となくWebのUIに困っているんですよという人が来ると、ぼこぼこにされる勢いです。とはいっても、自分たちもよく分かっていないので、教えてください。皆さんの参加をお待ちしております。

tenjin.web/6 OST3

しばらく間が空きましたが、tenjin.webでオープンスペース方式の会をします。オープンスペースについては「http://capsctrl.que.jp/kdmsnr/wiki/bliki/?OpenSpace」を参照。

今回のテーマもWebについてのいろいろなのですが、技術の話で盛り上がりたいと思います。

tenjin.web/5 MVC やりました

今回に限らず準備が大変なのですが、id:brazilに手伝ってもらって、なんとか面白い感じで出来ました。ありがとうございます。また、来ていただいた人もレベルが高く、いろいろと議論では参考になりました。ありがとうございました。

当日の資料は tenjin.web/5 MVC においてあります。実習時間のコードですが、ふじた先生のコードが参考になります。というか、短時間で普通に使える物が出来るところがさすがですね。

次回はまだ考え中ですが、ネタの議論もかねてそろそろOST3をやろうという話になっています。