ボタンの押し込みをCSSで表現する

ボタンの文字列を1pxだけ下に動かして押しこみを表現する。

時代は:active! タッチ・デバイスに:hoverなどない! みたいになりつつあるような気がしないでもないので、ボタンの押し込みの表現を色々考えている。とは言ってもタッチ・デバイスでは:active擬似クラスもいまいちアレなのでまだあんまり意味なかったりするけど。三周回ってデフォルト使えみたいな感じになっている節もある。ですよねー。

Demo: Pixel Pushing

padding

一番のメジャーで安定のクオリティー。

.test {
  padding-top: 10px;
  padding-bottom: 10px;
}

.test:active {
  padding-top: 11px;
  padding-bottom: 9px;
}

欠点はpx単位でpaddingプロパティーを制御せざるを得ないのでスケーラブルにしづらくなること。

position

ボタンのテキストだけでなく全体を動かす場合はpositionで動かすと簡単。

.test:active {
  position: relative;
  top: 1px;
}

他のCSSプロパティーとまったく干渉しないのが素晴らしいが、そのままだとちょっと違和感があるのでデモのposition #2の様にbox-shadowプロパティーを使って立体感をフォローした方が良い。

line-height

ボタンの高さを指定する場合はline-heightプロパティーでも可能。

.test {
  height: 2em;
  line-height: 2;
  overflow: hidden;
}

.test:active {
  line-height: 2.05;
}

ボタンのテキストの中央揃えにheightline-heightプロパティーを使うことも多いので、意外に導入コストは低め。paddingプロパティーに比べると多少はスケーラブルにしやすい(計算でなんとかなる)ところも良い。後続の要素の位置に影響を与えてしまうことがあるので、動作確認が面倒臭いのが難点。

text-shadow

最近考えだしたのがcolor: transparenttext-shadowプロパティーを組み合わせる方法。

.test {
  color: #999;
}

.test:active {
  color: transparent;
  text-shadow: 0 1px #999;
}

box-shadowプロパティーと違い、text-shadowプロパティーははみ出した部分のみではなく文字全体の影が完全に作られる。のでcolorプロパティーでtransparentを指定してやると影が全部見えるようになるというわけ。プロパティーの性格上、ボタンにした要素のボックス・モデルにまったく影響を与えないというのが最大の利点。Firefox 10やChrome 17、Safari 5では問題なく動くが、Internet Explorer 9ではまだtext-shadowプロパティーに対応していないので動かず、Opera 11でもバグらしき挙動(後述)がありうまく動かない。


text-shadowプロパティーを使ったものを思いついた時に「これはいける!」とかちょっと思ったんだけど、text-shadowプロパティーに対応していないInternet Explorer 9はともかく、Opera 11でもcolor: transparentにするとtext-shadowが消えるというバグらしき挙動があってうまくいかなかった……。

というわけで今のところは、スケーラブルでなくて良いのならpaddingプロパティーでやるのが良く、スケーラブルにしたい場合はbox-shadowプロパティーの力を借りつつpositionプロパティーでボタン全体を動かすのが良いというのが僕の結論になった。text-shadowプロパティーを使う方法は気に入ったんだけどなぁ……。

追記

デモでボタンをクリックするとページの先頭に戻るのは良くないのは確かにそうなんだけど、button要素で使われるネイティブUIの挙動の癖を統一するのは難しい(というか知らない)。appearanceプロパティーがInternet Explorer 9やOpera 11でサポートされればもうちょっとなんとかなるようになるかもしれないけど、今はまだかなーと思っていて、button要素と特に:active擬似クラスの組み合わせはあまり使いたくない。

というだけではなんなので、button要素を使ったデモも作っておいた。

あと記事のpaddingプロパティーのコードが間違っていたのも@GeckoTang教えてもらったのでこっそり直してた。

追記 #2

@ofkセレクターも間違ってることを教えてもらったのでそっちも直した。