Webサイトのデザインを変えずにPureでレスポンシブWeb化した話



2015年4月にGoogleが「サイトはモバイルでも読みやすくね♪」という勧告を出してから、自社サイトをどう対応しようか迷っていたのだけど、先ごろから入れ込んでいる CSSフレームワーク Pure なら変更が楽そうなので、この度 Pure で既存サイトのデザインのままレスポンシブWebにしてみました。その時行った作業を紹介します。

モバイル用のデザインをプランする

既存サイトのデザインのまま、と言っても、もちろんモバイル端末用には多少デザインを考えなくてはいけません。

非レスポンシブWebデザインの旧サイト

レスポンシブWeb化前のサイト

レスポンシブWeb化前のサイト

 

レスポンシブWeb化したサイト

レスポンシブWeb化したサイト(PCでの表示)

レスポンシブWeb化したサイト(PCでの表示)

レスポンシブWeb化したサイト(モバイル端末での表示)

レスポンシブWeb化したサイト(モバイル端末での表示)

 

モバイル用に追加したのは以下の3つの要素。

  1. 小さい端末のみで表示する最小化されたメニュー(クリックするとメニューが縦に開く)
  2. 小さい端末のみで表示するページトップに戻るリンク
  3. 小さい端末のみで表示する背景画像
モバイル端末用に追加した要素

モバイル端末用に追加した要素

 

レスポンシブWeb化の作業過程

以下で、変更の作業過程を紹介します。

CSSの切り替え

まずは読み込むCSSファイルを変更。

CSS切り替え前

<link href="../css/style.css" rel="stylesheet" type="text/css" />
<link href="../css/layout.css" rel="stylesheet" type="text/css" />

CSS切り替え後

<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="http://yui.yahooapis.com/combo?pure/0.6.0/base-min.css&pure/0.6.0/grids-min.css">
<link rel="stylesheet" type="text/css" href="../css/style.css" />
<!--[if lte IE 8]>
        <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?pure/0.6.0/grids-responsive-old-ie-min.css" />
        <![endif]-->
<!--[if gt IE 8]><!-->
    <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?pure/0.6.0/grids-responsive-min.css" />
    <!--<![endif]-->

Pure は全ての機能を利用するための一括読み込みも、一部機能だけの読み込みもできるのだけど、今回はレスポンシブWebレイアウトだけを使うので base と grids、そして、IEの古いバージョン対応のためのレスポンシブWeb用CSSを読み込み。

Pure の使い方は、以下のページに説明があります。

../css/style.css がサイト内独自のCSSルールを保存したファイル。

大きな端末での最大幅を決める

もともとのWebサイトも、幸いなことにテーブルレイアウトなどではなく、<div> + CSS でのレイアウトだったので、この <div> 構成をそのまま利用。2008年頃に購入したデザインテンプレートで、構造はおおざっぱに言って、以下のようになっている。

メニュー部分 body > #main > #header
左カラム(サイドメニュー) body > #main > #wrapper > .col_1
メインコンテンツ body > #main > #wrapper > .col_2
フッタ body > #main > #footer

一番外枠の <div id=”main”> に max-width を設定して全体の枠として利用。

固定幅だった、変更前(幅のレイアウトに関わる部分のみ)

#main {
	width: 766px;
	margin: 0px auto;
}

変更後(幅のレイアウトに関わる部分のみ)

max-widthを設定することで、PCなどこの幅を超える端末では固定幅レイアウトになり、それ以下の端末では端末の幅に対して100%になる。

#main {
	width: 100%;
	max-width: 766px;
	margin: 0px auto;
}

カラムが切ってある部分に .pure-g と .pure-u を設定

Pureでは、レスポンシブに表示幅を変更する <div>には .pure-u-* というクラスをつけ、その外側を <div class="pure-g"> で囲う。

このあたりの説明は以下のページ。

幸いなことに、元の <div> 構成はそのまま使えるので、ここにクラスを追加していく。例えば以下の通り。

.pure-g も .pure-u-* も、常に横幅一杯に表示すればよい要素には付けなくて良い。このため、#main などの枠になる部分には .pure-g は不要で、その下の幅を変更する必要のある要素のすぐ上位階層からタグ付を始める。

<div id="main">
	<!-- header -->
	<div id="header">
		<div class="head">
			<ul id="mainmenu" class="mainmenu pure-g">
				:(メインメニュー)
			</ul>
		</div>
	</div>
	<!-- content -->
	<div id="wrapper" class="pure-g">
		<div class="col_1 pure-u pure-u-1 pure-u-md-1-4">
				:(左カラム)
		</div>
		<div class="col_2 pure-u pure-u-1 pure-u-md-3-4">
				:(メイン領域)
		</div>
	</div>
	<!-- footer -->
	<div id="footer">
		<div class="foot pure-g">
			<div class="left pure-u pure-u-1 pure-u-md-3-5">(コピーライト)</div>
			<div class="right pure-u pure-u-1 pure-u-md-2-5">
				:(お問合せとプライバシーのリンク)
			</div>
		</div>
		<div class="foot pure-g">
			<div class="right pure-u pure-u-1 pure-u-md-2-5 sugu-pull-right">
				:(SNSリンクボタン)
			</div>
		</div>
	</div>
</div><!-- /#main -->

メニュー部分の調整

元のメニューは固定ピクセルで幅を指定してあったので、これは Pure のグリッドデザインの指定方法に従い割合で表示し(pure-u-md-1-5)、さらに、小さい端末になった時は幅広に縦に積んで表示する設定をする(pure-u-1)。

HTML側のタグ付

<ul id="mainmenu" class="mainmenu pure-g">
	<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu1"><a href="../index.html">ホーム</a></li>
	<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu2"><a href="index.html" class="on">会社概要</a></li>
	<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu5"><a href="../works/index.html">製品</a></li>
	<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu3"><a href="../services/index.html">サービス</a></li>
	<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu4"><a href="../perl/index.html">いまさら Perl?</a></li>
</ul>

変更前CSS(抜粋)

.mainmenu li {
	list-style-type: none;
	display: block;
	float: left;
	width: 151px; //幅の指定は削除
	height: 3.6em;
	margin: 0px 2px 0px 0px; //メニュー間にごくわずかな隙間がある
}

変更後CSS(抜粋)

.mainmenu li {
	list-style-type: none;
	display: block;
	float: left;
	margin: 0; //マージンを付けると Pure の諸事情でタグ付が面倒になるので、ボックスの間の空間は削除
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
	height: 45px; //高さの指定はどう変更してもよいがたまたま 45px
	overflow: hidden;
}

「box-sizing: border-box」の指定について

Pure のレイアウトコントロールは width で行っているため、.pure-u-* を追加した要素に margin や border 指定があると幅があふれてしまう。このため、「box-sizing: border-box」の指定をして、margin と border を含めて幅が計算されるようにする。本当は 「.pure-g > li, .pure-g > div」などのCSSセレクタでまとめて定義すればエレガントだけれど、今回は変に一括で指定して他に影響が出るのが怖いので、個別に設定。

また、同じ理由で元のレイアウトではメニューの間にあったわずかな隙間も除いた。このような隙間を残したいときは、.pure-u-* の要素(今回の場合は <li> )の下にスペースを開けるための <div> を設定してそこに margin を設定するなどの方法を採る必要がある。

小さい端末でのメニューのON/OFF

小さい端末でページの先頭にメニューが常に表示されているのは邪魔なので、最小化されたボタンをクリックした時だけメニューが開くようにする。

メニュー部分のHTMLコード

太字が追加した部分。(なお、<div id=”header-image”> や <div> は小さな端末では見えないように隠す。)

<!-- header -->
<div id="header">
	<div id="header-image">
		<img src="/images/header_bg.jpg" alt="CGIとPerl開発 すぐ使える株式会社" />
	</div>
	<div class="head">
		<a id="menuLink" class="menu-link" href="#menu">
			<span></span>
		</a>
		<ul id="mainmenu" class="mainmenu pure-g">
			<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu1"><a href="../index.html">ホーム</a></li>
			<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu2"><a href="index.html" class="on">会社概要</a></li>
			<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu5"><a href="../works/index.html">製品</a></li>
			<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu3"><a href="../services/index.html">サービス</a></li>
			<li class="pure-u pure-u-1 pure-u-md-1-5" id="menu4"><a href="../perl/index.html">いまさら Perl?</a></li>
			<li class="pure-u pure-u-1 pure-u-md-1-5 hidden-md" id="menu-close"><a href="#">[閉じる]</a></li>
		</ul>
		<div class="logo">
			<h2><a href="../index.html"><img src="../images/logo.gif" alt="CGIとPerl開発 - すぐ使える株式会社" width="321" height="59" border="0" /></a><br /><img src="../images/slogan.gif" alt="WEB-DB 開発から管理用スクリプトまで" width="321" height="41" /></h2>
		</div>
	</div>
</div>

メニュー部分のCSS

Pure サイトからいただきました。軽量化に気合入っています。ほぼコピペ。

.menu-link {
	position: relative;
	display: block;
	/* show this only on small screens */
	top: 0;
	left: 0;
	background: #000;
	background: rgba(0, 0, 0, 0.7);
	font-size: 8px;
	/* change this value to increase/decrease button size */
	z-index: 10;
	width: 2em;
	height: auto;
	padding: 2.1em 1.6em;
}
.menu-link:hover,
.menu-link:focus {
	background: #000;
}
.menu-link span {
	position: relative;
	display: block;
}
.menu-link span,
.menu-link span:before,
.menu-link span:after {
	background-color: #fff;
	width: 100%;
	height: 0.2em;
}
.menu-link span:before,
.menu-link span:after {
	position: absolute;
	margin-top: -0.6em;
	content: " ";
}
.menu-link span:after {
	margin-top: 0.6em;
}
@media screen and (min-width: 48em) {
	#menuLink {
		display: none;
	}
}

メニューのトグル(表示ON/OFF)の JavaScript

これは、Pureサイトの JavaScript は複雑過ぎて理解できなかったので、そんなに手をかけなくていいや、という事で、サクッと jQuery でトグル(表示ON/OFF)を設定。これに伴い、メニューには「閉じる」の項目を追加(上記コード内太字)。

なお、「閉じる」の<li> に .pure-u-md-1-5 が付いていますが、これは大きな端末では隠す設定をしているので実は不要。

<script src="../js/jquery-1_11_3-min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
	//Check menu pull down
    $('#menuLink').click(function(){
       $('#mainmenu').toggle(300);
    });
   $('#mainmenu > li').click(function(){
   	$('#mainmenu').toggle(300);
   });
});
</script>

.hidden-md で隠す方法

上記では大きな端末で #menuLink を隠すために、CSSで直接 #menuLink に display: none; を設定している。一方、大きな端末では隠すクラスをあらかじめ設定してしまう、という事も可能。これが、「閉じる」メニューに付いている .hidden-md 。なぜ2通りあるのかというと、作業上の歴史的な理由と、最後にクリーニングをしていない私の無精のせい~。クラスを設定した方が、HTMLコードを見ただけでタグの振る舞いが分かるので楽。

このようなクラス定義は以下のように行う。上で使っているのは .hidden-md の方ですが、.visible-md なども作っておくと便利(後で使います)。

// メディアクエリーが無い場合はモバイル端末(全ての端末)用
.visible-md {
	display: none;
}

// メディアクエリーを指定して、大きな端末の場合にクラス設定を上書き
@media screen and (min-width: 48em) {
	.hidden-md {
		display: none !important;
	}
	.visible-md {
		display: block;
	}
}

上へ戻るボタン

モバイル端末でメニューにアクセスしやすいように、ページトップに戻るリンク(ボタン)を付ける。

追加したHTMLコード

太字部分が追加。

<div class="sugu-clear-both"></div>
<div id="topLink" class="hidden-md"><a href="#header">&uarr;</a></div>
</div><!-- /#main -->

追加したCSS

#topLink {
	background-color: rgba(0, 0, 0, 0.58);
	position: fixed !important;
	display: block;
	/* show this only on small screens */
	top: 75%;
	right: 0% !important;
	font-size: 10px;
	width: 2em;
	height: 2em;
	padding: 1em;
	z-index: 10;
}
#topLink:hover {
	background-color: black;
}
#topLink a {
	color: white;
	text-decoration: none;
	display: block;
	margin: 0 auto;
	font-weight: bold;
	text-align: center;
}
#topLink a:hover,
#topLink a:visited,
#topLink a:active {
	color: white;
}

モバイル版で隠す要素

モバイル版では、PC版では左カラムに表示していたいくつかの要素を隠した。たとえば「お問い合わせ先」の繰り返し表示など。

PCの表示要素をモバイル端末では隠す

PCの表示要素をモバイル端末では隠す

このためしたのは以下の作業。端末サイズによって表示したり隠したりするコンテンツをまとめて <div> で括る。

  1. divを分割する(一方を隠したりするため)
  2. .visible-md クラスの設定(上記で定義したもの)

この部分のHTML例

<!-- content -->
<div id="wrapper" class="pure-g">
	<div class="col_1 pure-u pure-u-1 pure-u-md-1-4">
		<div class="indent mobile_top_block mobile_last_block">
			<h2 class="title_top_black" style="margin-bottom: 0.5em;">技術者向け情報</h2>
			<div class="column1">
				<ul>
					:(リンク)
				</ul>
			</div>
		</div>
		<div class="indent visible-md"><!-- PCのみ -->
			<h2 class="title_bot">お問合せ</h2>
			<dl class="contact-table">
				:(問い合せ先)
			</dl>
		</div>
		<div class="left indent visible-md"><!-- PCのみ -->
			<ul class="icons">
				:(SNSリンクアイコン)
			</ul>
		</div>
	</div><!-- /col_1 -->
	<div class="col_2 pure-u pure-u-1 pure-u-md-3-4">
		:(メインコンテンツ)
	</div><!-- /col_2 -->
</div><!-- /wrapper -->

背景画像の追加

メイン画像は場所を取るので、モバイル端末用には代わりに邪魔にならない背景画像としてマスコット画像を配置。

HTMLコード

<div class="col_2 pure-u pure-u-1 pure-u-md-3-4">
	<div class="indent_top mobile_top_block">
		<div id="breadcrumb">
			<ol class="breadcrumblist">
				<li class="crumbtop"><a href="/">ホーム</a></li>
				<li>会社概要</li>
			</ol>
		</div>

		<h2 class="title_top">会社概要</h2>	
		<p>2010年2月に法人化しました。小規模 システム開発を行っています。</p>
	</div>
:

CSS

.mobile_top_block {
	background-image: url(../images/foon-face-gray4bg.png);
	background-repeat: no-repeat;
	background-position: 100% 100%;
}
@media screen and (min-width: 48em) {
	.mobile_top_block {
		background-image: none;
	}
}

区切り線の追加

左カラムのコンテンツが縦に積みあがった時にコンテンツの切れ目がないと分かりにくいので、<div> の間に線を引く設定。PC版の時は、左カラムのコンテンツはかなりスペースを取って配置しているので境界線は不要だが、モバイル端末の場合はスペース節約のためにスペースを無くして border-top を指定して線を引く。この時、上記の例のように .visible-md (モバイル端末では隠すブロック)が2つ以上つながると、ブロックが非表示になるとともにそのブロックに設定した境界線(border-top)が消えてしまうので、そのような場所には個別にクラス .mobile_last_block を設定して線を引く。これは1ページごとに内容を見ながら手動で調整。

HTML

<div class="col_1 pure-u pure-u-1 pure-u-md-1-4">
	<div class="indent mobile_top_block mobile_last_block">
		<h2 class="title_top_black" style="margin-bottom: 0.5em;">技術者向け情報</h2>
		<div class="column1">
			<ul>
				:(リンク)
			</ul>
		</div>
	</div>
	<div class="indent visible-md"><!-- モバイル端末では .indent に指定した境界が無くなる -->
		<h2 class="title_bot">お問合せ</h2>
		<dl class="contact-table">
			:(問い合せ先)
		</dl>
	</div>
	<div class="left indent visible-md"><!-- モバイル端末では .indent に指定した境界が無くなる -->
		<ul class="icons">
			:(SNSリンクアイコン)
		</ul>
	</div>
</div><!-- /col_1 -->

CSS

@media screen and (max-width: 47.999em) {
	.col_1 .indent + .indent {
		border-top: 1px #cccccc solid;
		padding-top: 0;
	}
	.col_1 .mobile_last_block {
		border-bottom: 1px #cccccc solid;
	}
}

不要なCSS設定の削除

行き当たりばったりで調整したので、使わなくなってしまったCSS設定が出たはず。これは、Dust-Me Selectors という Firefox アドオンで検出してCSSファイルから削除。

CSSファイルの統合と最小化(minify)

実際のサイトでは、PureのCSSとサイトの基本設定のCSSを合体して1ファイルにした上で最小化しています。

いぢゃうです。

レスポンシブWeb化するために掛かった時間

手が空いている時に調べながら切れ切れにやったので時間が掛かったけれど、CSSを切り替えながら最初の1ページを変更するのに合計1.5-2日程度、他の10ページ余りを変換してコンテンツを見ながら最終チェックするのに半日程度という所です。