WEBサイト制作の勉強

WEBサイト制作の勉強の為の解説ブログです。

SEOに適した無限スクロールの制作

SEOに適した無限スクロールの導入

FacebookTwitterPinterestなどのソーシャルメディアサイトが使っている事で一躍有名になった無限スクロール(英: Infinite Scrolling)ですが、今でもシングルページを利用したウェブサイト、特にコンテンツの量が豊富なギャラリー的なサイトではよく見かけます。
しかし、よく見られるjQueryを使ったシンプルな無限スクロールはコンテンツをすべて1つのHTMLファイル上に記述しておいて、スクロールするたびに「display:block」と「display:none」を使って表示させていく、というものです。人が見る分にはこの形でも良いでしょうが、Googlebot に対してとなると話が変わってきます。

ご自身のサイトのニュース フィードやピンボードで、ユーザーの利便性を考えて無限スクロール(英語)を使用している方もいらっしゃるでしょう。しかし、Googlebot に対してとなると話が変わってきます。無限スクロールでは、クローラーがユーザーの行動(スクロールやボタンを押してさらにアイテムを読み込むなど)を常にエミュレートできるとは限らないため、フィードやギャラリー内のすべてのアイテムにアクセスできないことがあります。クローラーがアクセスできないコンテンツは、検索結果に表示されることもないでしょう。

無限スクロール ページからリンクされている個別のアイテムを検索エンジンがクロールできるようにするには、無限スクロールを分割した一連のページ群を生成するようにしましょう。

f:id:yachin29:20160216192134p:plain

Google ウェブマスター向け公式ブログ: 検索エンジンとの相性を考慮した無限スクロールのベストプラクティス


pushStateによるブラウザの履歴の更新

pushStateとは?

pushStateとは、HTML5でサポートされるAPIです。
ページを遷移せずHTML(の一部)を変えた場合でもブラウザに履歴を残し、また一意のURLを割り当てることが可能です。

HTMLの中身が変わってもAjaxはページを遷移しないのでURLが同じままです(#以下が入れ替わるだけで一意のURLとして処理しない)。

ブラウザの戻るボタンを押しても前のコンテンツを再び表示させることはできません。
本当に前のページに戻ってしまいます。

なのでGoogleは、クロール・インデックスできるように特殊な仕様をサポートしてくれたわけです。

しかしpushStateを使えば、Ajaxで変化させたそれぞれのコンテンツに対してユニークなURLを割り当てられるのです。

つまり検索エンジンにとってクロール・インデックスしやすくなります。

Googleの記事では、無限スクロールは次々にページを捲っていく事と同じとしている。そのため、無限スクロールで新しいコンテンツが表示される度にブラウザの履歴(URL)を更新しなければいけない。さらにスクロールでページを進んだり戻ったりする度にURLを更新させる必要があります。


さらにJavaScriptが切れている状態でも手動でページ遷移出来るような設定も取り入れ、検索エンジンとの相性を考慮した無限スクロールにカスタマイズしましょう。


www.suzukikenichi.com

digiday.jp


前回の内容を踏まえて、今回は検索エンジンが処理しやすい無限スクロールを作っていきましょう。

ポイント
・無限スクロールページを、JavaScript が無効でもアクセス可能な形にする。
・ページのタイトル・サイトURLの最適化
・コンテンツを細分化する事で表示スピードの向上

特にページのタイトルの最適化は非常に大事です。通常の無限スクロールは1枚のhtmlファイルに無数のコンテンツが記述されていますが、今回のようにhtmlファイルを細分化する事で、コンテンツに応じたより細かいタイトルやURLの設定が可能になります。


github.com

デモページ

http://yachin29.html.xdomain.jp/infini-scroll/

<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>jScroll</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="container">
<h1>無限スクロール</h1>
<div class="wrapper">
<div class="pic">
<p><img src="img/01b.jpg"></p>
</div>
<div class="text">
<h3>新・平家物語</h3>
<p>『新・平家物語』は、吉川英治の歴史小説の大作。1950年から1957年まで「週刊朝日」に連載された。現行版は吉川英治歴史時代文庫全16巻。<br>
題材は『平家物語』だけでなく、『保元物語』『平治物語』『義経記』『玉葉』など複数の古典をベースにしながら、より一貫した長いスパンで源平両氏や奥州藤原氏、公家などの盛衰を描いた長編作品。</p>
</div>
</div><!--/.wrapper-->
<a href="http://yachin29.webcrow.jp/infini-scroll/book2/" id="next">next</a>
</div><!--/#container-->

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="js/jquery.clever-infinite-scroll.js"></script>
<script>
		$('#container').cleverInfiniteScroll({
			contentsWrapperSelector: '#container',
			contentSelector: '.wrapper',
			nextSelector: '#next',
		});
	</script>
</body>
</html>

モバイルファーストを意識したレスポンシブデザインサイトの制作 4

ここまでで、PC時のレイアウトも含めほぼ完成ですが、今のままだとPC時にもjQueryアコーディオンパネルが動いてしまうので、if文でウィンドウサイズがスマホサイズの時のみに動くように条件分岐をしてみましょう。
また、スマホの機種によっては、「touchstart」の動きが安定しない為、タップした際にアコーディオンパネルが開いて閉じる、という挙動になってしまうので、アコーディオンパネルのようにslideToggleを使う場合はアニメーションが実行中はアニメーションの処理を受け付けないようにしましょう。

元のアコーディオンパネルの記述

 // アコーディオン
$('.toggle').find('h2').on('click touchstart',function(){
 $(this).siblings('dl').slideToggle(300, function(){
   $(this).parent().toggleClass('close');
   });
  });

新しい記述
スマホサイズの時のみに動くようにif文と.not(':animated')を追加

// アコーディオン

$('.toggle h2').on('click',function(){ 
     if( $('body').width() <= 640){ 

	$(this).siblings('dl').not(':animated').slideToggle(300);
	 $(this).find('span').toggleClass('close');
 return false;
		 };
});

モバイルファーストを意識したレスポンシブデザインサイトの制作 3

レスポンシブサイトのタブレット・PCレイアウトを完成させます。


作例

http://yachin29.webcrow.jp/sp-pc/





タブレット・PCレイアウトを完成させる為に行うこと

HTMLにタブレット・PC専用のコンテンツを挿入する。
ブレイクポイントを指定し、タブレット・PC用のスタイルを新規作成したCSSファイルに記述する。
アコーディオンパネルをタブレット・PCでは動かないようにする。

HTMLファイルにタブレット・PC用のコンテンツを追加する為に「div class="indexBoxes"」部分の記述を一部変更します。

変更前の「div class="indexBoxes"」部分の記述

<div class="indexBoxes">
<ul>
  <li><a href="#"><div>サービス紹介</div></a></li>
  <li><a href="#"><div>実績紹介</div></a></li>
  <li><a href="#"><div>会社概要</div></a></li>
  <li><a href="#"><div>採用情報</div></a></li>
</ul>
</div><!--/indexBoxes-->

変更後

<div class="columnWrapper"><!--レスポンシブ用のwrapper-->
<div class="indexBoxes">
<ul>
  <li><a href="#"><h2>サービス紹介</h2>
        <div class="captionBox"><img src="img/img_index_service.jpg" alt="サービス紹介">
        <p>全てのインターネットユーザーにスマートさを。</p></div></a>
  </li>
  
  <li><a href="#"><h2>実績紹介</h2>
       <div class="captionBox"><img src="img/img_index_proven.jpg" alt="実績紹介">
        <p>これまでに手がけたサービス、制作事例をご紹介します。</p></div></a>
  </li>
  
  <li><a href="#"><h2>会社概要</h2>
    <div class="captionBox"><img src="img/img_index_corporate.jpg" alt="会社概要">
    <p>企業沿革、コーポレートメッセージなどご紹介します。</p></div></a>
  </li>
    
  <li><a href="#"><h2>採用情報</h2>
    <div class="captionBox"><img src="img/img_index_recruit.jpg" alt="採用情報">
    <p>私たちの理念に共感でき、ともに未来を創っていける仲間を募集しております。</p></div></a>
  </li>
</ul>
</div><!--/indexBoxes-->

<section class="seminar toggle">
<h2><span>セミナー</span></h2>
<dl class="informationLink">
<dt>2015年11月11日</dt><dd><a href="#">テキストテキストテキストテキストテキスト</a></dd>
<dt>2015年10月19日</dt><dd><a href="#">テキストテキストテキストテキストテキスト</a></dd>
<dt>2015年10月14日</dt><dd><a href="#">テキストテキストテキストテキストテキスト</a></dd>
<dt>2015年10月10日</dt><dd><a href="#">テキストテキストテキストテキストテキスト</a></dd>
<dt>2015年9月29日</dt><dd><a href="#">テキストテキストテキストテキストテキスト</a></dd>
</dl>
</section><!--/seminar-->
</div><!--/columnWrapper-->


スマホサイト用のスタイルシートに追加

/*レスポンシブデザイン用の追加記述*/
div.indexBoxes .captionBox{
  display: none;
}
div.indexBoxes h2 {
  font-size: 16px;
  font-weight: bold;
}

ウィンドウサイズによって画像を切り替える

レスポンシブサイトでは基本的に画像は可変に設定するべきですが、幅が960pxの時と幅が320pxの時とで同じ画像で良いか、というと必ずしもそうではありません。例えば画像に文章が乗っている場合であれば、なおさらです。
backgroundプロパティであればメディアクエリで切り替えられますが、imgタグで指定したい場合には使えません。

そこで今回は、jQueryで画像ファイル名の一部を置換して表示する画像を切り替える方法です。


スマホサイトの時の画像名
「img_keyvisual_01_sp.jpg」

PCサイトの時の画像名
「img_keyvisual_01_pc.jpg」

この末尾のspとpcを変える事でウィンドウサイズに適した画像に差し替える事が出来ます。


「replaceWidth」で設定する値をもとに
ウィンドウサイズがそれ以上だったら画像ファイル名「_pc」が付いているものを表示し、
それ以下だったら画像ファイル名「_sp」が付いているものを表示します。

window.innerWidth

「window.innerWidth」とはブラウザウィンドウの ビューポート (viewport) の幅を取得出来る。


thisと$thisの違い
  • 「$(this)」はjQueryオブジェクト。
  • 「this」はDOMエレメント。

違いを簡単に説明すると、イベントが発生した要素に対して、javaScriptのメソッドやプロパティを利用したい時は「this」利用し、jQueryで操作したい時は$(this)を利用してjQueryオブジェクトに変換してから利用する。
「this」の持つ情報はjavaScriptで操作できる「DOM要素」です。イベントで設定したfunction内で利用した場合はイベントが発生したDOM要素を指します。



www.jquerystudy.info



ウィンドウサイズによる画像置換を行いたい画像に「.switch」を追加
<img src="img/img_keyvisual_01_sp.jpg" alt="#" class="switch">

jQueryの記述

$(function(){
//ウィンドウサイズによる画像置換

  var sizeChange = $('.switch'), // 置換の対象とするclass属性。
  pcName = '_pc', // 置換の対象とするsrc属性の末尾の文字列
  spName = '_sp',// 置換の対象とするsrc属性の末尾の文字列
  replaceWidth = 641; // 画像を切り替えるウィンドウサイズ。

  sizeChange.each(function(){
  var $this = $(this);
  function imgSize(){
  if(window.innerWidth > replaceWidth) { // ウィンドウサイズが641px以上であれば_spを_pcに置換する。
   $this.attr('src',$this.attr('src').replace(spName,pcName));
   } else {
      $this.attr('src',$this.attr('src').replace(pcName,spName));
			}
		}
		$(window).resize(function(){imgSize();});
	imgSize();
	});
});


ドロワーメニュー

/*  ハンバーガーメニュー
---------------------------------------------------------- */

#globalHeader nav {
  float: right;
}
#globalHeader nav p#menuToggle {
  background: -webkit-linear-gradient(top, #eeedf2 1%, #717171 4%, #2b2b2b 84%);/*古いAndroid用*/
  background: linear-gradient(to bottom, #eeedf2 1%, #717171 4%, #2b2b2b 84%);/*W3C標準*/
  border: 1px solid #444;
  border-radius: 5px;
  color: #fff;
  line-height: 36px;
  padding-left: 6px;
}
#hum-btn {
  display:block;
  float: right;
  background: url(../img/bg_line.png) repeat-y 0 60%/2px auto;
  position: relative;
  width: 36px;
  height: 36px;
  border-radius: 5px;
  padding-left: 20px;
  margin-left: 10px;
}
#hum-btn-icon {
  display: block;
  position: absolute;
  top:0;
  left:0;
  bottom:0;
  right:0;
  margin:auto;
  width: 22px;
  height: 2px;
  transition: .2s;
  background: #FFF;
}
#hum-btn-icon:before, #hum-btn-icon:after {
  display: block;
  content: "";
  position: absolute;
  top:0;
  left:0;
  bottom:0;
  right:0;
  margin:auto;
  width: 22px;
  height: 2px;
  background: #FFF;
  transition: .3s;
}
#hum-btn-icon:before {
  top: -14px;
}
#hum-btn-icon:after {
  top: 14px;
}
#hum-btn .close {
  background: transparent;
}
#hum-btn .close:before, #hum-btn .close:after {
  top: 0;
}
#hum-btn .close:before {
  transform: rotate(-45deg);
}
#hum-btn .close:after {
  transform: rotate(-135deg);
}
#globalHeader nav ul {
  display:none;
}

/*クリックしたら出てくるメニュー部分*/
ul#drawer {
  background: #333;
  border-bottom: 1px solid #000;
  position: absolute;
  left: 0;
  top: 50px;
  width: 100%;
  z-index: 99999;
}

ul#drawer li {
  border-top: 1px solid #000;
}
ul#drawer li a {
  border-top: 1px solid #666;
  color: #fff;
  display: block;
  padding: 10px;
}
ul#drawer li:first-child,
ul#drawer li:first-child a {
  border-top: none;
}
広告を非表示にする

メガドロップダウンメニューの導入

最後にPC用のナビにメガドロップダウンメニューを入れます

f:id:yachin29:20160908004023p:plain



最近よく見かけるメガドロップダウンメニュー。特にコーポレートサイトなど情報量が多いサイトでは、リンク先のページに飛んでからさらにそのページの中から目当てのコンテンツを探さなければならない、といった手間がかかります。
メガドロップダウンメニューであれば、リンク先のページの中の目当てのコンテンツにダイレクトに飛べるので、ユーザーの手間が省けるわけです。ユーザビリティの向上のためにも情報量の多いサイトであれば積極的に使っていきましょう。


メガドロップダウンメニューを採用しているサイト例
www.tiffany.co.jp


www.nike.com


www.kureha.co.jp



<nav class="pc-nav">
<ul>
<li class="nav1"><a href="#">商品情報</a>
<div class="Wrap">
<div class="wrapInner">
</div><!-- /.wrapInner -->
</div><!-- /.Wrap -->
</li>


メガドロップダウンメニューのCSS

/*メガドロップメニュー*/
.pc-nav ul li .Wrap {
  position: absolute;
  top: 116px;
  left: 0;
  z-index: 100;
  overflow: hidden;
  display: none;
  width: 100%;
  height: 100vh;
  background: rgba(0,0,0,0.6);
}
.Wrap .wrapInner {
  margin: 30px auto 0;
  width: 960px;
  height: 360px;
  background: #FFF;
  border-radius:8px;
}
.pc-nav ul li:hover:after{
  display:block;
  content: "";
  border: 10px solid transparent;
  border-bottom: 18px solid #fff;
  position: absolute;
  top: 120px;
  margin-left: 5%;
  z-index: 1000;
}


メガドロップダウンメニューのjQuery

$(function(){
  $('.pc-nav > ul > li').hover(function(){
    Panel = $(this).children('.Wrap');
    Panel.each(function(){
    Panel.css({display:'block',opacity:'0'}).stop().animate({opacity:'1'},200);
    });
  },function(){
    Panel.css({display:'none'});
  });
});

既存サイトのトレース ニュースリリース部分

PCレイアウト
f:id:yachin29:20170224015445p:plain


タブレット(959px〜641px)
f:id:yachin29:20170613105423p:plain



スマホ時(640px以下)
f:id:yachin29:20170613105452p:plain


このようなニュースリリース部分はレスポンシブを考えるとul要素を使ってコーディングする方が簡単に出来るので、多くの場合はul・liで組まれていますが、文章構造的にはdl要素を使う方が良いでしょう。
なので、今回はdl要素を使って実際にコーディングして行きます。

ポイント
  • ddがdtの下に回り込まないようにする
  • dtとddで行数が違う場合にレイアウトが崩れないようにする
  • dtとddの高さを1行目で合わせる


スマホ時のポイント
スマホ時になると最新記事3つ以外は隠れていて、「もっと見る」ボタンをクリックすると表示されるようにしてみましょう。
この際に最新記事3つ以外にクラス名をつけるやり方もありますが、それでは運用効率が非常に悪いので、擬似クラス(nth)を使えるようになりましょう。
さらに、これはjQueryだけで無く、プログラム全般に言えることですが、動きをつける際にはまず「何をしたら」、「何が」、「どうなる」という事をしっかりと明確にしましょう。
また、jQueryで要素を取得する際には「ツリー構造」と「ノード」の考え方をしっかりと理解する必要があります。

Traversingメソッドを利用

Traversingのメリット

トラバースを利用することで、イベントが発生した要素に関連した要素を操作する事ができます。ボタンが複数ある場合などは「this」を使う事になりますが、このトラバースを使えば操作したい要素を「this」から見てどういう関係性にある「要素」、という形で指定する事ができます。jQueryを使う上で非常に大事な考え方なので、しっかりと理解しましょう。



childrenメソッド
jQueryオブジェクトで指定した要素の「子」要素でセレクタにマッチする要素を選択します。子要素とは階層構造(入れ子構造)において直下にある要素のことです。
childrenメソッドを利用すれば「セレクタ:>(子要素)」と同じようなことが可能です。


parentメソッド
指定した要素の「親」要素を選択します。親要素とは階層構造(入れ子構造)において直上にある要素のことです。
名前が似ているparentsメソッドはparentメソッドと異なり「先祖」要素も選択します。

siblingsメソッド
指定した要素の兄弟要素(同じ階層の要素)を選択します。引数を設定しない場合はすべての兄弟要素を選択します。


f:id:yachin29:20170224130454p:plain

www.jquerystudy.info





文章構造

<div class="inner">
<div id="news">
<h2>ニュースリリース</h2>
<dl>
<dt>2017年6月12日</dt>
<dd><a href="#">「復興応援 キリン絆プロジェクト」熊本支援 阿蘇GIAHS(ジアス)ツーリズム推進協議会に支援金を助成</a></dd>
<dt>2017年6月9日</dt>
<dd><a href="#">国産最軽量のアルミ缶が「第41回木下賞」を受賞!</a></dd>
<dt>2017年6月9日</dt>
<dd><a href="#">「キリンウイスキー 富士山麓 ブレンデッド18年」が「アジアスター賞」、「ワールドスター賞」を、「キリン 生茶」525mlペットボトルが「アジアスター賞」を受賞!</a></dd>
<dt>2017年6月8日</dt>
<dd><a href="#">「ギュギュッと搾ったサングリア」新スタイル300ml小容量ボトル缶が販売好調</a></dd>
<dt>2017年6月8日</dt>
<dd><a href="#">「シャトー・メルシャン “調和を味わう”3本セット」をDRINXで数量限定発売</a></dd>
<dt>2017年6月7日</dt>
<dd><a href="#">「第4回 寿司×クラフトビールフェス」開催</a></dd>
<dt>2017年6月6日</dt>
<dd><a href="#">「キリンチューハイ ビターズ 皮ごと搾りはっさく<期間限定>」を新発売
</a></dd>
</dl>
</div>

<div id="new_info">
<h2>新着情報</h2>
<dl>
<dt>2017年6月13日</dt>
<dd><a href="#">「キリン 氷結®ストロング 塩グリーンレモン<期間限定>」を新発売!(6月13日発売)</a></dd>
<dt>2017年6月6日</dt>
<dd><a href="#">「47都道府県の一番搾り(栃木県・群馬県・埼玉県・千葉県・東京都・京都府・大阪府・奈良県・和歌山県・熊本県・宮崎県・鹿児島県・沖縄県)」を新発売!(6月6日発売)</a></dd>
<dt>2017年6月6日</dt>
<dd><a href="#">「47都道府県の一番搾り」新CMを公開!</a></dd>
<dt>2017年6月6日</dt>
<dd><a href="#">キリン食生活文化研究所 キリン食生活文化研究所のアンケート「ちょっと教えて」実施中!</a></dd>
<dt>2017年6月6日</dt>
<dd><a href="#">「キリン 午後の紅茶 ティー ウィズ ミルク」を新発売!(6月6日発売)</a></dd>
<dt>2017年6月6日</dt>
<dd><a href="#">「キリン 午後の紅茶」新CM『おいしい無糖「オール・マイ・ティー英語講座 ティー ウィズ ミルクぶら下がり」篇』を公開!</a></dd>
<dt>2017年6月6日</dt>
<dd><a href="#">「キリン 午後の紅茶」新CM『おいしい無糖「食事もオール・マイ・ティー ティー ウィズ ミルクぶら下がり」篇』を公開!</a></dd>
</dl>
</div>
</div>


スタイルシート

.inner {
  width:960px;
  margin:0 auto;
  padding: 0 20px;
  box-sizing: border-box;
}

#news {
  width:47%;
  float:left;
}
#new_info {
  width:47%;
  float:right;
}
#news h2, #new_info h2 {
  font-size:20px;
  padding: 20px 0 20px 10px;
  border-bottom: 1px solid #D8D8D8;
  box-sizing: border-box;
}

dl {
  overflow:hidden;
  margin:20px auto 0;
  line-height:2;
  font-size:12px;
}
dt {
  width:30%;
  float:left;
}
dt,dd {
  margin-bottom:14px;
}
dd {
  padding-left:30%;
  padding-bottom:10px;
  border-bottom:1px solid #CCC;
  background:url(dd_bg.gif) no-repeat 26% 6px;
}
dd a {
  color:#03C;
}
dd a:hover {
  text-decoration:underline;
}
@media screen and (max-width:959px) {
.inner {
  width:100%;
  margin:0 auto;
}

#news {
  width:100%;
  float: none;
  margin-bottom:40px;
}
#new_info {
  width:100%;
  float: none;
}

}

@media screen and (max-width:640px) {
.inner {
  padding: 0;
  margin:0 auto;
}
#news h2, #new_info h2 {
  font-size:16px;
  background: #D8D8D8;
  padding: 10px;
}
dt {
  width:100%;
  float:none;
  padding-left: 10px;
}
dt,dd {
  margin-bottom:10px;
  box-sizing: border-box;
}
dd {
  padding-left:20px;
  padding-bottom:10px;
  border-bottom:1px solid #CCC;
  background:url(dd_bg.gif) no-repeat 10px 6px;
}
}