响应式布局与媒体查询
1、响应式布局
响应式 web 设计会让您的网页在所有设备上看起来都不错,响应式 web 设计仅使用 HTML 和 CSS,响应式 web 设计并不是程序或 JavaScrip。简单来说就是为了让你的网页无论是在PC端抑或是手机浏览器端或者平板上都能够以一种比较合理优美的方式进行展示。
1.1 关于视口
视口(viewport)是用户在网页上的可见区域,视口随设备而异,在移动电话上会比在计算机屏幕上更小。
设置视口:在HTML5中的meta标签中使用添加如下属性:
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
width=device-width
部分将页面的宽度设置为跟随设备的屏幕宽度(视设备而定)
initial-scale=1.0
用于当浏览器首次加载页面时,设置页面初始缩放级别。
1.2 使用响应式布局的注意事项
1、根据不同设备的滚动习惯设置响应的响应式布局。
- 用户习惯在台式机和移动设备上垂直滚动网站,而不是水平滚动,
2、请勿使用较大的固定宽度元素
- 例如,如果图像的宽度大于视口的宽度,则可能导致视口水平滚动。请务必调整此内容以适合视口的宽度。
3、不要让内容依赖于特定的视口宽度来呈现好的效果
- 由于以 CSS 像素计的屏幕尺寸和宽度在设备之间变化很大,因此内容不应依赖于特定的视口宽度来呈现良好的效果。
4、 使用 CSS 媒体查询
为小屏幕和大屏幕应用不同的样式
- 为页面元素设置较大的 CSS 绝对宽度将导致该元素对于较小设备上的视口太宽。而是应该考虑使用相对宽度值,例如 width: 100%。另外,要小心使用较大的绝对定位值,这可能会导致元素滑落到小型设备的视口之外。
2、实现响应式布局的方式
2.1 响应式网格视图(栅格布局)
网格视图是基于grid布局的,它将页面分割为几列,某个模块需要多少列的宽度就给它分配对应的列数。通常响应式网格视图有12列,总宽度设置为100%,也就是总视图宽度,并且在调整窗口大小时会进行收缩和扩大。
构建响应式网格布局
首先去报所有的HTML元素中的属性的box-sizing:border-box
。这样可以保证元素的总宽度和高度中包括内边距(填充)和边框。
* {
box-sizing: border-box;
}
例如,我们设置两列,分别占据视图宽度的25%和75%。
如图:
.menu {
width: 25%;
float: left;
}
.main {
width: 75%;
float: left;
}
如果网页只包含两列,那么以上就可以满足了,但如果网页内容稍微有点多,那么哦我们就可以使用拥有12列的响应式网格布局,来更好的控制网页,每一列的宽度为:100% / 12列 = 8.33%。
然后,我们为每一列了创建一个类,在需要使用多少的列时就应用对应宽度的列:
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
/* 将所有元素设置为边框盒子 */
* {
box-sizing: border-box;
}
/* 清除浮动 */
.row::after {
content: "";
clear: both;
display: table;
}
/* 属性值选择器匹配所有class值中包括"col-"的元素,将其设置为左浮动 */
[class*="col-"] {
float: left;
padding: 15px;
}
.col-1 { width: 8.33%;}
.col-2 { width: 16.66%;}
.col-3 { width: 25%;}
.col-4 { width: 33.33%;}
.col-5 { width: 41.66%;}
.col-6 { width: 50%;}
.col-7 { width: 58.33%;}
.col-8 { width: 66.66%;}
.col-9 { width: 75%;}
.col-10 { width: 83.33%;}
.col-11 { width: 91.66%;}
.col-12 { width: 100%;}
html {font-family: "Lucida Sans", sans-serif;}
.header {
background-color: #e0bbf3;
color: #ffffff;
padding: 15px;
}
.menu ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.menu li {
padding: 8px;
margin-bottom: 7px;
background-color: #72c8e8;
color: #ffffff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.menu li:hover {
background-color: #72d7f9;
}
</style>
</head>
<body>
<div class="header">
<h1>Shanghai</h1>
</div>
<div class="row">
<div class="col-3 menu">
<ul>
<li>The Flight</li>
<li>The City</li>
<li>The Island</li>
<li>The Food</li>
</ul>
</div>
<div class="col-9">
<h1>The City</h1>
<p>
Shanghai is one of the four direct-administered municipalities of the
People's Republic of China. Welcome to Shanghai!
</p>
<p>可以通过调整浏览器窗口的大小,来查看内容如何响应调整大小。</p>
</div>
</div>
</body>
</html>
大屏幕下
小屏幕下
缺点:将浏览器窗口调整为非常小的宽度时,网格布局实现的网页看起来并不理想,他会把所有内容全部挤在一起。
2.2 媒体查询
媒体查询可以让我们根据设备显示器的特性(如视口宽度、屏幕比例、设备方向:横向或纵向)为其设定CSS样式,媒体查询由媒体类型和一个或多个检测媒体特性的条件表达式组成。媒体查询中可用于检测的媒体特性有 width 、 height 和 color (等)。使用媒体查询,可以在不改变页面内容的情况下,为特定的一些输出设备定制显示效果。
媒体查询与弹性和布局的使用情况:
媒体查询:当页面的结构发生变化的话最好使用媒体查询。
弹性盒:如果只是宽高的变化,尽量使用弹性盒。
2.2.1 使用方法
媒体查询的格式:
@media 媒体类型 and (媒体特性){你的样式}
<!-- link元素中的CSS媒体查询 -->
<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />
<!-- 样式表中的CSS媒体查询 -->
<style>
@media (max-width: 600px) {
.class {
display: none;
}
}
</style>
使用Media Queries必须要使用“@media”开头,然后指定媒体类型(也可以称为设备类型),随后是指定媒体特性(也可以称之为设备特性) ,中间用and连接。媒体特性的书写方式和样式的书写方式非常相似,主要分为两个部分,第一个部分指的是媒体特性,第二部分为媒体特性所指定的值,而且这两个部分之间使用冒号分隔。
与CSS属性不同的是,媒体特性是通过min/max来表示大于等于或小于做为逻辑判断,而不是使用小于(<)和大于(>)这样的符号来判断。
2.2.2 媒体类型(media-type)
all | 所有媒体(默认值) |
---|---|
screen | 彩色屏幕 |
打印预览 |
2.2.3 媒体属性
width | 表示视口宽度(可加max min前缀,表示范围) |
---|---|
height | 表示视口高度(可加max min前缀,表示范围) |
device-width | 设备宽度(可加max min前缀)media queries 4中弃用 |
orientation | portrait竖屏/landscape横屏 |
… | 其他请看官网 |
max-width最大宽度
作用:“max-width”是媒体特性中最常用的一个特性,其意思是指媒体类型小于或等于指定的宽度时,样式生效。
例如:
@media screen and (max-width:580px){
body {
background-color: red;
}
}
解释:当屏幕小于或等于580px时,页面的背景颜色变为红色。
min-width 最小宽度
作用:与“max-width”相反,指的是媒体类型大于或等于指定宽度时,样式生效。
@media screen and (min-width:900px){
.wrapper{width: 980px;}
}
解释:当屏幕大于或等于900px时,容器“.wrapper”的宽度为980px。
device-width 设备屏幕的输出宽度
在智能设备上,例如iPhone、iPad等,还可以根据屏幕设备的尺寸来设置相应的样式(或者调用相应的样式文件)。同样的,对于屏幕设备同样可以使用“min/max”对应参数,如“min-device-width”或者“max-device-width”。
<link rel="stylesheet" media="screen and (max-device-width:480px)" href="iphone.css" />
解释:指的是“iphone.css”样式适用于最大设备宽度为480px。这里的“max-device-width”所指的是设备的实际分辨率,也就是指可视面积分辨率。
多个媒体特性使用
多个媒体特性同时使用时可以用and连接,例如:当屏幕在600px~900px之间时,body的背景色渲染为“blue”
@media screen and (min-width:600px) and (max-width:900px){
body {background-color:blue;}
}
逗号分隔列表
当使用媒体查询的逗号分隔列表时,如果列表中的任意一个媒体查询为true,样式表都会被运用。在逗号分隔列表中的每个媒体查询都被作为独立查询对待,运用到一个媒体查询上的任何操作符都不影响其它的,可以理解为OR的意思。例如:
@media (min-width: 700px), handheld and (orientation: landscape) { ... }
表示的是应用一套样式在宽度大于等于700px的设备上,或者采用横向模式的便捷式设备上。
比较典型的设备断点:
/* 超小型设备(电话,600px 及以下) */
@media only screen and (max-width: 600px) {...}
/* 小型设备(纵向平板电脑和大型手机,600 像素及以上) */
@media only screen and (min-width: 600px) {...}
/* 中型设备(横向平板电脑,768 像素及以上) */
@media only screen and (min-width: 768px) {...}
/* 大型设备(笔记本电脑/台式机,992px 及以上) */
@media only screen and (min-width: 992px) {...}
/* 超大型设备(大型笔记本电脑和台式机,1200px 及以上) */
@media only screen and (min-width: 1200px) {...}
2.2.4 关键字的使用
not、only 和 and 关键字的含义:
not:not 关键字反正整个媒体查询的含义。
only:only 关键字可防止旧版浏览器应用指定的样式,这些浏览器不支持带媒体特性的媒体查询。它对现代浏览器没有影响。
and:and 关键字将媒体特性与媒体类型或其他媒体特性组合在一起。
它们都是可选的。但是,如果使用 not 或 only,则还必须指定媒体类型。
not关键字
关键词“not”是用来排除某种制定的媒体类型,也就是用来排除符合表达式的设备。换句话说,not关键词表示对后面的表达式执行取反操作,如:
@media not print and (max-width: 1200px){样式代码}
解释:样式代码将被使用在除打印设备和设备宽度小于1200px下所有设备中
only关键字
作用:only操作符表示仅在媒体查询匹配成功时应用指定样式(可以通过它让选中的样式在老式浏览器中不被应用)
例如:
@media only screen and (max-width:1000px){...}
解释:在老式浏览器中被解析为media=“only”,因为没有一个叫only的设备,所以实际上老式浏览器不会应用样式。
再例如:
@media screen and (max-width:1000px){...}
解释:上面这行代码,在老式浏览器中被解析为media=“screen”,它把后面的逻辑表达式忽略了。所以老式浏览器会应用样式。所以,在使用媒体查询时,only最好不要忽略。
2.2.5 根据不同的媒体使用不同的样式表
<link rel="stylesheet" media="screen and (min-width: 900px)" href="widescreen.css">
<link rel="stylesheet" media="screen and (max-width: 600px)" href="smallscreen.css">
2.2.6 案例练习
1、根据屏幕宽度不同显示不同背景颜色
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<style>
/* 正常打开网页时的页面状态 */
body {
background-color: #9af7bc;
color: white;
}
/* 媒体查询 */
/* 屏幕宽度小于992px时,变为蓝色 */
@media screen and (max-width: 992px) {
body {
background-color: rgb(160, 214, 234);
}
}
/* 屏幕宽度小于600px时,变为粉红色 */
@media screen and (max-width: 600px) {
body {
background-color: pink;
}
}
</style>
</head>
<body>
<div>请尝试扩大缩小浏览器窗口来查看页面效果</div>
</body>
</html>
2、不同宽度屏幕下菜单栏的展示
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<style>
* {
margin: 0;
}
body {
background-color: rgb(210, 247, 248);
color: white;
}
.tabNavs {
background-color: #90ebee;
}
.tabNavs > a {
display: inline-block;
text-decoration: none;
text-align: center;
color: white;
padding: 10px 20px;
border: 2px solid white;
}
.tabNavs > a:hover{
background-color: #70a4a7;
cursor: pointer;
}
.main {
height: 300px;
border: 1px solid rgb(151, 141, 141);
color: black;
}
@media screen and (max-width:600px) {
.tabNavs>a{
display: block;
}
}
</style>
</head>
<body>
<div>
<!-- 导航栏 -->
<div class="tabNavs">
<a href="#">Home</a>
<a href="#">News</a>
<a href="#">Contact</a>
<a href="#">Information</a>
<a href="#">About</a>
</div>
<!-- 主体部分 -->
<div>
<div class="main">什么玩意啊,找不到工作,天理难容</div>
</div>
</div>
</body>
</html>
效果展示:
3、列布局实现弹性图片布局
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<style>
/* 边框盒子 */
* {
box-sizing: border-box;
margin: 0;
}
/* 开启flex布局 */
.allColumn {
display: flex;
flex-wrap: wrap;
padding: 5px;
}
/* 默认情况下排成四列 */
.column {
flex: 25%;
max-width: 25%;
}
/* 图片 */
.column img {
width: 100%;
padding: 5px;
vertical-align: middle;
}
/* 当视图宽度小于922px时,变为两列 */
@media only screen and (max-width: 922px) {
.column {
flex: 50%;
max-width: 50%;
}
}
/* 当视图宽度小于600px时变为一列 */
@media only screen and (max-width: 600px) {
.column {
flex: 100%;
max-width: 100%;
}
}
</style>
</head>
<body>
<div class="allColumn">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
<script>
// 动态生成一定数量的图片
// window.onload = function () {
// let columns = document.getElementsByClassName("column");
// columns = Array.from(columns);
// columns.forEach((item, index) => {
// if (index % 2 == 0) {
// for (var i = 0; i < 8; i++) {
// var img = document.createElement("img");
// img.src = "./images/beauty1.webp";
// item.appendChild(img);
// }
// } else {
// for (var i = 0; i < 8; i++) {
// var img = document.createElement("img");
// img.src = "./images/beauty2.webp";
// item.appendChild(img);
// }
// }
// });
// };
// 第一步优化,将重复代码抽离出来进行封装
// 创建img节点,指定图片url
function createImages(item, num, url) {
for (var i = 0; i < num; i++) {
var img = document.createElement("img");
img.src = url;
item.appendChild(img);
}
}
// 第二步优化,使用promise实现图片异步加载
// 将异步操作封装到promise中
function loadImage(url) {
return new Promise((resolve, reject) => {
let img = new Image();
img.onload = function () {
resolve(url);
};
img.onerror = function () {
reject(url);
};
img.src = url;
});
}
async function loadImages() {
try {
// 实现并行加载,提高性能
await Promise.all([
loadImage("./images/beauty1.webp"),
loadImage("./images/beauty2.webp"),
]);
// 获取列节点
let columns = document.querySelectorAll(".column");
columns.forEach((item, index) => {
if (index % 2 == 0) {
createImages(item, 8, "./images/beauty1.webp");
} else {
createImages(item, 8, "./images/beauty2.webp");
}
});
} catch (error) {
console.error(error);
}
}
// 将事件监听添加到节点上,避免覆盖
window.addEventListener("load", loadImages);
</script>
</body>
</html>
效果展示:
大于992px时
小于
小于600时
4、媒体查询+flex实现一个兼容pc端和手机端的网站
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<style>
* {
box-sizing: border-box;
}
html,
body {
margin: 0px 0px;
}
.header {
padding: 60px;
text-align: center;
background-color: #94e8f7;
height: 230px;
}
/* 导航栏 */
.navBars {
background-color: grey;
display: flex;
}
.navBars > a {
text-align: center;
text-decoration: none;
color: white;
padding: 10px 20px;
}
.navBars > a:hover {
background-color: #cfd3d4;
}
/* 中间部分 */
.mainBody {
display: flex;
}
/* 侧边栏部分 */
.side {
flex: 30%;
background-color: #b4afaf;
padding: 20px;
}
/* 主体部分 */
.main {
flex: 70%;
padding: 20px;
}
/* 模拟照片 */
.photo {
width: 100%;
background-color: #d1d8d8;
padding: 20px;
}
/* 底部 */
.footer {
text-align: center;
padding: 10px;
background-color: #8d8888;
}
/* 当屏幕宽度小于600时,flex布局改变导航栏主轴方向 */
@media only screen and (max-width: 600px) {
.navBars,
.mainBody {
flex-direction: column;
}
}
</style>
</head>
<body>
<div>
<!-- 网站头部 -->
<div class="header">
<h1>我的网站</h1>
<p><b>这里是我的网站的详细信息,请往下看</b></p>
</div>
<!-- 导航栏 -->
<div class="navBars">
<a href="#">主页</a><a href="#">联系方式</a><a href="#">新闻</a
><a href="#">关于</a>
</div>
<!-- 中间 -->
<div class="mainBody">
<!-- 左边侧栏 -->
<div class="side">
<h2>关于我</h2>
<h5>我的照片</h5>
<div
class="photo"
style="height: 200px; text-align: center; line-height: 120px"
>
我的照片
</div>
<p>
关于我的一些信息关于我的一些信息关于我的一些信息关于我的一些信息关于我的一些信息。
</p>
<h2>更多我的文章</h2>
<p>下面是我的其他一些文章...</p>
<div class="photo">我的文章1</div>
<br />
<div class="photo">我的文章2</div>
<br />
<div class="photo">我的文章3</div>
</div>
<!-- 右边主体部分 -->
<div class="main">
<h2>文章标题</h2>
<h5>关键字 发布时间:2023-04-26</h5>
<div class="photo" style="height: 200px">图片信息</div>
<p>文章内容</p>
<p>
文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容
文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容
文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容
</p>
<hr />
<h2>文章标题</h2>
<h5>关键字 发布时间:2023-04-26</h5>
<div class="photo" style="height: 200px">图片信息</div>
<p>文章内容</p>
<p>
文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容
文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容
文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容
</p>
<br />
</div>
</div>
<div class="footer">
<h1>Footer</h1>
</div>
</div>
</body>
</html>
5、媒体查询+网格布局实现网站
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
/* 边框盒子 */
* {
box-sizing: border-box;
}
/* 清除浮动 */
.row::after {
content: "";
clear: both;
display: table;
}
/* 获取类名中包括col-的节点 */
[class*="col-"] {
float: left;
padding: 15px;
}
html {
font-family: "Lucida Sans", sans-serif;
}
.header {
background-color: #11cbe0;
color: #ffffff;
padding: 15px;
}
/* 左侧边栏 */
.menu ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.menu li {
padding: 8px;
margin-bottom: 7px;
background-color: #85c9e1;
color: #ffffff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.menu li:hover {
background-color: #0099cc;
}
/* 右侧边栏 */
.aside {
background-color: #69cdf1;
padding: 15px;
color: #ffffff;
text-align: center;
font-size: 14px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
/* 底部 */
.footer {
background-color: #788e97;
color: #ffffff;
text-align: center;
font-size: 12px;
padding: 15px;
}
/* 默认情况下(小于600px时)为100% */
[class*="col-"] {
width: 100%;
}
@media only screen and (min-width: 600px) {
/* 针对平板电脑: */
.col-s-1 {
width: 8.33%;
}
.col-s-2 {
width: 16.66%;
}
.col-s-3 {
width: 25%;
}
.col-s-4 {
width: 33.33%;
}
.col-s-5 {
width: 41.66%;
}
.col-s-6 {
width: 50%;
}
.col-s-7 {
width: 58.33%;
}
.col-s-8 {
width: 66.66%;
}
.col-s-9 {
width: 75%;
}
.col-s-10 {
width: 83.33%;
}
.col-s-11 {
width: 91.66%;
}
.col-s-12 {
width: 100%;
}
}
@media only screen and (min-width: 768px) {
/* 针对桌面: */
.col-1 {
width: 8.33%;
}
.col-2 {
width: 16.66%;
}
.col-3 {
width: 25%;
}
.col-4 {
width: 33.33%;
}
.col-5 {
width: 41.66%;
}
.col-6 {
width: 50%;
}
.col-7 {
width: 58.33%;
}
.col-8 {
width: 66.66%;
}
.col-9 {
width: 75%;
}
.col-10 {
width: 83.33%;
}
.col-11 {
width: 91.66%;
}
.col-12 {
width: 100%;
}
}
</style>
</head>
<body>
<div class="header">
<h1>Shanghai</h1>
</div>
<div class="row">
<div class="col-3 col-s-3 menu">
<ul>
<li>交通</li>
<li>文化</li>
<li>旅游</li>
<li>美食</li>
</ul>
</div>
<!-- 将各自屏幕宽度下的样式添加进来 -->
<div class="col-6 col-s-9">
<h1>欢迎来到上海</h1>
<p>
上海市,简称沪,别称申,是中华人民共和国直辖市,中国的经济、金融、贸易和航运中心,世界著名的港口城市,是中国人口第二多的城市。
</p>
</div>
<div class="col-3 col-s-12">
<div class="aside">
<h2>历史</h2>
<p>
最晚在新石器时代,上海地区已经有先民聚居。春秋时代,上海由吴国管辖,战国时代则是楚国领土
...
</p>
<h2>位置</h2>
<p>
上海位于中国东部弧形海岸线的正中间,长江三角洲最东部,东临东海,南濒杭州湾,西与江苏、浙江两省相接
...
</p>
<h2>环境</h2>
<p>
上海地处江南水乡,并位于长江入海口,亦不处于主要地震带上,因此如地震、洪水以及地质类灾害鲜有发生
...
</p>
</div>
</div>
</div>
<div class="footer">
<p>请调整浏览器窗口的大小,以查看内容如何响应调整大小。</p>
</div>
</body>
</html>
PC端(大于992px时)
平板端(600px-992px)
手机端(小于600px)