9月
06
2011
2

プログラマにも書ける!画像を使わずCSS3でつくる今風のタブ+ツールバー

TwitMgrのリニューアルに際して、今風のタブとツールバーを CSS3 だけで書いたので、その内容を順を追って説明してみます。

完成品

こんな感じのタブとツールバーを、CSS 3 だけで書いていきます。

フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

マークアップ

実際の TwitMgr で使ってるものとは違いますが、説明の都合上 HTML は下記のようなマークアップで行います。まだ何も CSS を適用していない状態なので、何がなにやらという状態ですね。

<div class="tab selected">フォローしている</div>
<div class="tab">フォローされている</div>
<div class="toolbar">
<ul class="pager">
  <li class="button enable">1</li>
  <li class="button enable">2</li>
  <li class="button current">3</li>
  <li class="button enable">4</li>
  <li class="button enable">5</li>
  <li class="period">...</li>
  <li class="button enable">≫</li>
</ul>
</div>
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

レイアウト

各部品の場所を決めていきます。位置関係が分かりやすいよう、仮で青のボーダーを入れました。ここはあまり特筆する点がありませんね。display と float を使って、適切な位置に要素を配置していくだけです。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
}
.toolbar {
  clear: both;
  height: 30px;
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

色の指定

文字の色と背景色を指定しました。普通に color と background-color を指定しただけですが、css3 らしい事としては、選択中のページを表す li.current に半透明の白色を指定する事で、その部分がハイライトされたような効果を出しています。
このようにする事で、背景色が変わったとしてもハイライト色を変える必要が無くなります。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
  color: #383;
}
.selected {
  background-color: #5a5;
  color: #fff;
}
.toolbar {
  clear: both;
  height: 30px;
  background-color: #5a5;
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
  color: #fff;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
}
.toolbar .pager li.current {
  background-color: rgba(255, 255, 255, 0.3);
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

ボーダーの指定

今度は各要素のボーダーを指定していきます。
いわゆる角丸を多用しています。四隅の特定の角だけを丸める事もできるので、タブっぽいデザインを書く時に便利です。ここまでくると何となくそれらしくなってきますね。

ページャー部分のボーダーは、背景色に合わせて半透明の白色にしています。背景色も文字もそれに含まれる要素も、全て一斉に半透明にする時は opacity で、背景色・ボーダーなど部分に応じて半透明にする時は rgba という使い分けをすると吉です。

またベンダープレフィックスとしてここでは、webkit (Chrome / Safari 等) と moz (Firefox 等) を付けています。他にも o (Opera) や ms (IE8+) もあるので、必要に応じて使い分けて下さい。

ただ、この状態では当たり前なのですが、選択中のタブとツールバーの間にも線が見えてしまっていますね。ここは綺麗に繋がってくれないと困ります。この問題は後で解決します。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
  color: #383;
  border-style: solid;
  border-color: #383;
  border-width: 1px 1px 0 1px;
  -webkit-border-top-left-radius: 5px;
  -moz-border-radius-topleft: 5px;
  border-top-left-radius: 5px;
}
.selected {
  background-color: #5a5;
  color: #fff;
  border-color: #373;
  border-bottom: 1px #5a5;
}
.toolbar {
  clear: both;
  height: 30px;
  background-color: #5a5;
  border: solid 1px #373;
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
  color: #fff;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
  border: solid 1px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.toolbar .pager li.enable {
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.current {
  background-color: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
  border: 0;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

グラデーションの指定

ツールバー部分にグラデーションをかけました。グラデーションの上端の色を選択中のタブの色と合わせる事で、シームレスに繋がるようにします。
このグラデーションの指定ですが、手作業で書くにはちょっと辛いので、Ultimate CSS Gradient Generator のようなジェネレータを使って書くのが良いかと思います。
ベンダープレフィックス付きの css を出力してくれるので、そのまま貼り付けるだけになります。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
  color: #383;
  border-style: solid;
  border-color: #383;
  border-width: 1px 1px 0 1px;
  -webkit-border-top-left-radius: 5px;
  -moz-border-radius-topleft: 5px;
  border-top-left-radius: 5px;
}
.selected {
  background-color: #5a5;
  color: #fff;
  border-color: #373;
  border-bottom: 1px #5a5;
}
.toolbar {
  clear: both;
  height: 30px;
  background-color: #5a5;
  border: solid 1px #373;
  background: -webkit-linear-gradient(top, #5a5 1%, #383 100%);
  background: -moz-linear-gradient(top, #5a5 1%, #383 100%);
  background: linear-gradient(top, #5a5 1%,#383 100%);
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
  color: #fff;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
  border: solid 1px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.toolbar .pager li.enable {
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.current {
  background-color: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
  border: 0;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

1px ラインの追加

デザイン系の記事で良く取り上げられる、1px の魔法を css で追加します。
具体的には右に 1px、下に 1px、ぼかし無しの状態で、要素の内側にボックスシャドウをかけます。こうするとちょうど、左上に 1px のラインを引いたような効果が出せます。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
  color: #383;
  border-style: solid;
  border-color: #383;
  border-width: 1px 1px 0 1px;
  -webkit-border-top-left-radius: 5px;
  -moz-border-radius-topleft: 5px;
  border-top-left-radius: 5px;
}
.selected {
  background-color: #5a5;
  color: #fff;
  border-color: #373;
  border-bottom: 1px #5a5;
  padding-right: 8px;
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
}
.toolbar {
  clear: both;
  height: 30px;
  background-color: #5a5;
  border: solid 1px #373;
  background: -webkit-linear-gradient(top, #5a5 1%, #383 100%);
  background: -moz-linear-gradient(top, #5a5 1%, #383 100%);
  background: linear-gradient(top, #5a5 1%,#383 100%);
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
  color: #fff;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
  border: solid 1px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.toolbar .pager li.enable {
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.current {
  background-color: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
  border: 0;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

タブとツールバーをつなぐ

ボーダーを追加して以来ずっと気になっていた、選択中のタブとツールバーの間の線を隠します。
まずタブの高さ自体がそもそも 14px になっているので、選択中のタブはそれにボーダー幅 1px と、ボックスシャドウ幅 1px を足した 16px にします。
そのままだと、非選択のタブと選択中のタブの高さが変わって、片方が浮いてしまう感じになるので、さらに margin-bottom を -2px にします。

こうする事で選択中のタブが占める高さは非選択のタブと同じ高さになるものの、背景の描画自体は 2px 分下に伸びる形になるので、ツールバーとの間にあった線を隠す事ができます。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
  color: #383;
  border-style: solid;
  border-color: #383;
  border-width: 1px 1px 0 1px;
  -webkit-border-top-left-radius: 5px;
  -moz-border-radius-topleft: 5px;
  border-top-left-radius: 5px;
}
.selected {
  height: 16px;
  margin-bottom: -2px;
  background-color: #5a5;
  color: #fff;
  border-color: #373;
  border-bottom: 1px #5a5;
  -webkit-border-bottom-right-radius: 2px;
  -moz-border-radius-bottomright: 2px;
  border-bottom-right-radius: 2px;
  padding-right: 8px;
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
}
.toolbar {
  clear: both;
  height: 30px;
  background-color: #5a5;
  border: solid 1px #373;
  background: -webkit-linear-gradient(top, #5a5 1%, #383 100%);
  background: -moz-linear-gradient(top, #5a5 1%, #383 100%);
  background: linear-gradient(top, #5a5 1%,#383 100%);
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
  color: #fff;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
  border: solid 1px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.toolbar .pager li.enable {
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.current {
  background-color: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
  border: 0;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

テキストの書式を調整する

残りは微調整になりますが、テキストの書式を指定していきます。
センタリングやフォントサイズの調整の他、選択中のタブやページを強調するためにテキストシャドウを指定しました。
下に 1px の位置にぼかし無しのシャドウを付けています。あまり離したり、ぼかしすぎたりすると 90 年代テイストの野暮ったさになってしまうので気を付けたいところです。

ところでこのテキストシャドウ、本当は 1px 程度はぼかした方が見た目が柔らかくなっていいのですが、XP 上の Chrome 限定で、「本来アンチエイリアスがかかっていないフォントに、テキストシャドウをぼかして適用するとアンチエイリアスがかかる」という仕様 (バグ?) があって、隣のシャドウ無しのフォントと見た目が変わってしまうので、あえてぼかし無しにしています。
自分が XP 上で Chrome を使っていて気になるというだけなので、気にせずぼかしを適用しても良いかも知れません。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
  color: #383;
  border-style: solid;
  border-color: #383;
  border-width: 1px 1px 0 1px;
  -webkit-border-top-left-radius: 5px;
  -moz-border-radius-topleft: 5px;
  border-top-left-radius: 5px;
}
.selected {
  height: 16px;
  margin-bottom: -2px;
  background-color: #5a5;
  color: #fff;
  border-color: #373;
  border-bottom: 1px #5a5;
  padding-right: 8px;
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
  text-shadow: 0 1px 0 #333;
}
.toolbar {
  clear: both;
  height: 30px;
  background-color: #5a5;
  border: solid 1px #373;
  background: -webkit-linear-gradient(top, #5a5 1%, #383 100%);
  background: -moz-linear-gradient(top, #5a5 1%, #383 100%);
  background: linear-gradient(top, #5a5 1%,#383 100%);
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
  color: #fff;
  text-align: center;
  font-size: 90%;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
  border: solid 1px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.toolbar .pager li.enable {
  border-color: rgba(255, 255, 255, 0.5);
}
.toolbar .pager li.current {
  background-color: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
  text-shadow: 0 1px 0 #333;
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
  border: 0;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

ユーザビリティを向上させる

静的な見た目についてはすでに完成していますが、オンマウス時の挙動を指定する事でユーザビリティを向上させます。

まずクリック可能な要素に対して cursor を pointer にするのは基本中の基本です。a 要素を使えばデフォルトのスタイルがそうなるのですが、HTML の思想からしてページ遷移 (ページ内ジャンプを含む) 以外で a 要素を使うのは正しいとは言えません。
余談ですが、a 要素の name 属性も HTML5 で廃止されました。要素に名前を付けるために a を使うなという事です。

なお、クリック時の動作自体は、JavaScript で動的に付与します。onclick 属性は Ajax で HTML を差し込む時に便利だったのですが、jQuery の live を使えば、後から追加される要素にも動的にイベントを付与出来るので、昔ながらの手法はそろそろ終わりにしましょう。

後は、hover 時のスタイルを追加します。タブが上に伸びたようになるのは、padding-top を増やした分、margin-top を減らす事で表現しています。
この時 transition を使えばさらにアニメーションさせる事もできるかと思ったのですが、padding と margin を同時に変化させると、アニメーションがガタガタしてしまうことが分かったので適用していません。

.tab {
  margin: 10px 5px 0 0;
  padding: 5px 7px;
  float: left;
  height: 14px;
  color: #383;
  border-style: solid;
  border-color: #383;
  border-width: 1px 1px 0 1px;
  -webkit-border-top-left-radius: 5px;
  -moz-border-radius-topleft: 5px;
  border-top-left-radius: 5px;
  cursor: pointer;
}
.tab:hover {
  padding-top: 7px;
  margin-top: 8px;
}
.selected {
  height: 16px;
  margin-bottom: -2px;
  background-color: #5a5;
  color: #fff;
  border-color: #373;
  border-bottom: 1px #5a5;
  padding-right: 8px;
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
  text-shadow: 0 1px 0 #333;
}
.toolbar {
  clear: both;
  height: 30px;
  background-color: #5a5;
  border: solid 1px #373;
  background: -webkit-linear-gradient(top, #5a5 1%, #383 100%);
  background: -moz-linear-gradient(top, #5a5 1%, #383 100%);
  background: linear-gradient(top, #5a5 1%,#383 100%);
  -webkit-box-shadow: 1px 1px 0 #9c9 inset;
  -moz-box-shadow: 1px 1px 0 #9c9 inset;
  box-shadow: 1px 1px 0 #9c9 inset;
}
.toolbar .pager {
  display: block;
  float: right;
  margin: 6px;
}
.toolbar .pager li {
  display: block;
  float: left;
  margin-left: 2px;
  color: #fff;
  text-align: center;
  font-size: 90%;
}
.toolbar .pager li.button {
  width: 20px;
  padding: 1px;
  border: solid 1px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.toolbar .pager li.enable {
  border-color: rgba(255, 255, 255, 0.5);
  cursor: pointer;
}
.toolbar .pager li.enable:hover {
  background-color: rgba(255, 255, 255, 0.3);
}
.toolbar .pager li.current {
  background-color: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
  text-shadow: 0 1px 0 #333;
}
.toolbar .pager li.period {
  width: auto;
  padding: 1px 2px;
  border: 0;
}
フォローしている
フォローされている
  • 1
  • 2
  • 3
  • 4
  • 5

さいごに

CSS3 を使う時は、ついつい派手に使いたくなるのですが、さりげなくワンポイントずつ使うと、比較的こなれた仕上がりになるようです。

また、例によって IE のようなレガシーブラウザでは、意図したとおりの見た目にはなりません。
IE6 でのキャプチャは以下のようになります。

このままだと厳しそうですが、選択中のページの背景色を半透明以外にも指定しておけば、ぎりぎり意図は伝えられるレベルですね。
プログレッシブエンハンスメント (長すぎ!略称募集) も意識したデザインをやっていければいいなと思います。

Written by Otchy in: Development | タグ: ,
10月
20
2010
2

HTML5+CSS3 使ってみた感想

Cron Builder を作るにあたって、初めてちゃんと HTML5+CSS3 を使ってみたので、その雑感などをメモ程度に書いてみます。

HTML5

header、footer、nav
分かりやすくていいです。ソースが見やすくなります。
早くエディタ側の対応が進んで、見やすく色分けしてくれるようになると嬉しいですね。
section
Cron Builder みたいなウェブアプリの場合、使いどころにちょっと悩みます。今回はタブの中身で使ってみました。article 要素に至っては、使いどころがないです。
ブログとかニュースサイトなら綺麗にハマるんだと思いますが、ウェブアプリの場合、新規追加の要素を無理して使う必要はないですよね。
header とか section って、ブロック要素じゃないの?
header、footer、section を最初、名前が違うだけのdiv のつもりで使ってたら、Chrome は意図通り表示されたのに、Firefox はブロック要素として振る舞っていませんでした。(未確認ですが inline-block ぽい?)
display: block して事なきを得ましたが、この辺って正しくはどうあるべきなんでしょう?(Fx 3.6 が実は HTML5 に対応していないだけ??)
div
せっかくだから、div 要素を使わずにやってみようと思って始めましたが、結局挫折。少し凝ったことをやろうとすると、やっぱり「論理的な意味を持たない枠」が必要になるので、そこは結局 div にしました。
まあ、無しにするのは難しいですが、div は確実に減らせます。div が減ると class とか id の指定も減らせて、CSS のセレクタが綺麗になるのが嬉しいところです。
その他 canvas、video、audio など
派手派手しい要素は全然使ってません。

CSS3

:hover
CSS3 じゃないけど、IE が a 要素にしか対応してなかったので、気分としては CSS3。a 要素以外にも色々使うと、スマートに書けます。
よく li の中に a を入れて…ってやってましたが、今回、タブを表す li 要素に直接 :hover したら HTML がスッキリしました。気持ちいい。
onclick イベントも jQuery の後乗せで li に直接付与して実現してて、a 要素の使用は本当の意味でページ遷移する時だけです。意味的にも綺麗で精神的によろしい。
border-radius
言わずと知れた角丸。もはや定番という意識です。
Fx 3.6 はまだベンダープレフィックスが必要なのがちょっと意外でした。Fx 4.0 では要らなくなるのかな?
text-shadow
実装されたのが昔だけあって、抜群の安定感。Cron Builder ではロゴにあたる部分で使用してます。
最近、本文に微妙にずらした text-shadow をかける例を見かけますが、やりすぎると見にくくなるので気を付けたいところですね。
調子に乗って、5px 5px 5px とか離しすぎでぼかしすぎの影を付けると、雰囲気が一気に 90 年代テイストになりますw
box-shadow
影繋がりで次は box-shadow。こっちは最近の実装なので、Chrome も Firefox もベンダープレフィックスが必要です。でも、ルール自体はシンプルなので使い勝手はブラウザに寄らず同じでした。
inset (内側の影) を指定すると窪んだ感じを表現できます。
Cron Buider では、border-radius と box-shadow: inset を組み合わせて使っていて、同じ事を CSS3 無しでやろうと思ったら、画像はいくつも必要だし、マークアップも汚くなってしまいます。今回、一番 CSS3 の恩恵を感じた部分はここでした。
グラデーション
最後はこれです。仕様未決定でしたっけ?ベンダープレフィックスどころか、実装によってそもそも書式が全然違うし、それらも複雑です。
オンライン上に色々とグラデーション CSS のジェネレータがありますが、グラデーションの指定はジェネレータが無いと書けないと思います。
その他
アニメーションとか回転とかは使ってません。CSS3 を考えた人達が「CSS3 すげーんだぜ!」って言いたい気持ちは分かるんですが、やりすぎじゃないかなぁと思ってます。昔懐かしい blink とか marquee の匂いを感じるんですがどうなんでしょう?

ざっとこんなところです。
全般的にみて、マークアップが綺麗になるケースが多く、それに伴い CSS のセレクタも分かりやすくなるケースが多かったので、将来的には主流になっていくと思いました。
jQuery 使ってると、CSS セレクタが分かりやすい=jQuery が分かりやすいっていう事なので、特に助かりますね。

スタンダードな使い方をしている限り、ブラウザ間の挙動の違いもほとんど無いので楽に作れます。
え?IE?もちろん、全力で無視してます。
body 直下に以下の条件付きコメントを入れているのが、せめてもの良心でしょうか。

<!--[if IE]>
<div style="padding: 5px; border: 3px solid #f00; background: #fee; color: #f00; font-size: 10pt;">
IE では一切動作確認していません。恐らく動作しません。
</div>
<![endif]-->
Written by Otchy in: Development | タグ: ,
5月
19
2009
2

css による疑似フレーム IE6 標準準拠モード完全対応版 (CSS ハック / JavaScript未使用)

css のみを使って、ヘッダ / メニュー / フッタをスクロールしないように固定して疑似フレームを表現する手法は position: fixed による方法が広く知られています。
この方法は、手軽に疑似フレームを表現できる一方で、IE6 が対応していないという非常に残念な現実があり、対象ブラウザから IE6 を完全に外してしまえるような状況ならともかく、(特に仕事の上などでは) IE6 を対象から外せない事も多いので頭痛の種でした。

IE 独自拡張の expression を使って、fixed に近い状況を作り出す技が色々と開発されているのですが、どうも自分にしっくり来るものがありませんでした。
そこで、下記の条件を満たすやり方を開発したので公開します。

  • IE6 標準準拠モードで動作させる
    IE 7 に関して、fixed を正しく動作させるために標準準拠に関しては重要な要件
  • css ハックは使わない
    将来のブラウザのバージョンで異変が起きる可能性を排除
  • メニューもフッタも固定する
    ヘッダだけの固定であればシンプルな実装が他にもある
  • 無駄な HTML マークアップを追加しない
    HTML 自体は fixed 対応ブラウザのみの場合と同様
  • 極力シンプルに記述できる
    冗長なコードを書いて無理矢理つじつまを合わせるような事はしない
  • スクロール時に画面がちらつかない
    expression の使い方によってはダサイ見た目になってしまうのでそれを回避
  • IE6 以外のブラウザに影響を与えない
    当然

論より証拠。まずはサンプルを見て下さい。
このページでは、ヘッダ / メニュー / フッタの 3 つがスクロールに対して固定されています。
fixed 対応ブラウザでは fixed で実現され、IE6 に関しては expression をちょっとだけ使っています。

まず、一般的な fixed 部分について簡単に解説します。

<div id="header">ヘッダ</div>
<div id="menu">メニュー</div>
<div id="contents">
START<br />
コンテンツ...<br />
END<br />
</div>
<div id="footer">フッタ</div>

HTML については、非常にシンプルです。
各部位ごとに異なる id を指定した div があるだけです。

css のうち装飾に関わる部分を除くとこんな感じです。

* {
	margin: 0;
	padding: 0;
}
#header {
	position: fixed;
	left: 0;
	top: 0;
	width: 100%;
	height: 24px;
	z-index: 3;
}
#menu {
	position: fixed;
	left: 0;
	top: 0;
	width: 150px;
	height: 100%;
	padding-top: 24px;
	z-index: 2;
}
#contents {
	padding: 24px 0 24px 150px;
	z-index: 1;
}
#footer {
	position: fixed;
	left: 0;
	bottom: 0;
	width: 100%;
	height: 24px;
	z-index: 3;
}

#header / #menu / #footer については、fixed で固定されています。
#menu / #contents では padding を指定する事で、重なってしまう部分が隠れないようにしてあります。
fixed 対応ブラウザであれば、これだけで疑似フレームの完成です。標準準拠モードになるよう、DOCTYPE を指定しているので、IE7 であっても同様に動作します。

続いて、IE6 向けの設定です。

<!--[if lt IE 7]>
<style>
#header, #footer, #menu {
	position: absolute;
}
#contents {
	overflow: auto;
	height: expression((document.documentElement.clientHeight - 48) + 'px');
}
#menu {
	height: expression((document.documentElement.clientHeight - 48) + 'px');
}
</style>
<![endif]-->

意外なほどシンプルではないでしょうか?これだけです。

<!–[if lt IE 7]> から始まる記述は IE 独自拡張の条件付きコメントで、IE 以外のブラウザでは完全に無視されます。
ここでは、IE 7 未満の IE を指定して専用の記述を読み込ませています。
どうせ IE に対してのみ動作を変えるのであれば、変に CSS ハックを使うよりよほどリスクが少なく確実な方法だと思います。

position: absolute; は、fixed に対応していない IE6 のために、設定を上書きしています。
css の設定は後勝ちなので、IE6 向けの設定は fixed 向けよりも後に書く必要があります。

#contens / #menu にある、expression がポイントです。
expression は、filter 関数などと同様の IE 独自拡張で、任意の JavaScript コードを使用して動的に css の値を指定する事が出来きるものです。

ここでは、#contents / #menu の高さを、ウィンドウ内部の高さからヘッダとフッタの分を引いた値に指定しています。
これにより「メニューとコンテンツ部分がウィンドウからはみ出ない」という状況が生まれ、実質的な疑似フレームになります。
また、expression 関数は、ウィンドウサイズが変更された際などにも自動的に再計算されます。

ヘッダとフッタの top や left を expression 関数で設定する手法も見かけたのですが、これだとスクロール時にちらつきが出るのでイマイチです。
この手法は、ウィンドウ自体がスクロールしないよう抑制し、コンテンツ部分のみを overflow: auto; でスクロールさせるという逆転の発想で実装されています。

ソースの全容はサンプルをダウンロードして確認して下さい。
また、実際に使用する時はもちろん、css を直接 HTML に書かず、外部ファイルに切り出した方がよいです。

Written by Otchy in: Development | タグ: , ,
3月
30
2009
2

サーバサイド高機能エディタ ecoder インストール方法

ecoder って何?

ブラウザ上でソースコード編集が可能な開発環境を提供「ecoder」:phpspot開発日誌 で紹介されている、激しく便利そうなエディタです。
ブラウザ上から、こんな感じでサーバ上のファイルを直接編集することができます。

HTML の編集CSS の編集JavaScript の編集PHP の編集

順に、HTML / CSS / JavaScript / PHP を編集している様子です。これらのファイルが、色分けされた状態でブラウザで編集できるなんて、よだれが止まりません。

そこで早速インストールしてみようとしたところ、まだベータ版ゆえか、公式ではいっさいドキュメントが用意されていなかったので、ソースを読みながらインストールした記録を公開することにしました。

対象者

  • PHP の動作するサーバを使用できる
  • Linux 設定について基本的な事を理解している or 自分で調べられる
  • Apache の設定について基本的な事を理解している or 自分で調べられる

ファイルのダウンロードと展開

ecoder のウェブサイトから、tar.gz ファイルをダウンロードして、ecoder を配置したい場所に展開します。
現在の最新版 (ver 0.3.2) の直 DL は http://downloads.sourceforge.net/ecoder/ecoder_0.3.2.tar.gz?use_mirror=jaist&filesize=406946 ですが、まだベータ版の状態なので、インストール時点での最新版を調べて DL した方が良いです。

Windows で作業をする場合は、ブラウザから DL して展開したファイルに対して、後述の設定変更を行った後に、FTP なりでアップすると良いでしょう。
ここでは、Linux 上で作業を完結させるためのコマンドを掲載しておきます。
DL するパスとか展開するパスは、それぞれの環境に合わせて読み替えてください。

$ su -
# cd /usr/local/src/
# mkdir ecoder_0.3.2
# cd ecoder_0.3.2
# wget http://downloads.sourceforge.net/ecoder/ecoder_0.3.2.tar.gz?use_mirror=jaist&filesize=406946
# tar xfvz ecoder_0.3.2.tar.gz
# mv ecoder_0.3.2.tar.gz ../
# cd ../
# cp -a ecoder_0.3.2/ /var/www/www.otchy.net/himitsu
# cd /var/www/www.otchy.net/
# chown -R apache:apache himitsu/
# cd himitsu/
# find -type d -exec chmod 755 {} \;
# find -type f -exec chmod 644 {} \;

※最後の権限変更は、デフォルトの設定がいろいろと気持ち悪かったのでなおしました

設定ファイルの編集

ルートディレクトリ直下にある code.php というファイルに、正しい設定を書かないと ecoder は動作しません。といっても、必要な設定はすべてここにまとめられているので、さほど難しくはないかと思います。
以下では、修正が必要な項目について、本サイトの設定を例に順番に説明します。
まずは、大抵の場合で修正が必要な項目です。

動作させるサイトのドメイン。

$code['domain'] = "http://www.otchy.net/";

クッキーを適用するドメイン。

$code['domain_cookie'] = "www.otchy.net";

編集するファイルのルート。スラッシュから始まるフルパスで記述する。

$code['root'] = '/var/www/www.otchy.net/';

エラーログの出力先。後述の .htaccess の設定と同じパスにする。
事前に Apache ユーザに対して書き込み許可を与えておく必要がある。

$dbug['error_path'] = '/var/log/ecoder/error.log';

続いて、必要に応じて修正するといいかも知れない項目です。

自動セーブ機能をデフォルトで ON にするかどうか。保存即公開の場合は、OFF 推奨。
デフォルト OFF になっていても、画面上から切り替えることが可能。

$code['autosave'] = 0;

自動セーブ機能を ON にした場合のセーブ間隔 (秒)

$code['autosave_time'] = 10;

編集時に裏でバックアップをするかどうか。

$code['backup'] = 1;

ツリービューに表示させるファイルの拡張子。

$_SESSION['tree_file_types'] = array( "php", "js", "html", "css", "txt", "htaccess", "ini" );

アップロードできないようにするファイルの拡張子。

$_SESSION['upload_banned'] = array( "exe" );

ツリービューの中で無視するファイル名。

$_SESSION['tree_file_ignore'] = array ( ".ftpquota" )

ツリービューの中で無視するディレクトリ名。

$_SESSION['tree_dir_ignore'] = array( ".", "..", ".files", ".snap", "logic", "cpanel", "ftp", "00", "01" );

セキュリティと .htaccess 設定

上記の設定を施しただけでも、とりあえず ecoder は動作し、ファイルの編集、保存を行うことができます。
ただ、セキュリティは全く考慮されておらず、URL さえ知っていれば、誰でも編集可能な状態になってしまいます。

実は、ecooder 自体でもセキュリティの仕組みを持っていて、code.php において、$code['secure'] = 1; と設定すれば、認証機能を有効にすることができます。
ただ、この認証は、別プログラムでアカウントを認証し、設定したキー名で PHP のセッションを発行する事により機能するようです。(推測)
既存のシステムにシングルサインオンで組み込むには非常に適した仕組みですが、認証プログラム自体は同梱されておらず、別途作り込む必要があります。

そんな面倒くさい作り込みはしたくないので却下して、ここでは簡単に BASIC 認証を設定しておくことにします。
平文でパスワードが流れるのが嫌な方は、SSL を同時に適用することをお勧めします。
自分専用の編集サイトであれば、おれおれ証明書でも十分ですし。
(その辺の設定については本記事の範疇外ですので別サイトなど参照してください。)

以上を踏まえた、.htaccess の編集箇所は以下の通りです。

ログファイルの出力先の権限を設定

<Files /var/log/ecoder/error.log>
  Order allow,deny
  Deny from all
  Satisfy All
</Files>

ログファイルの出力先を設定

php_value error_log /var/log/ecoder/error.log

BASIC 認証を追加

AuthUserFile /var/www/www.otchy.net/himitsu/.htpasswd
AuthGroupFile /dev/null
AuthName "ecoder login"
AuthType Basic
require valid-user

<Files .htpasswd>
  order allow,deny
  deny from all
</Files>

さらに、.htpasswd ファイルを作成する必要がありますが、ここでは詳しく説明しません。
Apache 同梱の htpasswd コマンドを使うのが一番楽かと思います。

$ htpasswd -c .htpasswd username

以上で、設定は完了です。
ファイル一式を配置したフォルダをブラウザから開けば、高機能なエディタが利用できます。
もし何らかの設定が間違っている場合、ecoder 側で結構丁寧なエラーメッセージを表示してくれるので、それを元に修正していけば大丈夫です。

この ecoder と AjaXplorer を組み合わせて使えば、簡単な開発はもう Web 上で完結できるんじゃないかという気がしてきますね。
すばらしい時代になったものです。

Written by Otchy in: Development | タグ: , , ,
2月
19
2009
2

右下または左下においた画像に文字列を回り込ませるHTML/CSS

普通、HTML で画像の回り込みというと、右上か左上に画像があって、そこに文字列が回り込むという感じです。これは簡単です。画像に対して float: left; すれば OK です。
しかし、右下か左下に画像を固定して、文字列がそこにたどり着いたら回り込むという動作は一筋縄ではいきません。
画像をブロックの左下に配置してテキストを回り込ませる方法を考える というページで色々と考察されていて、ふむふむと思ったのですが、この方法では、テキストの量が変わるたびに調整が必要になってしまうので、テキストの量が動的に変わる場合には対応しにくいです。
何より、文章をぶった切って画像を入れるというのはどうもスマートではありません。

色々と試行錯誤してみたところ、以下の方法で実現できそうだったので、公開してみます。

<html>
<head>
<style>
#block {
    width: 200px;
    height: 200px;
    overflow: hidden;
    font-size: 10pt;
    border: solid 1px #666;
    padding: 0.5em;
}
#bar {
    float: right;
    width: 1px;
    height: 100px;
    background-color: red;
}
#img {
    float: right;
    clear: both;
    width: 100px;
    height: 100px;
    background-color: blue;
}
</style>
</head>
<body>
<div id="block">
<div id="bar"></div>
<div id="img"></div>
ああああああああああああああああああああああああああああ
ああああああああああああああああああああああああああああ
ああああああああああああああああああああああああああああ
ああああああああああああああああああああああああああああ
ああああああああああああああああああああああああああああ
</div>
</body>
</html>

このソースを保存して開くと、以下のような見た目になります。
わかりやすいように色分けした div で表現していますが、赤線は実際には透明、青い四角は実際には画像だと思って下さい。

ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ

#bar の部分とか美しいマークアップとは言えないですし、画像に文字が被ったりとかしてますが、微調整してやれば十分使い物になるかと思います。
最初は絶対実現できないんじゃないかと思ったので、出来た時は嬉しかったですね~。

Written by Otchy in: Development | タグ: , ,

Powered by WordPress | Aeros Theme | TheBuckmaker.com