做为一个前端开发者,响应式网站开发是必备技能之一。响应式有它的很好的优势,也有它必定的缺点。这就须要咱们在开发的时候作出取舍。对于内容较少、主要为展现类网站,故采用响应式;对于内容多,管理类的网站采用分开开发的方式,不一样设备采用不一样的一套代码。本文会主要探讨响应式布局原理和技巧,并结合实例来加深印象。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)
文中如有不许确或错误的地方,欢迎指出~