●JavaScriptでデバイス判定が必要な理由
スマートフォンやタブレット、PCなど様々なデバイスでWebサイトを閲覧した経験があると思いますが、その際デバイスによって表示が崩れていたり、操作性が悪かったりすることはありませんでしたか?
モダンなWebサイトでは、どのようなデバイスからアクセスされても最適なユーザー体験を提供することが求められます。
レスポンシブWebデザインの登場によって、ある程度はデバイスの違いを吸収できるようになりました。
CSSのメディアクエリを使って画面サイズに応じたスタイルを適用することで、スマホでもタブレットでもPCでも見やすいレイアウトを実現できるのです。
しかし、レスポンシブデザインだけではカバーしきれない部分もあります。
デバイスによって適した機能や振る舞いは異なるからです。
たとえばスマホではGPS機能を活用した位置情報連動のサービスを提供したり、カメラを使った機能を実装したりといったことが考えられます。
一方PCではマウスオーバーを前提としたリッチなインタラクションを取り入れるといった具合です。
○レスポンシブデザインだけでは限界がある
レスポンシブデザインは主にレイアウトの調整を担うものです。
デバイスそのものの特性の違いまではカバーできません。
たとえば次のような場面では、単なるレイアウト調整以上のアプローチが必要になります。
・スマホではGPS機能を使った現在位置との連動機能を提供したい
・タブレットではマルチタッチ操作に対応したインタラクションを実装したい
・PCではホバーアクションを多用したリッチなUIを取り入れたい
このように、本格的なデバイス対応を行うには、アクセスしてきたデバイスを判定した上で、適切な機能や振る舞いを提供する必要があるのです。
その際に力を発揮するのがJavaScriptを使ったデバイス判定になります。
○デバイスごとに最適化したUXを提供
JavaScriptを使ってデバイスを判定することで、アクセスしてきたデバイスに合わせた最適なユーザー体験を提供できるようになります。
たとえば次のようなデバイス別の最適化が可能になるでしょう。
スマホの場合:
・位置情報を使った機能の提供
・カメラやマイクを使った機能の実装
・軽量化した機能やコンテンツの提供
タブレットの場合:
・マルチタッチ操作を活かしたインタラクションの実装
・没入感の高いコンテンツ表現
・PCに近い情報量を持った画面設計
PCの場合:
・マウスオーバーを活用したリッチなインタラクション
・大画面を活かした情報量の多い画面設計
・専用アプリのダウンロード促進
このようにデバイスの特性をふまえた上で、ユーザー体験を最適化していくことが理想的です。
デバイス判定は、より洗練されたWebサイトを作るための第一歩だといえるでしょう。
○広告の配信先を最適化
Webサイトの運営において広告は重要な収益源になります。
しかし、タブレットやスマホの普及に伴って、広告配信先の最適化も求められるようになってきました。
広告の種類やフォーマットはデバイスによって適したものが異なります。
たとえばスマホでは画面サイズが限られているため、テキスト広告よりもバナー広告が効果的でしょう。
またタブレットではテキスト中心の記事広告が馴染みやすいかもしれません。
このように、デバイス別に最適な広告手法を採用することで、広告収益の最大化を図ることができます。
そのためにもJavaScriptを使ったデバイス判定が役立つわけです。アクセス解析ツールと組み合わせることで、デバイス別のユーザー属性に合わせたよりきめ細やかな広告運用が可能になるでしょう。
●ユーザーエージェントを使った判定
さて、JavaScriptを使ったデバイス判定の具体的な方法について見ていきましょう。
まずは昔ながらの定番とも言えるユーザーエージェントを使ったアプローチです。
ユーザーエージェントとは、Webブラウザがサーバーに送信するテキスト情報のことです。
どのようなOSやブラウザ、デバイスからアクセスしているかを示す識別子になっています。
このユーザーエージェントを解析することで、アクセスしてきたデバイスを判定するというわけです。
往年のWebサイトではこの手法がよく使われていました。現在でも十分通用する知識ですので、抑えておきましょう。
○サンプルコード1:ユーザーエージェント文字列の取得
では早速、JavaScriptでユーザーエージェント文字列を取得するコードを見てみましょう。
navigator.userAgentプロパティを参照するだけでOKです。
たとえばWindowsのChromeで上記のコードを実行すると、次のようなユーザーエージェント文字列が得られます。
ブラウザやOSのバージョンなどが含まれているのがわかりますね。
これを手がかりにしてデバイス判定を行うわけです。
○サンプルコード2:iOSデバイスの判定
ユーザーエージェントの中から特定の文字列を探すことで、どのデバイスかを判定できます。
たとえばiOSの場合、”iPhone”や”iPad”、”iPod”といった文字列が含まれます。
これを利用したiOS判定のサンプルコードがこちらです。
iPhoneからアクセスした場合は次のような結果になります。
シンプルながら、確かにiOSかどうかを判定できていますね。
このように特定の文字列を頼りにデバイスを特定していくのがユーザーエージェント判定の基本です。
○サンプルコード3:Androidデバイスの判定
同様にAndroidの判定もしてみましょう。
Androidの場合は”Android”という文字列が含まれています。
Androidのスマートフォンやタブレットならこのような出力になるはずです。
ユーザーエージェントを使えば、モバイルOSの判定はお手の物ですね。
○サンプルコード4:タブレットデバイスの判定
タブレットの判定も考えてみましょう。
ユーザーエージェントにタブレットを示唆するキーワードがいくつか知られています。
代表的なのが”Tablet”や”Pad”、”Silk”などです。
iPad用のブラウザからだとこのような出力になります。
ただ、これらのキーワードを含んでいてもスマートフォンの場合もあるので、完全なタブレット判定とは言えません。
あくまで”タブレットの可能性が高い”程度の判定だと思っておきましょう。
○ユーザーエージェントの問題点と今後の動向
このようにユーザーエージェントを使えば、簡単にデバイス判定ができることがわかりました。
しかし、このアプローチにはいくつか問題点もあります。
そもそもユーザーエージェントは変更可能な情報です。
PCからでも自由に偽装できてしまうため、判定の確実性は低いと言わざるを得ません。
またユーザーエージェントの仕様も流動的なものです。
新しいデバイスの登場に合わせて書式が変わることもあれば、セキュリティ上の観点から意図的に情報を隠蔽する動きもあります。
実際、iOSの場合は最近のバージョンでユーザーエージェントの「細分化」が進んでいます。
具体的なデバイス名を含まなくなり、判定が難しくなってきているのです。
さらにHTTPクライアントヒントという新しい仕様の導入によって、ユーザーエージェントの役割は徐々に終わりを迎えようとしています。
●Navigator APIを使った判定
ユーザーエージェントの限界を感じて「もっと確実なデバイス判定の方法はないの?」と思った方もいるのではないでしょうか。
ご安心ください。
モダンブラウザの普及に伴って、より洗練された判定方法が使えるようになってきています。
そのひとつがNavigator APIです。
Webブラウザが提供するJavaScriptのAPIで、端末の各種情報を取得できるようになっています。
ハードウェア性能やバッテリー状態なども知ることができるんです。
Navigator APIを使えば、ユーザーエージェントよりも正確で詳細なデバイス判定が可能になります。
現代のWeb開発においては必須の知識と言っても過言ではないでしょう。
○サンプルコード5:プラットフォームの判定
ではNavigator APIの基本的な使い方から見ていきましょう。
navigator.platformプロパティを参照することで、OSやハードウェアのアーキテクチャ情報を取得できます。
たとえばWindowsパソコンで実行すると、次のような結果が得られるはずです。
同様にMacなら”MacIntel”、iPhoneなら”iPhone”、Android端末なら”Linux armv81″などの文字列が返ってきます。
よく知られているプラットフォーム名との対応関係は次の通りです。
- “Win32” : Windows
- “MacIntel” : Intel Mac
- “iPhone” : iPhone
- “iPad” : iPad
- “Linux armv81” : Android端末
- “Linux x86_64” : Linux PC
このようにnavigator.platformを見るだけで、OSやデバイスの系統を大まかに判定できます。
ただし、あくまで「系統」の判定であって、詳細なバージョンなどはわかりません。
○サンプルコード6:タッチデバイスの判定
続いてタッチ操作が可能なデバイスかどうかを判定してみましょう。
maxTouchPointsプロパティを見ることで、マルチタッチポイントの最大数がわかります。
たとえばiPadで実行すると、次のような結果になります。
一方でPCの場合は、touchイベントに対応していないので0が返ってきます。
したがって、maxTouchPointsの値が1以上であればタッチデバイスだと判断できます。
簡単なロジックでタッチデバイス判定が実現できるのは嬉しいですね。
○サンプルコード7:メモリ情報から判定
続いてメモリ情報を取得して、高スペックデバイスかどうかを判断してみましょう。
DeviceMemoryプロパティでRAMの搭載容量を知ることができます。
iPhoneXで実行してみると、こんな感じで表示されます。
一方、メモリ4GBのAndroidタブレットなら次のような結果になるでしょう。
もちろんPCでもメモリ容量は取得可能です。
私のMacBook Proでは次のように表示されました。
搭載メモリが多いほどハイスペックな端末だと考えられます。
たとえば4GB以上であれば3Dゲームなどリッチコンテンツに耐えうるデバイスだと判断できるかもしれません。
○サンプルコード8:バッテリー情報から判定
最後にバッテリー情報を見てみましょう。
getBattery()メソッドを呼び出すことで、バッテリーに関するさまざまな情報を取得できます。
iPhoneで実行してみると、たとえばこのような出力が得られます。
バッテリー情報はモバイルデバイスの特性を知る上で重要な指標となります。
常時電源が確保されているPCとは異なり、充電の有無やバッテリー残量は使い勝手に直結するからです。
単に「モバイルかどうか」だけでなく、バッテリー残量が少ない場合は重い処理を避けるなど、きめ細かなユーザー体験の最適化が可能になるでしょう。
●CSS Media Queryを使った判定
JavaScriptを使ったデバイス判定は強力ですが、実はCSSだけでもある程度のデバイス判定は可能なんです。
それを実現するのがCSS Media Queryという機能です。
CSS Media Queryは、デバイスの画面サイズや解像度、色深度などの情報を使って、適用するCSSを切り替える仕組みです。
レスポンシブWebデザインの根幹をなす技術と言えるでしょう。
通常、CSS Media Queryはレイアウトの調整に使われることが多いですが、JavaScriptと組み合わせることでデバイス判定にも活用できます。
Media Queryで条件分岐し、JavaScriptでそれを判定するわけです。
たとえばスマートフォン向けのスタイルが適用されているかどうかを見れば、アクセスしてきたデバイスがスマホなのかどうかがわかります。
レスポンシブデザインをすでに実装済みのサイトなら、比較的簡単にデバイス判定ロジックを追加できるのが魅力ですね。
それではMediaQueryを使ったデバイス判定の具体的な方法を見ていきましょう。
シンプルな実装ながら、意外と精度の高い判定が可能だと気づかれるはずです。
○サンプルコード9:画面サイズでの判定
まずは画面サイズを使った判定のサンプルコードです。
CSSでメディアクエリを定義し、JavaScriptから判定します。
ポイントは擬似要素の値をJavaScriptから取得していることです。
window.getComputedStyle()メソッドとcontentプロパティを使うことで、CSSで設定した文字列を参照できます。
たとえばiPhoneで実行すると、次のようにスマートフォンだと判定されるはずです。
一方で画面の大きなタブレットなら、次のような判定になります。
画面サイズの閾値は自由に設定できるので、プロジェクトの基準に合わせて調整しましょう。
やや面倒なのは、ブレイクポイントを変更した場合はHTMLとCSSの両方を修正する必要があることですね。
メンテナンス性を考えると、閾値は変数化しておくのがベターかもしれません。
○サンプルコード10:デバイスピクセル比での判定
続いて、より正確なデバイス判定が期待できるデバイスピクセル比を使った方法を紹介します。
デバイスピクセル比とは、物理ピクセルとCSS上のピクセルの比率のことです。
高解像度ディスプレイを搭載したデバイスほど、この値が高くなる傾向にあります。
たとえばiPhoneXのデバイスピクセル比は3、iPhone8は2、一般的なPCやノートPCは1になります。
この特性の違いを手がかりにデバイスを判別できそうですね。
iPhone8で実行してみると、次のようにmidレンジのデバイスだと判定されます。
一方でMacBookProなら、lowレンジの判定になるはずです。
このようにデバイスピクセル比を見ることで、より詳細なデバイスの特定が可能になります。
ただしベンダープレフィックスが必要だったり、Android端末で比較的新しい機能だったりと、気をつけるべき点もあります。
実装の際はサポート状況をよく確認しておきましょう。
●よくあるエラーと対処法
さて、ここまで3つのデバイス判定方法を紹介してきました。
具体的なサンプルコードを使いながら、実装のイメージはつかめたのではないでしょうか。
しかし、いざ自分で書いてみると上手くいかない…そんな経験をされた方も多いと思います。
JavaScriptのデバイス判定は一筋縄ではいかないのが実情なのです。
初心者がつまずきやすいポイントを踏まえて、よくあるエラーとその対処法を見ていきましょう。
コードを書くだけでなく、適切にデバッグする方法も身につけることが大切ですからね。
○判定が意図通りにならない場合
デバイス判定のロジックを書いたはいいけれど、iPhoneなのにAndroidだと判定されてしまう…。
こんな状況に遭遇したことはありませんか?
意図通りの判定にならない場合、まず疑うべきはデバイス名の指定ミスです。
例えば、iOSの判定で次のように書いてしまったとします。
正しくは「iOS」なのに、小文字の「ios」と書いているために判定が効いていないのです。
JavaScriptは大文字小文字を区別するので、「iOS」「Android」「Windows」など、正しい表記を使うよう注意しましょう。
またデバイス名だけでなく、判定に使うプロパティ名にも気をつけましょう。
例えばよくある間違いが、navigator.userAgentを「userAgent」と書いてしまうことです。
正しくはnavigator.userAgentですから、navigatorを忘れずにつけるようにしましょう。
このようなタイプミスは初心者に限らず誰にでもありがちです。
判定がうまくいかない場合は、まず綴りのチェックから始めると良いでしょう。
変数名やプロパティ名をコピペすれば、ミスを防げます。
○iOS/Androidの判定が困難なケース
userAgentで判定する場合、iOS/Androidといったモバイルデバイスは比較的分かりやすいキーワードで判別できます。
しかしそれ以外のデバイスやブラウザだと、判定がかなり難しくなってきます。
例えばMacでChromeを使っている場合のuserAgent文字列は次のようになります。
一方でSafariだと、次のような感じです。
両者を見比べると、「Chrome」や「Safari」といったキーワードの有無で区別できそうだとわかります。
しかし、これだけでは十分とは言えません。
というのもEdgeの場合、userAgent文字列に「Chrome」が含まれているからです。
最近のブラウザはChromiumベースになっているので、userAgentの判定が非常にやっかいなのです。
したがって、userAgentによるブラウザ判定はある程度の精度で考えるしかありません。
プロダクトの要件次第ですが、「Chrome系」「Safari系」といった程度の区別に留めておくのが無難でしょう。
○判定ロジックが複雑になってしまう場合
「デスクトップSafari」「iOS版Chrome」「Androidタブレット」…。
このように様々な条件が組み合わさると、判定ロジックがどんどん複雑化していきます。
ifの条件分岐が増えれば増えるほど、コードは読みづらく、バグも生まれやすくなります。
かといって、判定の粒度を荒くすると、今度はデバイス対応に不都合が出てきます。
こうした状況に陥ったら、デバイス判定用のライブラリの導入を検討しても良いかもしれません。
UAParserやua-parser-jsなど、有名なライブラリが幾つかあります。
例えばua-parser-jsを使うと、次のように簡単にデバイス情報を取得できます。
出力結果
パース処理を任せることで、複雑怪奇な判定ロジックから解放されるのは大きなメリットです。
ただし、ライブラリを常に最新に保つ工夫は必要になりますので、そこは注意が必要ですね。
●デバイス判定のベストプラクティス
さてここまで、JavaScriptを使ったデバイス判定の様々な方法を見てきました。
ユーザーエージェントからCSSのメディアクエリまで、それぞれの特徴と実装方法を詳しく解説しましたね。
でも、本当に良いデバイス判定の実装をするには、単にコードを書けるだけでは不十分なのです。
プロジェクトの要件や運用面なども考慮に入れた、戦略的な判定設計が求められます。
そこでここでは、JavaScriptのデバイス判定を行う上でのベストプラクティスを提案します。
初心者の方はもちろん、ある程度経験のあるエンジニアの方にも参考になるはずです。
これからご紹介する4つの考え方を念頭に置けば、堅牢で保守性の高いデバイス判定の実装が可能になるでしょう。
判定機能の設計にお悩みの際は、ぜひこの章を思い出してみてください。
○ユーザーエージェントに頼りすぎない
デバイス判定の代名詞とも言えるユーザーエージェント判定。
確かに手軽で手堅い方法ではあるのですが、万能というわけではありません。
新しいデバイスが登場する度にユーザーエージェントのパターンを追加しなければならないのは非効率的ですし、そもそもユーザーエージェントは偽装可能な情報なので、信頼性にも欠けます。
ですから、ユーザーエージェントに頼りすぎるのは避けましょう。
デバイスの特定が目的なら、むしろ別のアプローチを検討してもいいかもしれません。
例えばCSSメディアクエリなら、画面サイズを基準にデバイスを判別できます。
今日ご紹介したような、JavaScriptと組み合わせる方法を使えば、かなり正確な判定が可能になるはずです。
○フィーチャーディテクションを併用する
ユーザーエージェントの限界を補うのに有効なのが、フィーチャーディテクションと呼ばれる手法です。
これは、デバイスの機能や特性を直接チェックして、その有無や種類を判定するアプローチになります。
たとえばタッチイベントへの対応をチェックすれば、タッチデバイスかどうかを判別できますよね。
こうした具体的な機能の可否を見ることで、より的確なデバイス対応が可能になるのです。
フィーチャーディテクションの実装には、Modernizrというライブラリがよく使われます。
様々なHTML5やCSS3の機能をチェックするメソッドが用意されているので、知っておくと役立つでしょう。
使い方はとてもシンプルです。
例えばgeolocationプロパティの有無を見るなら、次のように書くだけです。
ただしModernizrはあくまで機能の有無を教えてくれるだけで、デバイスそのものを特定するわけではないので注意が必要です。
あくまでユーザーエージェント判定の補助として使うのがおすすめです。
○サーバーサイドでも判定ロジックを持つ
今日ご紹介したデバイス判定は、基本的にクライアントサイドJavaScriptで行うものでした。
しかし、場合によってはサーバーサイドでもデバイス判定のロジックを持つと良いでしょう。
たとえばWebサイトへのアクセスログをもとに、デバイス別のアクセス状況をレポーティングしたいケースがあるとします。
その場合、サーバーサイドでユーザーエージェントを判定し、データを蓄積しておく方が効率的です。
またページ表示の高速化を考えた時、サーバーサイドでデバイスを判定してからHTMLを生成する戦略も考えられます。
その場合、Node.jsのようなJavaScriptランタイムを使えば、クライアントとサーバーでコードを共有できるのが嬉しいポイントですね。
○判定結果をキャッシュする
最後に、デバイス判定の結果はキャッシュしておくことをおすすめします。
毎回判定を行うと、ページ表示のパフォーマンスに悪影響を及ぼすかもしれません。
判定結果をCookieやlocalStorageに保存し、次回以降はその値を参照するだけにすれば、処理の負荷を下げることができるはずです。
ここではlocalStorageを使ったデバイス判定結果のキャッシュ例を紹介します。
初回アクセス時にのみ判定を行い、それ以降はlocalStorageの値を使うことで、無駄な処理を省けるわけです。
ただしデバイスが変わることも考慮し、一定期間でlocalStorageをクリアする仕組みも必要になります。
あくまで利便性とのバランスを取るように実装しましょう。
まとめ
今回は、JavaScriptを使ったデバイス判定の様々な手法について解説してきました。
ユーザーエージェントを使った基本的なアプローチから、Navigator APIやCSSメディアクエリを活用した高度な判定方法まで幅広く取り上げてきたつもりです。
デバイス判定は、Webサイトやアプリケーションにおけるユーザー体験の最適化に欠かせない技術です。
本記事で得た知識とサンプルコードを活かして、ぜひ実際の開発に役立ててみてください。
皆さんの活躍を心から応援しています!