読者です 読者をやめる 読者になる 読者になる

WEBサイト制作の勉強|フェリカテクニカルアカデミー

WEBサイト制作の勉強の為の解説ブログ。東京池袋のフェリカテクニカルアカデミーでは求職者支援訓練の一環として、WEBサイト制作を学ぶことができます。

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

jQueryプラグイン jQuery HTML5+CSS3

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

jQuery レスポンシブデザイン

ここまでで、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').find('h2').on('click touchstart',function(){
        if( $('body').width() <= 640){ //ブレイクポイント未満でアコーディオンが動くようにする条件分岐
      $(this).siblings('dl ').not(':animated').slideToggle('fast', function(){
        $(this).parent().toggleClass('close');
      });
     }
  });

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

Webサイト制作 レスポンシブデザイン

レスポンシブサイトのタブレット・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;
}

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

jQuery

レスポンシブサイトでは基本的に画像は可変に設定するべきですが、幅が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();
	});
});


Flexboxの使い方

HTML5+CSS3

Flexbox(Flexible Box Layout Module)はCSS3の新しいレイアウトモジュールで、複雑なレイアウトを今までより少ないコードでフレキシブルなボックスを組むことが出来ます。以前からあった技術ですが、各ブラウザーによって書き方が違ったり、仕様が変わったりと、イマイチ使いづらさがありましたが、最近のモダンブラウザーでは利用に難がなくなり充分使えるようになりました。IEのサポートポリシーの変更により、今後普及してくる技術の1つです。これを使う事でfloatを使って作っていたレイアウトが感覚的に作れるようになります。

視覚で見るのが非常に解りやすいです。
www.youtube.com

メリット
  • 少ない記述で簡単に横並びにできる!
  • 横並びになった要素の高さが最初から揃ってる!
  • 要素を上下左右、好きな順序に並び替えられる!
  • 高さの異なる横並びの要素を、簡単に上下中央揃え!

などなど、本来CSSでは出来ずにjQueryなどで行っていた事が非常に簡単に出来るようになります。

デメリット

無し!(強いて言えば一部のブラウザーにバグがあり)

ブラウザーのFlexboxのサポート状況
最新のサポート状況をhttp://caniuse.com/#search=flexboxなどで必ずチェックしましょう

f:id:yachin29:20161130115839j:plain
※2016年11月


Flexboxの基本

flexboxレイアウトを使うには親要素のdisplayプロパティに「flex」を指定するだけです。今回は「ul」要素を使います。

ul {
  display: flex;
}

f:id:yachin29:20160212221400j:plain

f:id:yachin29:20160212222603j:plain

flex-direction

flex-direction」プロパティを設定することにより、flexアイテムがflexコンテナでどのように配置されるか明示します。方向は2種類で、横列の水平、縦列の垂直に配置できます。
flex-direction: row; で左から右
       row-reverse; で右から左
       column; で上から下
       column-reverse; で下から上

ul {
  width:600px;
  margin: 20px;
  display: flex;
  flex-direction: row;
}
flex-wrap

flex-wrap」プロパティは、flexコンテナが複数のアイテムを一行、または複数行に配置することをコントロールします。

flex-wrap: nowrap;(初期値)は各アイテムの幅が親要素の幅に収まるように縮小される。
flex-wrap: wrap; 各アイテムの幅が親要素の幅に収まらない場合、下に回り込みます。

justify-content

「justify-content」プロパティは、flexアイテムを一行に配置します。(text-alignの指定と類似)

justify-content: flex-start;(初期値)flexコンテナの左側に配置されます。
justify-content: flex-end; flexコンテナの右側に配置されます。
justify-content: center; 中央に配置されます。
justify-content: space-between; 最初と最後のアイテムは端に、残りは等間隔で配置されます。
justify-content: space-around; 全てのアイテムが等間隔に配置されます。

子要素に指定

order

「order」プロパティは、display: flexを指定している親要素に配置される子の順番をコントロールします。
order: 1;
order: 2;
order: 3;

今までfloatやpositionを多用しなければ出来なかった様なレイアウトが少ないコードで簡単に組めるので、ぜひ色々なレイアウトを実際に組んでみましょう。
実際に「order」プロパティを使って3カラムレイアウトを組んでみましょう。

<body>
<nav>
  <ul class="main-nav">
    <li><a href="#" class="logo">Logo</a></li>
    <li><a href="#">Menu 1</a></li>
    <li><a href="#">Menu 2</a></li>
    <li><a href="#">Menu 3</a></li>
  </ul>
</nav>

<div class="main">
<section class="col-1">
<h1>Column 1</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent fermentum id mauris eget commodo. Sed ex leo, porttitor sit amet lectus et, pretium eleifend ipsum.</p>
</section>

<section class="col-2">
<h1>Column 2</h1>
<p>Morbi non semper sapien. Suspendisse elementum interdum metus, in volutpat lectus consectetur id. Praesent vulputate ipsum eget lectus tempus tempus. Nullam ut lobortis risus, eu tempor tellus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. </p>
<p>Integer vel pellentesque elit. Sed faucibus magna vitae metus ornare, ut pulvinar leo blandit. Mauris tincidunt ante nec quam maximus iaculis ut id lorem. Integer nec ligula faucibus, sollicitudin elit at, maximus tortor.</p>
</section>

<section class="col-3">
<h1>Column 3</h1>
<p>Integer commodo, risus vel viverra bibendum, massa massa consectetur felis.</p>
</section>
</div>
</body>


スタイルシート

@charset "utf-8";
/* CSS Document */

/* reset */
html, body, div, h1, h2, h3, h4, h5, h6,p, blockquote, pre, 
address,ul, ol, li, dl, dt, dd,table, th, td, form, fieldset {
  margin: 0;
  padding: 0;
  line-height: 1.0;
  font-family:
    "Hiragino Kaku Gothic ProN",
    Meiryo, 
    sans-serif;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}
ul, ol {
  list-style: none; /* マーカーを消す */
}
a {
  text-decoration: none; /* 下線を消す */
}
img {
  border: 0;
}
img, input {
  vertical-align: bottom;
}


/*Flexboxスタイル*/

.main-nav, .main {
  display: flex;
}
.main-nav li:first-child {
  margin-right: auto;
}
.main-nav a {
  margin: 10px;
  border-radius: 5px;
  background: #60B99A;
  color: #fff;
  display: block;
  padding: 15px;
}
.main-nav .logo {
  background: #4584b1;
}

/* Main contents */
.main section {
  flex: 1;
  margin: 10px;
  border-radius: 5px;
  background: #F5F0CF;
  padding: 15px;
}
.main .col-2 {
  flex: 2;
}
.main h1 {
  color: #E6AC27;
}
.main p {
  margin-top: 10px;
  font-size: 18px;
}


/* Mobile */
@media screen and (max-width: 767px) {
.main {
    flex-direction: column;
}
}
広告を非表示にする

ドロワーメニュー

HTML5+CSS3
/*  ハンバーガーメニュー
---------------------------------------------------------- */

#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'});
  });
});