Hatena::ブログ(Diary)

Cyokodog :: Diary

こちらのブログは更新を停止しております。最新の記事は以下ブログをご覧ください。
www.cyokodog.net

April 27, 2012

一定範囲で position:fixed させる Ex Flex Fixed がかゆいとこだらけだったので作り直しました

かゆいとこだらけの Ex Flex Fixed (サイドメニューなどを一定の範囲でのみ position:fixed させる jQuery Ex Flex Fixed)を作り直しました。

改善内容

  • fixed 要素の幅を自動調整するようにした
  • リキッドレイアウト(可変幅)でちゃんと表示するようにした
  • fixed 要素がコンテナからはみ出ないようにした
  • fixed 要素がウィンドウ高さに収まらない状態でのスクロール時の表示を見やすくした
  • 動的にレイアウトサイズが変更されても、ちゃんと表示されるようにした
  • カラム高さを揃えるプラグインと併用できるようにした

という訳で半年も放置しておいてあれですが、ちょくちょく問い合わせもあるので、ご利用の際には新バージョンでどうぞ。

動作確認

以下のレイアウトのデモページで、新旧それぞれのバージョンの動作を確認してみます。

f:id:cyokodog:20120426201437p:image

<div class="header"></div>
<div class="contents-wrapper">
	<div class="sub-contents-wrapper">
		<div class="sub-contents">
			sub contents
		</div>
	</div>
	<div class="main-contents-wrapper">
		<div class="main-contents">
			main contents
		</div>
	</div>
	<div class="ext-contents-wrapper">
		<div class="ext-contents">
			ext contents
		</div>
	</div>
</div>
<div class="footer"></div>
/* 全体をセンタリング */
body{
	margin :0 auto;
	max-width : 1000px;
	min-width : 600px;
}

/* clearfixでwrapperに高さを出す */
div.contents-wrapper{
	/zoom : 1;
}
div.contents-wrapper:after{
	content : '';
	display : block;
	clear : both;
}

/* subを固定幅 */
div.sub-contents-wrapper{
	margin-right : -200px;
	float : left;
	width : 200px;
	position : relative;
	z-index:1;
}
/* extを%指定可変幅 */
div.ext-contents-wrapper{
	margin-left : -30%;
	float : left;
	width : 30%;
	position : relative;
	z-index:1;
}
/* margin,padding,borderをつける */
div.sub-contents,
div.ext-contents{
	margin:16px;
	padding:8px;
	border:solid 4px #ccc;
}

/* メインコンテンツを可変幅 */
div.main-contents-wrapper{
	float : left;
	width:100%;
	position : relative;
}
div.main-contents{
	margin:16px;
	margin-left : 216px;
	margin-right : 31.5%;
	width : auto;
	padding:8px;
	border:solid 4px #ccc;
}

/* wpapper はblue系 */
div.contents-wrapper{
	background:#c0e0ff;
}
div.main-contents-wrapper{
	background:#b0d0ff;
}
div.sub-contents-wrapper,
div.ext-contents-wrapper{
	background:#a0c0f0;
}
/* contents はgray系 */
div.main-contents{
	background:#e8e8e8;
}
div.sub-contents,
div.ext-contents{
	background:#f0f0f0;
}

デモでは div.sub-contents、div.ext-contents を固定表示にします。

$('div.sub-contents,div.ext-contents').exFlexFixed({
	container : 'div.contents-wrapper'
});

デモ画面では、「Ex Flex Fixedを適用する」ボタンをクリックすると実行されます。

fixed 要素の幅を自動調整するようにした

通常 position:fixed を適用すると、内包物に合わせて幅が縮小しますが、position:static のように親要素に合わせた幅調整がされます。

f:id:cyokodog:20120426201438p:image

Demo(旧) Demo(新)

任意の幅に固定したい場合は、width パラメータを指定します。

$('div.sub-contents,div.ext-contents').exFlexFixed({
	container : 'div.contents-wrapper',
	width : 80
});

リキッドレイアウト(可変幅)でちゃんと表示するようにした

旧バージョンでは、ウィンドウのリサイズで左カラムの表示位置がずれてしまいましたが、ずれないよう修正。

f:id:cyokodog:20120426201439p:image

Demo(旧) Demo(新)

fixed 要素がコンテナからはみ出ないようにした

メインコンテンツの内容が少ないと、コンテナの高さがでず fixed 要素がはみ出してしまいましたが、はみ出さないよう修正。

f:id:cyokodog:20120426201440p:image

Demo(旧) Demo(新)

fixed 要素がウィンドウ高さに収まらない状態でのスクロール時の表示を見やすくした

fixed 要素が大きくウィンドウ高さに収まらない状態でスクロールした場合、fixed 要素の全体を表示した後、位置固定をしますが、旧バージョンでは、上方向に向かってスクロールした場合、位置固定後のスクロールとなってしまい閲覧性がいまいちだったので修正。

f:id:cyokodog:20120426201441p:image

Demo(旧) Demo(新)

上下にスクロールし、右カラムの表示のされ方を確認してください。

動的にレイアウトサイズが変更されても、ちゃんと表示されるようにした

旧バージョンでも(固定レイアウトに限り) watchPosition パラメータを指定する事で、ある程度対応できてましたが不完全でしたので修正。

$('div.sub-contents,div.ext-contents').exFlexFixed({
	container : 'div.contents-wrapper',
	watchPosition : true
});

f:id:cyokodog:20120426201442p:image

Demo(旧) Demo(新)

ダミーテキストを、×で削除、+で追加することでレイアウトサイズを変更してみてください。

カラム高さを揃えるプラグインと併用できるようにした

Ex Equal Height という動的にレイアウトサイズが変更された場合でも、カラム高さを揃える事のできるプラグインを作りましたので、これを併用してみます。

$('div.contents-wrapper > div').exEqualHeight({
	watchHeight : true
});
$('div.sub-contents,div.ext-contents').exFlexFixed({
	container : 'div.contents-wrapper',
	watchPosition : true
});

f:id:cyokodog:20120426201436p:image

Demo

exEqualHeight() メソッド実行時に、watchHeight パラメータを指定することで、動的なレイアウトサイズ変更にも対応させることができます。ただこの場合、内部的に setTimeout による監視が、exEqualHeight、exFlexFixed それぞれで行われることになるので、リソースや処理タイミングが気になる場合は、以下のような記述で調整処理をまとめることができます。

var height_API = $('div.contents-wrapper > div').exEqualHeight({
	api : true,
	watchHeight : false,
	windowResizeAdjust : false
});
$('div.sub-contents,div.ext-contents').exFlexFixed({
	container : 'div.contents-wrapper',
	watchPosition : true,
	watchCallback : function(fixed_API){
		height_API.adjust();
	}
});

Demo

exEqualHeight を非監視状態で実行、API オブジェクトを取得し、exFlexFixed の監視処理のコールバックにて、リサイズ判定+高さ調整を実行してます。

パラメータ

下記パラメータがあります。

api
初期値:false
true にすると api オブジェクトを返します。
watchPosition
初期値:'auto'
watchPosition パラメータ、windowResizeAdjust パラメータが共に auto の場合 false になります。true の場合、レイアウトの監視とサイズ・位置調整を行います。
watchDelay
初期値:500
指定値の間隔(ms)で監視処理を行います。
watchCallback
初期値:function(api){}
監視処理のコールバック関数を指定できます。apiapi オブジェクトが渡されます。
container
初期値:null
必須パラメータ。position:fixed 適用範囲となるコンテナ要素を指定します。
width
初期値:'auto'
position:fixed の幅を指定します。auto の場合は自動調整されます。
windowResizeAdjust
初期値:'auto'
watchPosition パラメータが true で且つ windowResizeAdjust パラメータが auto の場合 false になります。ウィンドウリサイズ時にサイズ・位置調整を行います。
windowResizeDelay
初期値:100
ウィンドウのリサイズイベントの発生判定間隔(ms)を指定します。

API

下記メソッドがあります。

adjustPosition()
レイアウトサイズ変更時に行われるサイズ・位置調整処理を行います。
adjustScrollPosition()
スクロール時に行われる位置調整処理を行います。

ダウンロード

こちらからどうぞ

dangodango 2012/05/31 10:28 Ex Flex Fixedを使わせていただいており、大変助かっております。

質問させていただきたいのですが、ヘッダーをfixedしている場合に、
サイドメニュー部分へEx Flex Fixedを適用し、スクロールさせると
ヘッダーの下にもぐりこみ、おそらくサイドメニュー部分がウインドウの
もっとも上に到達した時点でEx Flex Fixedのposition:fixedの効果が
適用され、ヘッダーより下にもぐりこみから戻されるように表示されます。

具体的にはtwitter bootstrapを使用して、classに"navbar navbar-fixed-top"と
指定することで、position:fixedされています。

自分なりにEx Flex Fixed内でposition:fixedの開始位置指定場所を探して
みたのですが、探しきれませんでした。

説明が分かりにくく申し訳ありませんが、ヘッダーの下部があたかも
ウインドウの上部になるような動作にするにはどのようにしたらよろしいでしょうか。

恐縮ですが、よろしくお願いいたします。

dangodango 2012/05/31 14:54 試行錯誤の結果、下記の修正でヘッダーの下へもぐりこむ動作は
回避することができました。

jquery.exflexfixed-0.2.0.jsの

144行目
if(top < 0){

if(top < ヘッダーの高さ){
へ変更

149行目
top = 0;

top = ヘッダーの高さ;
へ変更

以上です。
それ以外の部分がどの操作時に必要となるのかまで
調査できておりません。
他に修正するべき点などあればご指摘いただけないかと
思います。

よろしくお願いいたします。

cyokodogcyokodog 2012/06/01 01:28 dangoさん

コメントありがとうございます。
修正の件、問題ないと思います。
一応、v0.3.0ということでパラメータ指定でも対応できるようにしました。
GitHubにあげてありますので、もしよろしければ
example-1.5.0.html、example-1.5.1.html
をご覧ください
example-1.5.1.htmlはヘッダ部にもexFlexFixedを適用し、ヘッダがフッタにかぶらないようにした例になります。

dangodango 2012/06/01 23:35 cyokodogさん

迅速な回答およびパラメータ追加対応ありがとうございます。
おかげさまで、目的の動作を実現することができました。

また、フッタへの配慮、なるほどと思いました。

使わせていただき、なにか気づく点などあればご連絡するように
いたします。

dangodango 2012/06/03 12:38 細かい部分ではありますが、ひとつ提案です。

マウスのホイールなどでスクロールさせた場合、
一度のスクロールで、即exFlexFixedの効果が発揮されると
本来、ウインドウのトップでposition:fixedされるべきところ、
その場でposition:fixedされてしまい、ウインドウトップと
exFlexFixed対象との間にすき間ができてしまいます。

具体的には、一度のスクロールで、
c._orgMarginTop < c._win.scrollTop()
となる場合、その場でposition:fixedされてしまうので、
v0.3.0の163行目に挿入するかたちで、
if (!top) {
if (c._orgMarginTop < c._win.scrollTop()) {
top = 0;
}
}
などとすると、解決されました。

以上、次回バージョンアップ時などにご検討ください。
また、冗長な書き方ですので、よろしければアドバイスください。

cyokodogcyokodog 2012/06/05 00:56 dangoさん

ご提案ありがとうございます。
ただ、自宅PCが非力なせいなのか、chrome/firefox/operaで試したところ現象が起きませんでした
そこそこ性能の良い会社PCのIE9で試した場合も同様でした
という訳で検証ができないのでちょっと実装は無理そうです><

dangodango 2012/06/11 19:11 cyokodogさん

返信遅くなりまして恐縮です。

提案内容を確認いただいてありがとうございます。

こちらでも改めてシンプルなテストページを作成し
確認してみました。

私の環境でも以前申し上げた内容にはならず、
cyokodogさんのおっしゃるとおりでした。

詳細まで調査できておりませんが、HTMLやCSSの書き方に
よるものがあるのだと思います。

大変失礼いたしました。

あいーんあいーん 2012/08/16 03:18 iPhoneやiPadなどのMobileSafariにも対応してもらえませんか?

cyokodogcyokodog 2012/08/18 21:40 すいません。iPhoneもiPadも持ってないんでちょっと難しいです

nounou 2013/02/03 22:18 Ex Flex Fixed にお世話になっております。

同類のJqueryをいくつも試したところうまくいかず こちらのEx Flex Fixedでようやく期待する動きをしてくれたのですが、挙動のおかしい点が一点だけございます。

固定したい要素をサイド中ほどに掲載しているのですが、下記のように固定させたい要素のひとつ上の要素に食い込む形で重なってしまいます。

http://gyazo.com/ef6b6b7d00162f3490c7b93a80204637

リサイズを行うと正しい位置に表示されます。
http://gyazo.com/33e500502c92380ee164b95e1200e9ca

もし 原因にお心当たりございましたらお教え願えませんでしょうか。

お忙しいとは存じますがどうぞよろしくお願いいたします。

ishikoroishikoro 2014/02/10 01:30 素晴らしいプラグインありがとうございます。いつもお世話になっております。

jquery.exflexfixed-0.3.0.jsを使用させて頂いております。

リロードすると、位置がずれて文字に被る状態になります。

ブラウザはchrome とsafariです。firefoxでは問題ありませんでした。

どうぞ宜しくお願い申し上げます。

cyokodogcyokodog 2014/02/12 00:17 ishikoroさん

返信遅れてすいません。時間のあるときに確認してみます。

wazamebawazameba 2014/02/16 17:17 こんにちは。

バージョン0.3.0をアメブロで使わせて頂いたところ、うまく動作させることができました。

かゆいところに手が届く本当にステキなプラグインを提供いただきありがとうございます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証