スマートフォンWebアプリのレイアウトテンプレートを考えた
2013年06月27日
いつか僕もスマートフォン用のWebアプリを作りたいって思うときが来るかなーとかうすらぼんやり考えてて、でもスマートフォン用のWebアプリって確か固定配置が難しくなかったっけ?んじゃどうすんだろうねー、とか色々考えてて、あれ?もしかしたらこれいけんじゃね?って案が出たので作ってみました。
根本の考え方
基本的にスマートフォンアプリのUI(僕はiOSしか知らないのでAndroidはとりあえず置いておく)を踏襲するというか、それを可能にするのがとりあえずの目的です。
多分画面全部のスクロールってのはあんまりないイメージ。スクロールするとしてもそれは画面のどこか一画面な気がする。
何となくTwitterアプリとかFacebookアプリとかな感じのUIが作れれば色々応用が利くかなぁと思います。
主なやりたいこと
一般的だとぼくが思ってるiOSアプリのUIということで、最低限これだけが実装できて、他で使い回せるように作れれば良いかなぁと思ったものをピックアップします。
- ヘッダーの上部固定
- フッターの下部固定
- コンテンツ部分はスクロールする
- スライド式メニュー
これが出来れば何となくiOSアプリっぽくなりませんかね。何となくなる気がしてますがどうでしょう。
今日はお時間がないのでできあがったものがこちらになります
うそです、ちゃんと下に解説を書いてます。お時間のある方は読んでもらえると嬉しいです。
とりあえずこれが完成イメージです。ヘッダー、フッターがちゃんと固定されていて、中身だけスクロールしているのが分かりますでしょうかね。分かりにくいね。誰かデザイン直してください。
デモもアップしています。スマートフォンでデモページを見れますのでこちらもどうぞ。誰かデザイン直してください。
html
というわけで、まずはhtmlの構成を。
■html
<div class="bodyInner">
<div class="page">
<header class="pageHeader">
</header>
<section class="content">
</section>
<footer class="pageFooter">
</footer>
</div><!-- /.page -->
<div class="globalNav">
<ul>
<li>メニュー1</li>
<li>メニュー2</li>
</ul>
</div><!-- /.globalNav -->
</div><!-- /.bodyInner -->
まず body タグを丸っと囲む .bodyInner というdivを作ります。 body で良いじゃんかと思われた方がいそうですが、body に overflow:hidden; が効かないっぽかったんで苦肉の策です。僕だってできれば使いたくないよこんな無駄な感じのタグ!!
そしてその中に .page と .glovalNav という div を作ってます。 .page はメインとなるページですね、 .globalNav はスライド式メニューです。最初 .slideMenu っていうクラス名にしようとしたんだけど、スライドしない表示のさせ方をする事もあるかもね、と思い直して汎用性を高くしたクラス名にしました。
.page の中にはヘッダー、フッター、コンテンツが入ります。
画面の高さ=コンテンツの高さにする
まずは、上でちらっと書いたようにコンテンツ自体の高さを画面の高さと同じにしてしまいます。ページのサイズ=ウィンドウのサイズな感じのFlashサイトが良くありましたよね、あんな感じにします。
Webページだと縦に長いコンテンツをスクロールさせるという画面仕様が一般的だと思いますが、アプリだとそもそもそこが違っていて、画面サイズを基準にコンテンツを作るんじゃないかと思うので、今回はWebページっぽく作るのではなく、アプリっぽく作ってみようと思います。
実装方法ですが、高さを画面サイズにすることはcssとかviewportとかだけで何とかすることは(多分)できませんので、 Javascript にお任せします。
■Javascript
// 画面の高さ取得
var windowHeight = window.innerHeight;
// コンテンツの高さを画面の高さにする
var contents = $(".bodyInner, .page, .globalNav");
contents.css("height", windowHeight + "px");
はみ出した部分を隠す
コンテンツ部分の高さを指定するのは良いのですが、実際には指定した高さよりもコンテンツが多ければ当然あふれてしまいます。
それを防ぐために、コンテンツ部分には overflow を指定します。
■css
.content {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
overflow に scroll を指定してあげれば iframe 的なスクロールが出来るようになります。
ついでに -webkit-overflow-scrolling: touch; を指定してあげればOSネイティブの慣性スクロールを実装してくれます。というかそれは標準でやってくれてもいいんじゃないかなぁと思いますけどね。
ヘッダー、フッターの固定配置
さて次はヘッダーとフッターの固定配置です。
今回はそもそも上記のようにページの高さを画面の高さと同じにしているので、固定配置というか、ヘッダーは上に、フッターは下に絶対配置すれば自動的に固定配置になります。
というかまぁ、ヘッダーは最上に置いてる要素なので特に絶対配置する理由も見当たりませんね。なのでフッターだけ絶対配置でページ下部に配置。
■css
.page {
position: relative;
}
.pageFooter {
position: absolute;
left: 0;
bottom: 0;
}
コンテンツ部分はどうするか
さて次はコンテンツ部分ですね。コンテンツ部分は表示位置としてはヘッダーを通常配置していますので、コンテンツ部分の開始位置はヘッダーのすぐ下からになります。
そしてフッターを画面最下部に配置していますので、コンテンツの高さは先ほど書いたように、以下のようにすればOKという事になりますね。
コンテンツ高さ = 画面高さ - ヘッダー高さ - フッター高さ
なので、これも Javascript で指定しましょう。
■Javascript
// 画面の高さを取得
var windowHeight = window.innerHeight;
// ヘッダーの高さを取得
var headerHeight = $(".pageHeader").innerHeight();
// フッターの高さを取得
var footerHeight = $(".pageFooter").innerHeight();
// コンテンツの高さを作る
var contentHeight = windowHeight - headerHeight - footerHeight;
$(".content").css({"height": contentHeight + "px"});
そしてここにもはみ出した部分を隠す処理が必要です。
■css
.content {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
これでヘッダー、コンテンツ、フッターの配置が完了です。
横向きにしたときの対応
とりあえずこれで良い感じに動きます。横向きにした場合の対応として、サイズ取得->変更の箇所をリサイズ時にも適用させてあげるとなお良いですね。
■Javascript
$(window).resize(function(){
// 高さ取得&変更を記述
});
スライド式メニュー
最後にスライド式メニューです。よくあるやつです。僕がいつか作りたいいつか作りたいと願ってやまなかったスライド式メニューです。意外とあっさりやれたので、やっぱり人間「やるかやらないか」に尽きるんだなぁと思いました。
まず、メインの表示部分を .page の中に全部突っ込んで、スライド式メニューは .globalNav の中に入れてるので、通常の状態は .page も .globalNav も top: 0; left: 0; の位置に配置しておいて、 globalNav を .page の下に配置しておいて、トグルボタンを押したときに .page が右にスライドされれば実現できます。
cssはこんな感じ。 body を relative にして、 .page と .globalNav を絶対配置。そして z-index で重なり順を調整。
■css
.bodyInner {
position: relative;
overflow: hidden;
width: 100%;
}
.page,
.globalNav {
position: absolute;
top: 0;
left: 0;
overflow: hidden;
}
.page {
z-index: 2;
background: #fff;
width: 100%;
-webkit-transition: left 0.3s linear;
box-shadow: -1px 0 3px #999;
}
.globalNav {
z-index: 1;
width: 80%;
background: #fee;
}
ボタンクリック時の切り替えはjavascripを記述しましょう。
■Javascript
var menuFlg = 0;
globalNavToggle.bind( "click", function(){
// 開いてない状態だったら
if ( menuFlg === 0 ) {
menuFlg = 1; // フラグ変更
page.css({"left": "80%"}); // コンテンツを右に80%移動
} else {
menuFlg = 0; // フラグ変更
page.css({"left": "0"}); // コンテンツを左に戻す
}
});
切り替えはJavascriptですが、アニメーションは先ほどのCSSで transition を指定しているので、それっぽくアニメーションしてくれます。
これで完成。細かいとこはここには記述してないですが、まぁそれはcssの細かい話なので別にいいかなーと。
おわりに
これで一応それっぽいものが出来上がりました。僕のもってるスマートフォンではそれなりに動いてるみたいです。まだまだ「完璧だぜ!」というにはほど遠い、と言うか何点か何とかしたいところがあるのですが、初めの一歩としては上出来かなぁと。
実機確認は自分でもってる2端末でしかやってないんだけど普通に動いたら良いな−。
上手い事いったり誰かが褒めてくれたらいつも通りjQueryプラグインにしてみたりもしようかなぁと思ってる感じですが、とりあえず今回はこれで良いかな。作るとしたらこれだとcssファイルもセットにする必要があるかなー。
というわけで、何となくスマートフォン用Webアプリの雛形的なものも出来たことですし、これを使って何を作ろうかなぁと思う感じです。はたして本当に作るのか?
他にこんな事も書いてます
- JavaScript祭スピンオフ! フロントエンド祭り in Co-Edo でオブジェクトベースのJSについて話してきた
- 第5回 HTML5minutes! で話してきた
- 秋のJavaScript祭りで話をしてきた
- 春のJavaScript祭りでAngularJSについてお話ししてきました
- Dashすげー便利
- jQueryのwidth,height系メソッドの違いについて
- Grunt+ST2な人がプロジェクトをチャチャっと開始する方法
- ローカルマシンにNode.jsをインストール
- AngularJSでページロード時にコンパイル前のタグが表示されるのを防ぐ
- スクロールで隠れるナビゲーションメニューのJSがステキだったので勝手にプラグイン化しました
FBでコメント