第 2 章 媒體查詢 : 支援不同的視域 - 媒體查詢 (Media query) * 為 CSS3 的模組之一, 用來查詢使用者媒體 (Media) 的特性, 以便調整 CSS 的樣式 * 媒體特性 : 視域寬度 螢幕寬高比 (Aspect ratio) 橫或縱向 (Landscape or portrait) (1) 媒體查詢語法 - 範例 : 依據媒體查詢結果變換背景顏色 bgchange.html bgchange.css <!DOCTYPE html> <html> <head> <title>browser background changer</title> <meta charset=utf-8> <link rel=stylesheet href=bgchange.css> </head> <body> </body> </html> body { background-color: grey; @media screen and (max-width: 960px) { body { background-color: red; @media screen and (max-width: 768px) { body { background-color: orange; @media screen and (max-width: 550px) { body { background-color: yellow; @media screen and (max-width: 320px) { body { background-color: green; * 使用現代的瀏覽器, 變換頁面尺寸, 背景顏色會跟著變化 * CSS2 亦可使用下列方式指定某種媒體應使用某個樣式檔 <link rel="stylesheet" type="text/css" media="screen" href="screen- styles.css"> * CSS2 僅查詢媒體型態 (Type), 但 CSS3 主要功能不在於查詢型態, 而是依據該裝置的能力 (Capability) 或特性 (Feature) 來決定其樣式 # 如果瀏覽器的回答是 真 (True), 就使用所指定的樣式 ; 否則 (False) 就不使用 # 例如 : 依據條件載入某個樣式檔 - 提問 : 你的螢幕是縱向? : <head> <link rel=stylesheet media="screen and (orientation: portrait)" href=portraitscreen.css> </head> - 上述有兩個問題 :(1) 詢問型態 : 是螢幕嗎?(2) 詢問特性 : 是縱向嗎? - 可加上邏輯運算 not <link rel=stylesheet media="not screen and (orientation: portrait)" href=portraitscreen.css> - 可串接許多條件判斷 <link rel=stylesheet media="screen and (orientation: portrait) and (min-width: 800px)" href=800wide-portrait-screen.css> 2-1
- 可串接許多條件判斷 <link rel=stylesheet media="screen and (orientation: portrait) and (min-width: 800px)" href=800wide-portrait-screen.css> - 亦可使用 @import ( 但這種方式增加 1 個 HTTP request, 也就降低速度, 少用 ) @import url(phone.css) screen and (max-width:360px); # 例如 : 依據條件設定 h1 元素為綠色 @media screen and (max-device-width: 400px) { h1 { color: green - 可查詢的媒體特性 * 在建構回應式網頁時, 最常查詢的是視域寬度 (width) 與裝置的螢幕寬度 (devicewidth), 其餘的較少使用 * 所有可供查詢的特性如下 : # width: 視域寬度 # height: 視域高度 # device-width: 裝置的螢幕寬度 # device-height: 裝置的螢幕高度 # orientation: 螢幕方向 # aspect-ratio: 視域寬高比 ( 例如 :aspect-ratio: 16/9) # device-aspect-ratio: 裝置螢幕寬高比 # color: 表示一個顏色的位元數 ( 例如 :min-color: 16) # color-index: 色彩查詢表 ( 調色盤 ) 裡的顏色數量 # monochrome: 一個像素在單色畫幀緩衝區的位元數 # resolution: 螢幕或列印的解析度 ( 例如 :min-resolution: 300dpi) # scan: 針對電視, 漸進式 (Progressive) 或交錯式 (Interlace) 特性, 例如 :720p HD TV scan: progressive,1080i HD TV scan: interlace # grid: 裝置屬於網格型 (Grid) 或位元圖型 (Bitmap) * 以上名稱除了 scan 與 grid 外, 都可以在前面加上 min 或 max 來產生範圍值, 例如 : <link rel=stylesheet media="screen and (min-width:200px) and (max- width:360px)" href=phone.css> (2) 範例 1: : 依據視域呈現不同的選單結構 - 設計頁面的 6 個導航 (Navigation) 的依視域寬度有不同的排列方式 ( 資料來源 :How to Create a Responsive Navigation, by Thoriq Firdaus) * 視域由寬到窄設定清單選項的排列格式 : 水平排列 3 列 2 行 2 列 3 行之下拉式清單 6 列 1 行 2-2
- 第一步 : 建立網頁 nav.html, 使用 HTML5 的標準 * 建立 <nav> 區塊標籤, 並設為 clearfix 類別 ( 利用前述之 clearfix 技術 ) * <ul> 標籤亦設為 clearfix 類別 * 加上清單標籤 <a>, 並設其 ID 為 pull <!DOCTYPE html> <html> <head> <title> 回應式導航範例 </title> <meta charset=utf-8> <link rel=stylesheet href=nav.css> </head> <body> <nav class=clearfix> <ul class=clearfix> <li><a href=#> 首頁 </a></li> <li><a href=#> 如何做 </a></li> <li><a href=#> 圖示 </a></li> <li><a href=#> 設計 </a></li> <li><a href=#>web 2.0</a></li> <li><a href=#> 工具 </a></li> </ul> <a href=# id=pull> 清單 </a> </nav> </body> </html> - 在 <head> 元素中加入 meta viewport 標籤, 用來在不同的視域中適當縮放頁面 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> * 基本格式 :<meta name="viewport" content=""> * 可在 content="" 做許多設定, 例如專為 320px 視域寬度所設計的頁面 :<meta name="viewport" content="width=320"> * 最常用的設定 :content="width=device-width, initial-scale=1, maximum-scale=1" # 設定頁面寬度等於裝置的寬度 :width=device-widt # 確保在開啟頁面時, 頁面是以 1:1 的比例呈現, 沒有縮放 :initial-scale:1 # 防止使用者縮放頁面 :maximum-scale=1 - 開始建立各個元素的風格 (Style) * 設定背景顏色 :#ece8e5 * <nav> 標籤 : 高度為 40px, 寬度為與頁面相同 (100%), 適當的顏色 字體 字型, 相對位置, 下方邊界為 2px 寬 實線 顏色為 #283744 * 設定 <nav> 元素中的 <ul> 標籤 ( 不在 <nav> 元素中的 <ul> 標籤不受影響 ): 置中, 寬度為 600px, 高度為 40px * 設定 <nav> 元素中的 <li> 標籤 ( 不在 <nav> 元素中的 <li> 標籤不受影響 ): 以 inline ( 亦即不換行 ) 方式呈現, 設為向左浮動使按鈕依序排列 * 以上設定均儲存於 style.css, 在 nav.html 的 <head> 元素中加入連結 <link rel="stylesheet" href="style1.css"> * nav.css 及目前結果 body { background-color: #ece8e5; nav { height: 40px; width: 100%; background: #455868;.clearfix:before,.clearfix:after { content: " "; display: table;.clearfix:after { clear: both; 2-3
font-size: 11pt; font-weight: bold; position: relative; border-bottom: 2px solid #283744; nav ul { padding: 0; margin: 0 auto; width: 600px; height: 40px; nav li { display: inline; float: left;.clearfix { *zoom: 1; * 導航 # 因 <ul> 寬度為 600px, 共有 6 個導航, 因此導航寬度設為 100px # 文字置中, 以 inline-block 方式呈現 (inline 呈現, 而且本身是區塊 ), 不裝飾連結 ( 亦即沒有底線 點擊變色等屬性 ), 設定文字高度及陰影 nav a { color: #fff; display: inline-block; width: 100px; text-align: center; text-decoration: none; line-height: 40px; text-shadow: 1px 1px 0px #283744; # 將每個導航 <a> 的右方設定 1px 寬的邊界 ( 除了最右邊的導航 ), 但這會使得導航的寬度變成 101px, 因此將 box-sizing 設為 border-box # 顏色 :#576979,mozilla 及 webkit 瀏覽器引擎的 box-sizing 均設為 border-box nav li a { border-right: 1px solid #576979; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; nav li:last-child a { border-right: 0; # 導航的滑鼠效應 : 在 :hover 或 :active 狀態時, 有較亮的顏色 # 清單連結設為隱藏 nav a:hover, nav a:active { nav a#pull { background-color: #8c99a4; display: none; - 目前結果 ( 尚無回應式特性, 縮小視域會將導航截斷 ) - 利用媒體查詢及 jquery 設計回應式導航 : 建立視域門檻 * 原始頁面寬度為 600px, 此為第一門檻, 設計視域小於 600px 時, 做以下變化 : # <nav> 的高度設為 auto, 以自動因應高度 ( 當導航變成 3 列時, 高度增加 ) # 導航區塊應佔滿視域寬度, 所以 <ul> 的寬度設為 100% 2-4
# 當頁面縮減, 希望導航成為 3 列, 每列 2 個導航, 並且依序排列, 因此 <li> 設為向左流動, 且寬度為 50% # 為 <a> 加上裝飾, 並設定文字位置 @media screen and (max-width: 600px) { nav { height: auto; nav ul { width: 100%; display: block; height: auto; nav li { width: 50%; float: left; position: relative; # 結果如下圖 (a) nav li a { border-bottom: 1px solid #576979; border-right: 1px solid #576979; nav a { text-align: left; width: 100%; text-indent: 25px; (a) (b) * 第 2 個門檻設為 480px, 導航以清單按鈕控制 # 在這個視域範圍中, 原先隱藏的清單標籤要出現 (display: block;) # 原先的 <ul> 元素要隱藏 (display: none;), 且高度設為自動 # 清單按鈕設定 - 背景顏色 #283744, 寬度 100% # 利用 :after 設定清單按鈕後方的屬性 - 沒有文字內容 (content: "";) - 背景採用影像 nav-icon.png, 不重複 - 高寬各為 30px,inline-block 方式呈現, 右方間隔 15px, 上方間隔 10px @media only screen and (max-width : 480px) { nav { border-bottom: 0; nav ul { display: none; height: auto; nav a#pull { display: block; background-color: #283744; width: 100%; position: relative; nav a#pull:after { content:""; background: url('nav-icon.png') no-repeat; width: 30px; height: 30px; display: inline-block; position: absolute; right: 15px; top: 10px; # 結果如上圖 (b), 但點選清單並無反應, 連結 Google API 的 jquery 函式庫置於 2-5
<head> 元素中, 並於 </body> 之前撰寫 jquery 程式 <head>... <script src=http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js></script> </head> <body>... <script> $(function() { var pull = $('#pull'); menu = $('nav ul'); menuheight = menu.height(); $(pull).on('click', function(e) { e.preventdefault(); menu.slidetoggle(); ); $(window).resize(function(){ var w = $(window).width(); if(w > 320 && menu.is(':hidden')) { menu.removeattr('style'); ); ); </script> </body> # 結果如下圖 (c) (c) (d) * 第 3 個門檻設為 320px, 導航點選後以單欄排列 # 選項設為單欄, 亦即 <li> 不流動, 寬度 100%, 如上圖 (d) @media only screen and (max-width : 320px) { nav li { display: block; float: none; width: 100%; nav li a { border-bottom: 1px solid #576979; (3) 範例 2: 得獎者不是... - 最佳的回應式網頁設計是由小視域漸漸設計到大視域, 但本範例先從目前對我們而言較為直覺的由大到小方式設計 - 製作類似右圖 寬 960px 的頁面, 所包含的結構元素 : * 頁首 (Header) * 上方導航 (Navigation) * 側邊欄 (Sidebar) * 內容 (Content) 2-6
* 註腳 (Footer) - 規劃頁面的主要結構 * 開新檔 oscar2-1.html, 輸入以下內容 : <!DOCTYPE html> <html> <head> <title> 獎者不是...</title> <meta charset=utf-8> <link rel=stylesheet href=css/normalize.css> <link rel=stylesheet href=css/oscar2-1.css> </head> <body> <!-- the wrapper --> <div id=wrapper> <!-- the header and navigation --> <div id=header> <p> 得獎者不是...</p> <div id=navigation> <ul> <li><a href=#> 為什麼?</a></li> <li><a href=#> 劇情簡介 </a></li> <li><a href=#> 照片 </a></li> <li><a href=#> 影片 </a></li> <li><a href=#> 引用 </a></li> <li><a href=#> 小考 </a></li> </ul> <!-- the sidebar --> <div id=sidebar> <p> 無名英雄...</p> <p> 言過其實的廢話 </p> <!-- the content --> <div id=content> <p> 每年我觀賞奧斯卡金像獎頒獎典禮時, 都覺得很生氣...</p> <p> 像金剛 紅磨坊 慕尼黑等電影都得獎, 但真正的電影英雄卻都沒得獎, 一點也沒有好萊塢精神, 不是嗎?</p> <p> 在這裡, 我們要將事情導正 </p> <p> 這些才應該贏得獎項 <span>»</span></p> <!-- the footer --> <div id=footer> <p> 注意, 我們的意見是絕對正確的, 你們是錯的, 即使你們認為自己正確 這是事實, 接受吧 </p> </body> </html> * 建立 css 目錄, 所有 css 檔案均存放在該目錄 * Normalize CSS: # 各種瀏覽器均有自己的初始設定, 會使同一個 HTML 呈現不同結果 # Normalize.css 重新設定, 讓各個瀏覽器均呈現一致的結果 * 由設計圖看出 2-7
# header 及 footer 的影像都是 940px 寬, 左右邊界 (margin) 各為 10px # sidebar 為 220px 寬, 左右 margin 各為 10px # content 為 700px 寬, 左右 margin 各為 10px - 開新檔 oscar2-1.css, 輸入以下內容以設定各個結構區塊之特性, 並上色以資識別 : #wrapper { margin-right: auto; margin-left: auto; width: 960px; #header { margin-right: 10px; margin-left: 10px; width: 940px; background-color: #779307; #navigation { padding-bottom: 25px; margin-top: 26px; margin-left: -10px; padding-right: 10px; padding-left: 10px; width: 940px; #navigation ul li { display: inline-block; #navigation ul li a { height: 42px; line-height: 42px; margin-right: 25px; text-decoration: none; font-size: 27px; color: black; #sidebar { margin-top: 58px; padding-right: 10px; margin-right: 10px; margin-left: 10px; float: left; width: 220px; border-right-color: #e8e8e8; border-right-style: solid; border-right-width: 2px; background-color: #fe9c00; #content { margin-top: 58px margin-right: 10px; float: right; width: 698px; background-color: #dedede; #footer { margin-top: 20px; margin-right: 10px; margin-left: 10px; float: left; clear: both; width: 940px; background-color: #663300; color: white; * 視域寬度 >960px 如下圖, 但縮減瀏覽器寬度 (<960px) 會造成右邊內容被截斷 - 影像繪製 : 影像應該越經濟越好 * 頁面上下方的旗幟不應該全部繪製, 而應該畫一個基礎單元然後重複背景圖 ( 如右下圖 ), 且利用 margin 及 padding 加高 header 與 footer, 將 oscar2-1.css 另存新檔為 oscar2-2.css, 並如下修改 : #header { background-position: 0 top; background-repeat: repeat-x; background-image: url(../img/buntingfw.png); #footer { border-top: 4px double #bfbfbf; padding-top: 33px; padding-bottom: 43px; background-position: 0 bottom; background-repeat: repeat-x; 2-8
background-image: url(../img/buntingfwinvert.png); * 將 oscar2-1.html 另存新檔為 oscar2-2.html, 將連結改為 <link rel=stylesheet href=css/oscar2-2.css>, 結果如右圖 - 設定各類字型 圖片效果 * 設定 得獎者不是 字眼 # 將 oscar2-2.html 另存新檔為 oscar2-3.html, 並將連結改為 <link rel=stylesheet href=css/oscar2-3.css> # 設定文字連結, 給予一個 <div id=logo>, 不是... 字眼再以 <span> 標籤包起 : <a href=/><div id=logo> 得獎者 <span> 不是...</span></a> # 將 oscar2-2.css 另存新檔為 oscar2-3.css, 並加上 : #logo { display: block; padding-top: 75px; color: #0d0c0c; font-size: 48px; #logo span { color: #dfdada; * 上方導航按鈕設定適當的樣式 #navigation {... border-bottom-color: #bfbfbf; border-bottom-style: double; border-bottom-width: 4px; #navigation ul { width: 100%; #navigation ul li {... text-align: center; * 設定左側欄 : # 在 HTML 加入圖片 <div id=sidebar> <h1> 無名英雄...</h1> <a href=#><img src=img/midnightrun.jpg width=99 height=135></a> <a href=#><img src=img/wyattearp.jpg width=99 height=135></a> <br> <h1> 言過其實的廢話 </h1> <a href=#><img src=img/moulinrouge.jpg width=99 height=135></a> <a href=#><img src=img/kingkong.jpg width=99 height=135></a> # CSS 加上以下資料 #sidebar h1 { font-size: 1.2em; * 內容設定 : 2-9
# 在 HTML 加入影像 文字環繞 設定字型效果 <div id=content> <img class=oscarmain src=img/oscar.png width=202 height=531> <h1> 每年 <span> 我觀賞奧斯卡金像獎頒獎典禮時, 都覺得很生氣...</span></h1> <p> 像 <b> 金剛 </b> <b> 紅磨坊 </b> <b> 慕尼黑 </b> 等電影都得獎, 但真正的電影英雄卻都沒得獎, 一點也沒有好萊塢精神, 不是嗎?</p> <p> 在這裡, 我們要將事情導正 </p> <p><a href=#> 這些才應該贏得獎項 <span>»</span></a></p> # CSS 加入 : #content h1 { font-size: 34px; #content h1 span { display: block; line-height: 40px; color: #757474; font-size: 28px;.oscarMain { float: left; margin-top: -28px; width: 202px; # 結果如右圖 * 當視域寬度小於 960px 時, 右方內容會被截斷 (4) 防止行動瀏覽器自動調整頁面大小 - 覆蓋預設之視域設定 * ios 與 Android 瀏覽器均奠基在 Webkit 技術上, 這些瀏覽器 ( 以及 Opera) 允許使用特定的 <meta> 視域元素 ( 置於 <head> 元素中 ) 來覆蓋原先的設定, 例如 : # 可設定固定寬度或者縮放的比例 : 設定視域寬度為裝置的寬度, 而且頁面以 2 倍大小呈現 <meta name=viewport content="initial-scale=2.0, width=device-width"> # 可設定使用者可縮放的程度 : 設定縮放範圍為 0.5 到 3 倍 <meta name=viewport content="width=device-width, maximum-scale=3, minimum-scale=0.5"> # 可禁止縮放 : <meta name=viewport content="initial-scale=1.0, user-scalable=no"> # 註 : 亦可將 <meta> 設定以下列格式放在 CSS 檔中, 而不要放在 HTML 檔中 @viewport { width: 320px; - 對於不同視域寬度固定網頁設計 * 將 oscar2-3.css 另存新檔為 oscar2-4.css, 並加入媒體查詢指令 : # 如果視域寬度不大於 768 像素,wrapper header footer 及 navigation 均設為 768 像素寬 @media screen and (max-width: 768px) { #wrapper, #header, #footer, #navigation { width: 768px; margin: 0px; 2-10
# 將 oscar2-3.html 另存新檔為 oscar2-4.html, 並將連結改為 <link rel=stylesheet href=css/oscar2-4.css>, # 透過 <meta> 元素控制頁面呈現尺寸後, 所有瀏覽器均不會再自動縮放頁面, 因此可以將頁面設定固定下來, 在 HTML 的 <head> 元素中加入以下 : <meta name=viewport content="initial-scale=1.0, width=device-width, user-scalable=no"> # 刪除各區塊背景顏色, 刪除 #footer 中的文字顏色設定 (color: white;), 結果如圖 (a) (a) (b) (c) * 目前 navigation 仍延展到頁面外, 且 content 因太寬而流動到 sidebar 之下, 在 CSS 的 @media 元素中加入 : @media screen and (max-width: 768px) {... #content, #sidebar { padding-right: 10px; padding-left: 10px; width: 728px; # 結果如上圖 (b),sidebar 及 content 均填滿整個頁面, 左右 padding 也都看來適當 - 回應式設計的理念 : 內容應該最早出現 * 因為行動裝置的視域通常較小, 應該讓重要的資訊先出現, 因此, 在 HTML 中 content 應放在 sidebar 之前 * 即使調換了 content 與 sidebar 的順序, 因為有 float: left 與 float: right 的設定, 在寬視域狀況下,sidebar 仍在左邊而 content 在右邊, 結果如上圖 (c) - 修改 sidebar 樣式, 讓影像在小視域下改為左右並列 * 在 HTML 的 sidebar 區塊中再加入類別 # 主類別 :sideblock # 子類別 :unsung ( 無名英雄 ) 與 overhyped ( 言過其實 ) <div id=sidebar> <div class="sideblock unsung"> <h1> 無名英雄...</h1> <a..."><img...></a> <a...><img...></a> <div class="sideblock overhyped"> <h1> 言過其實的廢話 </h1> <a...><img...></a> <a...><img...></a> 2-11
* @media 樣式中再增加其他設定,@media 最後版本及結果圖如下 : @media screen and (max-width: 768px) { #wrapper, #header, #footer, #navigation { width: 768px; margin: 0px; #logo { text-align: center; #navigation { text-align: center; background-image: none; border-top-color: #bfbfbf; border-top-style: double; border-top-width: 4px; padding-top: 20px; #navigation ul li a { background-color: #dedede; line-height: 60px; font-size: 40px; #content, #sidebar { margin-top: 20px; padding-right: 10px; padding-left: 10px; width: 728px;.oscarMain { margin-right: 30px; margin-top: 0px; width: 150jpx; height: 394px; #sidebar { border-right: none; border-top: 2px solid #e8e8e8; padding-top: 20px; margin-bottom: 20px;.sideBlock { width: 46%; float: left;.overhyped { margin-top: 0px; margin-left: 50px; - 媒體查詢機制解決了所有問題? 沒有! * 目前媒體查詢所設定的視域門檻還不夠, 低於 768px 視域會有截斷情形 * 在 768px ~ 960px 之間的視域也會有截斷情形 * 問題原因 : 當視域到達媒體查詢門檻, 頁面佈局會變化, 但當視域在媒體查詢的門檻之間, 資料佈局是維持固定的 * 解決方案 : 將固定的佈局改為流動的佈局 2-12