角丸幅可変ボタンでクロスフェードをする
角丸の幅可変ボタンを作ろうと思うと割と面倒くさいんですけど
さらにクロスフェードさせたい(実質クロスフェードではないんですが)
という欲望に負けてやってみました。
とりあえずMacでしか確認してないのでIEとかどうなるかわかりません。
IE6で崩れてたのでCSSを修正しました。
角丸可変ボタンのHTML
そもそも角丸幅可変のボタンを作ろうと思うと要素の入れ子は避けられません。
下のような感じになります。
SUBMIT
ムダな要素はJSで…
でもいいですけど、ここはデザインに直接影響するところなので
HTML+CSSだけでやったほうがいいです。
中のSPANはあきらめてください。僕は気にしてません。
角丸可変ボタンのCSS
これにCSSを書いていくと
たぶん以下みたいな感じになると思います。
ボタンは2つ以上並ぶ事も想定します。
使う画像は次の2つです。
p.btn { overflow: hidden; } p.btn a { float: left; padding-left: 5px; color: #fff; background: url(../../img/btn_left.gif) no-repeat left top; text-decoration: none; } p.btn a span { padding: 0 20px 0 15px; display: block; height: 35px; background: url(../../img/btn_right.gif) no-repeat right top; line-height: 35px; cursor: pointer; /* for IE */ }
最近は結構普通にinline-block使ってます。
floatで書きなおしました。
クロスフェードを実現するには
問題はここからですが
クロスフェードをさせるとなると、背景画像を2枚重ねていないとできません。
背景画像を入れ替えれば…CSS Spriteを使ってたらそういうわけにもいきません。
元々あるボタンの下にフェード後のボタンを配置して
mouseover時に上のボタンをフェードアウトさせればうまくいきそうです。
構造としては
- フェード後のボタン
- 元々あるボタン
を並列に並べて、
フェード後のボタンが元々あるボタンの下にくるようにする必要があるので
2つのボタンをグループ化して、
フェード後のボタンを絶対配置でグループの左上に配置します。
具体的には下のHTMLのようになります。
SUBMIT
SUBMIT
jQueryを使って構造を変える
さすがにこれは汚いので、jQueryで構造を変更しましょう。
グループを識別するためにidを割り当ててます。
$("a","p.btn").each(function(){
$(this).replaceWith("");
// 既存のボタンをグループと置き換える
$("span#cfG"+i)
.append(""+$(this).text()+"")
.append($(this).clone());
// フェード後のボタンを追加したのち
// 既存のボタンをその後ろに追加する
});
CSSを追記する
さらにCSSを追記します。
p.btn span.cfGroup { float: left; position: relative; } p.btn span.cfGroup span.cfGM { position: absolute; top: 0; left: 0; z-index: 10; } p.btn span.cfGroup span.cfGLeft { float: left; padding-left: 5px; color: #fff; background: url(../../img/btn_left.gif) no-repeat left -35px; text-decoration: none; } p.btn span.cfGroup span.cfGLeft span.cfGRight { padding: 0 20px 0 15px; display: block; height: 35px; background: url(../../img/btn_right.gif) no-repeat right -35px; line-height: 35px; }
さらにこのままだと、
既存のボタンとフェード後のボタンの重なりが逆になるので
z-indexを大きい数値にしておきます。
z-indexを使う場合は、position: relativeにする必要があります。
p.btn a { float: left; padding-left: 5px; position: relative; z-index: 100; color: #fff; background: url(../../img/btn_left.gif) no-repeat left top; text-decoration: none; }
上のボタンをフェードさせて実現する
ここまでくればあとは、
hover時に上に乗ってるボタンをフェードアウトさせるだけです。
$("a","p.btn").each(function(){
$(this).replaceWith("");
$("span#cfG"+i)
.append(""+$(this).text()+"")
.append($(this).clone());
// ここから下がフェード
$("a","span#cfG"+i).hover(function(){
$(this).fadeTo("normal",0);
},function(){
$(this).fadeTo("normal",1);
});
});
ポイント
フェードさせるときの注意がひとつだけあって
fadeOutにすると、最終的にdisplay: noneになるので
グループの幅と高さがなくなって、下にある要素が上に詰まります。
なので、ここではfadeToでOpacityのみを操作しています。
連続でホバーさせたときに動作が…
A要素にhoverするとfadeToが呼び出されて
フェードアニメーションが実行されますが連続でhoverさせると
アニメーションキューがたまっていって、ぴかぴかします。
これを解決するにはfade実行時に
直前のアニメーションキューを削除すればいいので
// ここから下がフェード $("a","span#cfG"+i).hover(function(){ $(this).queue([]).fadeTo("normal",0); },function(){ $(this).queue([]).fadeTo("normal",1); });
queue([])でアニメーションキューを空にすればぴかぴかしなくなります。
あ、、
このサンプルなら画像を2つに分ける必要はなかったですね…
Leave a comment
Trackbacks: 0
- Trackback URL for this entry
- Listed below are links to weblogs that reference
- 角丸幅可変ボタンでクロスフェードをする from 5509
Comments: 1 - Leave a comment
Hi! I like your srticle and I would like very much to read some more information on this issue. Will you post some more?