ヘッダを固定【fixed】したサイトのページ内リンクのズレを考える

Advertisement

ヘッダーやメニューバーを上部に固定させるサイトデザインは世の中に溢れています。
ページスクロールの解説記事もたくさん溢れています。
ただ、position:fixedなどでヘッダを固定した際のズレの事、考えた事ありますか?

ページ内スクロールのズレとか何を言うてるの?

何様やねんという冒頭の内容で、すいません。
ズレ」というよりはposition:fixedなどでヘッダを固定した際に、ページ内スクロールしたら表示したい開始位置が固定した要素で隠れるという内容です。
この「ズレ」に関しても対策方法の解説記事はたくさんあります。

お困りのほとんどの方が、そのページ内スクロールの解説で解決できると思います。
ただ、僕が作業していて、解説記事では100%解決しなかったので、自分でごにょごにょした内容をこの記事で書きます。

この記事はこんな方にオススメ

  • サイト上部に固定要素のあるサイトにページ内スクロール設置している
  • CSSでbackgroundを指定している
  • コピペしたらJavascriptの動きに無駄があった

よくあるページ内スクロールズレ対処法

CSSでの解決方法

CSS
section#link1{
	/*固定した要素の高さ*/
	margin-top: -100px;
	padding-top: 100px;
}

CSSで解決できてシンプルで、手っ取り早いと思います。
ですが、背景画像や色を設定してい要素に、この方法で対応してしまうと、背景までpaddingと共に突き抜けてしまうんですね。。。

私の師匠の教えで、「ネガティブ要素はフォースの乱れを起こす」とのお言葉。
そんな時代は終わったかもしれませんが、昔からネガティブマージンなどのマイナスで要素を動かすのは私は信じていません。

ただ、要素の背景になにも指定していない場合は手っ取り早くていいと思います。

Javascript(jQuery)で解決方法

jQuery
$(function(){
	var headerHeight = 100;
	$('a[href^="#"]').click(function(){
		var href= $(this).attr("href");
		var target = $(href == "#" || href == "" ? 'html' : href);
		var position = target.offset().top - headerHeight;
		$("html, body").animate({scrollTop:position}, 500);
		return false;
	});
});

ページ内スクロールにヘッダーの高さを引いて移動させる方法です。
これなら上記のCSSの問題もクリアできます。
ですが、このままだとわずらわしい動きになります。

まず、本来のidタグ箇所へ飛んでいき(ズレた表示)、そこから高さ分動いて2回動いてるのでスマートではないです。
言い方が悪いですが、これを解消せずにローディングで誤魔化す方法を紹介している記事もありました。

また、下記のヘッダーの高さを指定するにあたり、スマホ表示時にヘッダーの高さが変わる場合、さらに指定してあげないといけません。

var headerHeight = 100;

そこで、ごにょごにょしたのが、下記のソースです。

改良したページ内スクロールソース

jQuery
$(function(){
	var headerHeight = $('header').outerHeight(); //固定している要素の高さ取得
	$('a[href^="#"]').click(function(){
		var href= $(this).attr("href");
		var target = $(href == "#" || href == "" ? 'html' : href);
		var position = target.offset().top - headerHeight;
		$("html, body").stop().animate({scrollTop:position}, 500);
		return false;
	});
});

変更点は2か所。

var headerHeight = $('header').outerHeight();

まず、固定している要素の高さを取得
これで、スマホ表示時、高さが可変する場合でも高さに合わせてスクロールします。

この時、移動させる位置に余白を持たせたいときは、「+10」とかにしてあげる。

var headerHeight = $('header').outerHeight() + 10;

みたいな感じでpx単位で調整できます。

動きに関しては、.animateの前に.stop()を追加してください。

$("html, body").stop().animate({scrollTop:position}, 500);

これで、1つ目のアニメーションが終わってなくても次のアニメーションに移行し、2段階な動きからスムーズに動きます。

まとめ

個人の考えではありますが、これが僕がごにょごにょした方法です。
結果、Javascriptでの解決しましたが、状況・環境によっては使えない事や、使わない方がいいこともあるかもしれません。
正解があるようでない世界、ケースバイケースでCSSやJavascriptをうまく使い分けて使って対応するしかないですね。

最後にもう一度、僕が言いたいのは師匠の教えの「ネガティブマージンはフォースの乱れを起こす」。
これだけはわかってほしいって事です。

タイトルを「ネガティブマージンはフォースの乱れを起こす」にすればよかった。
ちなみに、師匠は「ネガティブマージンの扱いの重要さ」は教えてくれましたが、「フォース」云々は言ってません。

Advertisement
CSSJavaScriptWEB Tips
東田ダダーンをフォローする
このブログを購読する
当ブログから更新通知を受けてもいいという方はリンクより更新通知の許可をしてください。 東田ダダーンが更新された際、更新した旨、通知されます。
東田ダダーン

コメント