JavascriptとCSSで表示切り替えとか
前回はTabを押した時にページ遷移をして(表示される内容は変わっていませんでしたが)内容を切り替えていました。
今回は、前回作ったものに更にボタン(ラジオボタン)を追加して、非同期でコンテンツの内容を変えてみます。
やったこと
- ボタンを2つ追加して、それぞれを押した時にページの表示内容を非同期で切り替える
- cssでビューポイントを設定して、ウインドウのサイズに合わせて表示内容のサイズを切り替える
はじめに
HTMLにおけるidとclassの関係を勘違いしており、前回のコードで一部同じidを複数箇所で使っているところがありました...。 また、idとclassは一つのタグに対してそれぞれ両方セットすることができるため、javascriptなどで特定の要素にアクセスする場合はidを、表示サイズなど複数要素で共有できるものはclassを使うことで、cssの量を減らすことができそうです。
ページ構成
public以下に、html/0.htmlとhtml/1.htmlというファイルを追加しています。
また、js/jquery-2.1.3.min.jsも追加しています(後述しますが、ネットから取得して利用する形でも問題ありません)。
プロジェクトのルートディレクトリ Lapp.rb Lconfig.ru LGemfile Lvendor Lbundle L... Lpublic Ljs Ljavascript.js Ljquery-2.1.3.min.js Lhtml L0.html L1.html Lviews Llayout.slim LviewTab.slim Lcss Lstylesheet.sass
ページ表示内容の切り替え
Ajaxについては以前もやりましたが、今回は表示したい部分のみを記述したHTMLファイルを作成しておき、それを呼び出して表示する、という処理を行います。
layout.slim
今回は非同期処理のためにjQueryを追加します。public/js/javascript.js同様、layout.htmlから読み込めるようにします。
doctype html html head meta charset="utf-8" title TabTest link href="/css/stylesheet.css" rel="stylesheet" body onload==@updateTabs main#main == yield script src="/js/jquery-2.1.3.min.js" script src="/js/javascript.js"
viewTab.slim
前回のコードの「section#tab_frame」と同階層に、以下を追加します。
section#tab_frame 〜(省略)〜 section#btn_frame input#btn_0 type="radio" name="btns" onchange="showContents(0);" label#btn_label_0.btn_label for="btn_0" ボタン0 input#btn_1 type="radio" name="btns" onchange="showContents(1);" label#btn_label_1.btn_label for="btn_1" ボタン1 section#contents_frame
- 「section#btn_frame」以下のボタンを切り替えることで、ページの表示内容を切り替えます。
- 読み込んだhtmlは、「section#contents_frame」以下に追加します。
javascript.js
(function() { 〜(省略)〜 this.loadTabs = function(intNewTabNum, intLastRightTabNum){ // ロード時に実行. Tabの表示切り替え、矢印ボタンのEnable/Disable. intTabNum = intNewTabNum; intRightTabNum = intLastRightTabNum; updateTabStyles(); // デフォルトでボタン0のコンテンツが表示されるようにする document.getElementById("btn_0").checked = true; showContents(0); }; 〜(省略)〜 this.showContents = function(intNewContentsNum){ $.ajax({ type: 'GET', url: '/async/' + intNewContentsNum, dataType: 'html', success: function(data) { $('#contents_frame').html(data); }, error:function() { alert('Error'); } }); }
- slimのボタンからだけでなくページロード時に実行する「loadTabs」からも「showContents」を呼んでいるのは、ページ表示時にコンテンツが表示されるようにするためです。
app.rb
〜(省略)〜 get '/async/:name' do File.open("public/html/" + params[:name].to_s + ".html") end end
- 上記では(なんとなく)app.rbでルーティングし、取得したhtmlファイルを返す処理を入れています。
- 「public/html」にアクセスするパスは、app.rbからの場合は「public/html/〜」、public/js/javascript.jsからは「/html/〜」となります。
非同期で呼び出すHTML
基本的には「section#contents_frame」以下に追加する部分だけをHTML形式で記述すればOKです。
ただし、そのままではHTMLは表示されてもCSSは反映されません。
そのため、呼び出すHTML内でスタイルを指定するか、CSSをロードする記述をしてやる必要があります。
0.html
< link href="/css/stylesheet.css" rel="stylesheet" > < div class="zero" id="zero_1" > < div class="zero_inside" id="zero_2" >< /div > < /div >
1.html
< link href="/css/stylesheet.css" rel="stylesheet" > < div class="one" id="one_1" >< /div > < div class="one" id="one_2" >< / div > < div class="one" id="one_3" >< /div >
レスポンシブデザインを取り入れてみる
画面やデバイスのサイズに合わせて、表示したコンテンツの大きさや並びなどを変更する、というレスポンシブデザインにトライしてみました。
やること
今回は後者で作成しました。
stylesheet.sass
$screen_s: 768px $screen_m_from: 769px $screen_m_to: 1536px $screen_l: 1537px @media only screen and (max-width: $screen_s) #main background-color: green height: 350px width: 600px @media only screen and (min-width: $screen_m_from) and (max-width: $screen_m_to) #main background-color: red height: 525px width: 900px @media only screen and (min-width: $screen_l) #main background-color: blue height: 700px width: 1200px
基本的には上記のような感じで、表示したウインドウの横幅の最小値(min-width)や最大値(max-width)を設定して、合致したものを適用します。
- 切り替え自体は自動で行われます。
- 背景色など画面サイズに関係がないものは「@media 〜」の子や孫にならないように書いておけば、すべての条件で適用されます。
- サイズを%で指定している場合は「@media 〜」の条件によらず親に合わせてサイズ変更されるため、これも別途書いておけばOKです。
- 画面サイズを変数として使用できますが、「only screen and (max-width: 768px)」自体を変数とした場合はエラーとなり、使用できませんでした。
というわけでSASSのコードを載せておきます。
stylesheet.sass
$screen_s: 768px $screen_m_from: 769px $screen_m_to: 1536px $screen_l: 1537px @media only screen and (max-width: $screen_s) #main background-color: green height: 350px width: 600px .btn_label font-size: 10px height: 100% width: 20% border: 1px solid #000 border-radius: 5px float: left #zero_1 border-radius: 50% height: 190px width: 140px margin: 40px 0px 0px 230px overflow: hidden #zero_2 border-radius: 50% height: 160px width: 110px margin: 15px 0px 0px 15px #one_1 height: 45px width: 15px margin: 40px 0px 0px 282.5px transform: rotate(45deg) -moz-transform: rotate(45deg) -webkit-transform: rotate(45deg) #one_2 height: 190px width: 15px margin: -43.5px 0px 0px 300px #one_3 height: 15px width: 76px margin: 0px 0px 0px 269.5px @media only screen and (min-width: $screen_m_from) and (max-width: $screen_m_to) #main background-color: red height: 525px width: 900px .btn_label font-size: 15px height: 100% width: 20% border: 1px solid #000 border-radius: 7.5px float: left #zero_1 border-radius: 50% height: 285px width: 210px margin: 60px 0px 0px 345px overflow: hidden #zero_2 border-radius: 50% height: 240px width: 165px margin: 22.5px 0px 0px 22.5px #one_1 height: 67.5px width: 22.5px margin: 60px 0px 0px 423.75px transform: rotate(45deg) -moz-transform: rotate(45deg) -webkit-transform: rotate(45deg) #one_2 height: 285px width: 22.5px margin: -65.25px 0px 0px 450px #one_3 height: 22.5px width: 114px margin: 0px 0px 0px 404.25px @media only screen and (min-width: $screen_l) #main background-color: blue height: 700px width: 1200px .btn_label font-size: 20px height: 100% width: 20% border: 1px solid #000 border-radius: 10px float: left #zero_1 border-radius: 50% height: 380px width: 280px margin: 80px 0px 0px 460px overflow: hidden #zero_2 border-radius: 50% height: 320px width: 220px margin: 30px 0px 0px 30px #one_1 height: 90px width: 30px margin: 80px 0px 0px 565px transform: rotate(45deg) -moz-transform: rotate(45deg) -webkit-transform: rotate(45deg) #one_2 height: 380px width: 30px margin: -87px 0px 0px 600px #one_3 height: 30px width: 152px margin: 0px 0px 0px 539px #arrow_button_left left: -999px position: absolute top: -999px #arrow_button_right left: -999px position: absolute top: -999px input[type="radio"] top: -999px left: -999px position: absolute #tab_frame height: 10% width: 100% .arrow_label background-color: #FFF height: 100% width: 3.3% border: 1px solid #000 border-radius: 5% display: block float: left input[type="button"]:disabled + #arrow_label background-color: #111 height: 100% width: 20px border: 1px solid #FFF border-radius: 5% display: block float: left .tab_label height: 100% width: 140px border: 1px solid #000 border-radius: 5% float: left #tab_label_0 background-color: #FFF #tab_0:checked + #tab_label_0 background-color: #000 #tab_label_1 background-color: #FFF #tab_1:checked + #tab_label_1 background-color: #000 #tab_label_2 background-color: #FFF #tab_2:checked + #tab_label_2 background-color: #000 #tab_label_3 background-color: #FFF #tab_3:checked + #tab_label_3 background-color: #000 #tab_label_4 background-color: #FFF #tab_4:checked + #tab_label_4 background-color: #000 #btn_frame height: 5% width: 100% overflow: hidden #btn_label_0 background-color: #386B88 #btn_0:checked + #btn_label_0 background-color: #DEB67E #btn_label_1 background-color: #386B88 #btn_1:checked + #btn_label_1 background-color: #DEB67E #contents_frame background-color: #7AB900 height: 84.8% width: 100% overflow: hidden .zero background-color: #E7850E .zero_inside background-color: #7AB900 .one background-color: #E7850E
- ちなみに表示されるのは、CSSで表現した0と1の文字です。
- 角丸のborder-radiusは、正円を描く場合は%指定が必要ですが、ボタンなどの角を丸くする場合はpx指定しないと元の四角の形が崩れてしまい、うまく角が丸まりません。
参考
Ajax
Sinatraでのファイルアクセス
レスポンシブデザイン
- デバイスに合わせてCSSを振り分ける「Media Queries」 - Developers.IO
- Sassを使ってレスポンシブウェブデザインにする時に覚えておいた方がいいこと4つ - howtohp
- iPhone/iPad/iPad mini用メディアクエリ一覧 - ENTEREAL/エンタリアル