做爲一個前端開發者,響應式網站開發是必備技能之一。響應式有它的很好的優勢,也有它必定的缺點。這就須要咱們在開發的時候作出取捨。對於內容較少、主要爲展現類網站,故採用響應式;對於內容多,管理類的網站採用分開開發的方式,不一樣設備採用不一樣的一套代碼。本文會主要探討響應式佈局原理和技巧,並結合實例來加深印象。javascript
咱們不少人其實把這響應式和自適應兩種網站當成一回事,但事實上這兩種網站的佈局方式是有必定的區別的。咱們能夠來看看這兩種方法的概念以及分別對應解決的問題。css
響應式佈局就是一個網站可以兼容多個終端,能夠根據屏幕的大小自動調整頁面的的展現方式以及佈局,咱們不用爲每個終端作一個特定的版本。響應式網站的幾個標誌:html
自適應佈局是指網頁可以在不一樣大小的終端設備上自行適應顯示,也就是讓一個網站在不一樣大小的設備上顯示同同樣的頁面,讓同一個頁面適應不一樣大小屏幕,根據屏幕的大小,自動縮放。自適應佈局的幾個標誌:前端
總的來講,這兩種方式的原來是類似的,都是先檢測設備,根據不一樣的設備採用不一樣的CSS。那開發中咱們該如何去選擇?這就要結合響應式與自適應的優缺點來看。java
響應式佈局的優勢:
一、靈活性強;二、可以快捷解決多設備顯示適用問題。css3
缺點:
一、效率較低,兼容各設備工做量大;二、代碼較爲累贅,加載時間會加長;三、在必定程度上改變了網站原有的佈局結構。git
自適應佈局的優勢:
一、對網站複雜程度兼容更大;二、代碼更高效;三、測試和運營都相對容易和精準。github
缺點:
一、同一個網站須要爲不一樣的設備開發不一樣的頁面,增長的開發的成本。web
上面兩種方法各有本身的優缺點,因此咱們在開發的時候,要從實際的項目出發。對於頁面不是太複雜的狀況下,咱們能夠利用響應式佈局;而對於頁面中信息較多,佈局較爲複雜的狀況,咱們能夠採用自適應佈局的方式。瀏覽器
介紹完基本的概念,咱們來看看響應式佈局的基本步驟,主要分爲下面幾步:
1.設置meta標籤
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
2.使用@Media查詢來設置樣式,這是響應式佈局的核心
@media screen and (max-width: 1920px) { ... }
3.設置佈局分界點,即經過設置多種視圖寬度樣式來控制頁面佈局
@media screen and (max-width: 1920px) { ... } @media screen and (max-width: 1700px) { ... }
其實仍是很簡單的,就是在適配的時候稍微有點點繁瑣。
對於@Media查詢的分界點,這個能夠根據本身的項目來調整,設置合適本身項目的佈局分界點。在設置分界點時,要注意前後順序,當使用max-width
數值大的在前面,數值小的在後面;當使用min-width
時,數值小的放前面,數值大的放後面。下面列出了我在項目開發時所設置的部分佈局分界點:
@media screen and (max-width: 1920px) { ... } @media screen and (max-width: 1700px) { ... } @media screen and (max-width: 1600px) { ... } @media screen and (max-width: 1440px) { ... } @media screen and (max-width: 1280px) { ... } @media screen and (min-width: 992px) and (max-width: 1200px) { ... } @media screen and (min-width: 768px) and (max-width: 991px) { ... } @media screen and (max-width: 767px) { ... }
那咱們何時用min-width
,何時用max-width
呢?一般來講,若是是移動端優先,則用min-width
;若是是PC端優先,則用max-width
。
熟悉經常使用的佈局單位仍是很重要的,經常使用的佈局單位包括像素(px
),百分比(%
),em
,rem
,vw/vh
。咱們能夠合理的運用這些佈局解決方案,來提升咱們開發時的效率和質量。
像素是網頁佈局的基礎,一個像素表示計算機屏幕所能顯示的最小區域。像素分爲兩種類型:css像素和物理像素。二者區別以下:
css像素:爲web開發者提供,在css中使用的一個抽象單位;
物理像素:只與設備的硬件密度有關,任何設備的物理像素都是固定的。
當瀏覽器的寬度或者高度發生變化時,經過百分比單位可使得瀏覽器中的組件的寬和高隨着瀏覽器的變化而變化,從而實現響應式的效果。通常咱們的直觀理解都會認爲子元素的百分比徹底相對於直接父元素,這種理解沒問題,好比height
和width
屬性。可是在css的盒模型中不止有height
和width
屬性,還有padding
、border
、margin
等屬性,因此這就值得咱們去具體分析一下。
咱們先寫好html代碼,而後經過不一樣的css代碼來看看會呈現出什麼樣的狀況:
<div class="parent"> <div class="child">子元素</div> </div>
當子元素的height
和width
使用百分比時,是相對於直接父元素的height
和width
進行變化的。
.parent{ width: 200px; height: 200px; background: #aaaaaa; } .child{ width: 50%; height: 50%; background: red; }
子元素的top
和bottom
若是設置百分比,則相對於直接非static定位(默認定位)的父元素的高度;
子元素的left
和right
若是設置百分比,則相對於直接非static定位(默認定位的)父元素的寬度。
.parent{ width: 200px; height: 200px; background: #aaaaaa; position: relative; } .child{ width: 50%; height: 50%; background: red; position: absolute; top: 50%; left: 50%; }
子元素的padding
若是設置百分比,不管是垂直方向或者是水平方向,都相對於直接父親元素的width
,而與父元素的height
無關。
.parent{ width: 300px; height: 400px; background: #aaaaaa; } .child{ width: 50%; height: 50%; background: red; padding-top: 20%; padding-left: 20%; }
打開控制檯,查看子元素,咱們能夠看見padding-top
和padding-left
都爲父元素width
的20% ——60px:
子元素的margin
和padding
是同樣的,子元素的margin
若是設置成百分比,不管是垂直方向仍是水平方向,都相對於直接父元素的width
。
border-radius
設置爲百分比則是相對於自身的寬度
.parent{ width: 200px; height: 200px; background: #aaaaaa; } .child{ width: 50%; height: 50%; background: red; border-radius: 50%; }
em
和rem
相對於px
更具靈活性,他們都是相對長度單位,而他們之間的區別能夠用一句話來歸納:em
相對於父元素,rem
相對於根元素。em
是相對於父元素的font-size
,rem
則是相對於html元素的font-size
。
vw/vh
是與視圖窗口有關的單位,vw
表示相對於視圖窗口的寬度,vh
表示相對於視圖窗口高度,除了vw
和vh
外,還有vmin
和vmax
兩個相關的單位。
單位 | 含義 |
---|---|
vw | 相對於視窗的寬度,視窗寬度是100vw |
vh | 相對於視窗的高度,視窗高度是100vh |
vmin | vw和vh中的較小值 |
vmax | vw和vh中的較大值 |
這個單位和百分比很相似,可是仍是有區別的:
單位 | 含義 |
---|---|
% | 大部分相對於祖先元素,也有相對於自身的狀況好比(border-radius、translate等) |
vw/vm | 相對於視窗的尺寸 |
好了,說了這麼多,咱們如今能夠結合上面的理論知識,來完成一個響應式佈局的demo。下面我會貼出部分代碼來說一些思路,完整的代碼放在了個人github上面。
首先,咱們進行總體的佈局,這個demo主要分爲三部分:頭部、內容、底部,相似於簡單的企業官網。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>響應式佈局實踐</title> <link rel="stylesheet" href="./css/index.css"> </head> <body> <div id="root"> <!-- 頭部 --> <header> <div class="header-box"> <div class="logo"> logo </div> <nav class="main-nav"> <ul class="nav-list"> <li id="nav-item" class="main-nav-item"> <ul class="nav-main-list"> <li class="list-item">首頁</li> <li class="list-item">文章</li> <li class="list-item">論壇</li> <li class="list-item">娛樂</li> <li class="list-item">聯繫</li> </ul> </li> <li class="main-nav-login"> <div class="login-box">登陸 | 註冊</div> </li> </ul> </nav> </div> </header> <!-- 內容 --> <div id="container"> <div class="container-header"></div> <div class="content"> <!-- 內容一--> <div class="content-box content-box1"> <div class="content-box1-text"></div> <div class="content-box1-img"> <div class="img-radius"></div> </div> </div> <!-- 內容二--> <div class="content-box content-box2"> <div class="content-box2-text"></div> <div class="content-box2-text"></div> <div class="content-box2-text"></div> </div> <!-- 內容三--> <div class="content-box content-box3"> <div class="content-box3-text"></div> <div class="content-box3-text"></div> <div class="content-box3-text"></div> <div class="content-box3-text"></div> <div class="content-box3-text"></div> <div class="content-box3-text"></div> </div> </div> </div> <!-- 底部 --> <footer></footer> </div> </body> </html>
在這個demo中,最初的css代碼是在1920px
下進行編寫的,這個就是咱們的初始樣式。
初始樣式代碼比較長,就不貼在文章裏面了,看這裏>>> index.css
咱們先來看看初始的效果:
在實際開發的時候,有些模塊中包含的內容,使得這些模塊不能無限制的進行縮小。因此在index.css的初始佈局中,咱們對一些模塊的大小進行了限制,設置了min-width
。
前面咱們提到,佈局分界點是要根據實際的項目來進行劃分的,我針對這個項目進行了如下的劃分,你們也能夠根據本身的想法來進行劃分。
咱們先看看把寬度調到1201px
時會出現什麼狀況:
咱們能夠看見部分模塊超出了父元素的寬度,使得頁面變得良莠不齊了,因此咱們就要對佈局進行調整了:
@media screen and (max-width: 1280px) { /* 內容一 */ .content-box1{ flex-wrap: wrap; height: 650px; } .content-box1-text{ width: 90%; margin: 0 auto; } .content-box1-img{ display: flex; align-items: center; margin: 0 auto; } }
再來看佈局狀況:
這時候出現的狀況:
咱們看到,佈局又混亂了,而後咱們須要繼續調整佈局:
@media screen and (min-width: 992px) and (max-width: 1200px) { /* 內容二 */ .content-box2{ height: 400px; } .content-box2-text{ height: 300px; min-width: 200px; } /* 內容三 */ .content-box3{ justify-content: space-around; } }
再來看看佈局狀況:
在這個分界點時,一樣會出現佈局問題,因此要進一步實現調整,由於是重複操做,這裏就不貼圖和代碼了。咱們能夠重點看看下面的適配。
在boostrap的柵格系統中,把<768px
的屏幕歸爲手機。咱們也能夠以此做爲參考。此時佈局調整不只僅是內容的調整,咱們的導航欄也要發生改變——由橫向導航欄變爲點擊出現的縱向導航欄(具體需求,具體實現,這裏只是提出一種廣泛的變換方法)。以下圖所示:
要想實現上圖中的效果咱們須要作哪些事情呢?
咱們先在類名爲nav-list
的末尾加入如下HTML代碼:
... <li class="phone-show"> <div id="nav-btn" class="nav-btn"> <span></span> <span></span> <span></span> </div> </li> ...
而後對按鈕樣式進行美化:
@media screen and (max-width: 767px){ ... .phone-show{ display: block; height: 60px; width: 60px; } .nav-btn{ height: 100%; width: 100%; display: flex; flex-direction: column; flex-wrap: wrap; justify-content: space-around; } .nav-btn span{ display: inline-block; height: 10px; width: 60px; background: coral; } }
看看效果:
這個咱們能夠巧妙的運用一個相對定位和絕對定位的關係實現導航條樣式和位置的修改:
@media screen and (max-width: 767px){ .header-box{ position: relative; } ... /* 手機端樣式 */ .main-nav-item{ display: none; position: absolute; width: 10rem; right: 0; top: 8rem; border-radius: 0 0 .5rem .5rem; } .nav-main-list{ width: 100%; background: #ffffff; display: flex; flex-direction: row; flex-wrap: wrap; border-radius: 0 0 .5rem .5rem; } .list-item{ width: 100%; margin: 0 1rem; border-bottom: 1px solid #eeeeee; } }
看看效果:
利用js來控制切換的思路很簡單,咱們在網頁打開時,先把導航隱藏掉,而後定義一個變量hide
,初始值爲true
,點擊按鈕時進行判斷:若是hide
值爲true
,則讓導航顯示;反之隱藏。
let btn = document.getElementById("nav-btn"); let nav = document.getElementById("nav-item"); let hide = true; btn.addEventListener('click', function () { if (hide){ nav.style.display = "block"; hide = false; } else { nav.style.display = "none"; hide = true; } });
最後再進行一些細節方面的調整,咱們的響應式佈局demo就初步完成了。咱們在平常的開發的時候,通常來說不會這麼簡單,因此仍是也根據實際狀況去進行調整,以知足實際的需求。
完整demo點擊這裏——demo地址
自適應和響應式的區別有哪些你知道嗎?
響應式和自適應有什麼區別?
響應式佈局的經常使用解決方案對比(媒體查詢、百分比、rem和vw/vh)
文中如有不許確或錯誤的地方,歡迎指出~