响应式布局:
根据不同的移动设备的尺寸,开发一套可以适应各种尺寸的页面,让页面以最好的视觉效果呈现在屏幕;
常见的响应式布局方法:
- 媒体查询
- rem布局
- flexBox
- 流式布局
一、1. flex布局
什么是flex?
flex 是Flex box的缩写,意为弹性布局,用来为盒模型提供最大的灵活性;
- 容器指定为flex布局:
display: flex;
- 行内元素也可以使用flex布局:display: inline-flex
- 使用flex布局后,子元素的float clear vertical-align属性自动失效
二、基本概念
2.1 容器:采用flex布局的元素称为flex 容器(flex container),简称容器。它所有的子元素自动成为容器成元素,称为Flex项目(flex item)简称项目;
2.2 主轴和交叉轴:
- 默认 水平的主轴和垂直的交叉轴。
- 主轴开始的位置与边框的交叉点叫做 main start,结束位置叫做main end;
- 交叉轴开始的位置叫做cross start,结束位置叫做cross end;
项目默认沿着主轴排列,单个项目占据的主轴空间叫做 main size,占据交叉轴空间叫做cross size;
三、容器属性
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
3.1 flex-direction: 设置主轴方向;可选值:
row(默认值) 主轴为水平方向,起点在左端
row-reverse: 主轴为水平方向,起点在左端
column: 主轴为垂直方向,起点在上沿
column-revers: 主轴为垂直方向,起点在下沿。
3.2 flex-wrap : 设置项目拍不下时如何换行
- nowrap 默认值 不换行,压缩item的尺寸来实现
- wrap: 换行,第一行在上方
- wrap-reverse: 换行,第一行在下方
3.3 flex-flow flex-direction 和 flex-wrap 的简写
3.4 justify-content 设置项目在主轴上的对齐方式,可选值:
- flex-start: 默认值,左对齐
- flex-end: 右对齐
- center: 居中
- space-between: 两端对齐,项目之间间隔相等
- space-around: 每个项目两侧间距相等,所以项目之间的距离比项目和边框之间的距离大一倍
3.5 align-items 设置项目在交叉轴上对齐方式
- flex-start: 交叉轴起点对齐
- flex-end: 交叉轴终点对齐
- center: 交叉轴的终点对齐
- baseline: 项目第一行文字基线对齐
- stretch: 默认值,如果项目未设置高度或者设为auto,将占满整个容器的高度
四 项目属性:
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
4.1 order 属性定义项目的排列顺序,数值越小越靠前,默认为0
4.2 flex-grow 属性:定义项目的放大比例,默认为0,如果剩余空间也不会放大;如果所有的项目的flex-grow都为1,则他们等分剩余空间,如果某一个的flex-grow 为2,其余的都为1,为2的那个占据的剩余空间比其他的大
4.3 flex-shrink 属性定义了项目的缩小比例,默认为1,即空间不足,该项目将缩小;如果所有的项目的flex-shrink都为1,当空间不足时,都将等比缩小;如果一个项目的flex-shrink为0,其他的都为1时,前者不缩小;(如果容器设置了flex-wrap无效了)
4.4 align-self: 允许单个项目与其他项目的对齐方式不同,可以覆盖容器的align-items属性;默认值auto,表示继承父元素的align-item属性,如果没有stretch
- auto
- flex-start
- flex-end
- center
- baseline
- stretch
二、rem布局
viewport
在使用rem布局前,必须先在html开头加入一个meta标签,name是viewport
<meta name="viewport" content="width=device-width, initial-scale=1.0">
rem是什么?
rem: 和px一样都是单位,px是固定单位,rem是相对单位,是相对于html标签的字体大小来的,html标签的字体大小 font-size就是1rem;
为什么用rem布局?
成rem有一个好处,如果写成px就是死的,现在我们写成rem,把元素的跟字体大小调成50px,页面中所有的盒子都缩放了,而且比例一致;我们按照一个手机的尺寸把图切好了,但是拿到另一个手机上了,此时另一个手机的尺寸和之前的手机不一样,样式就全乱了。现在用rem来写,当换了手机后,我们根据手机屏幕的大小改html的字体大小,这些样式自动按照比例改了。
rem布局的思路
我们开始给html的字体大小设置为100px(此时1rem就是100px),接下来我们写样式的时候,把所有的尺寸都用rem设定(测量出来的px/ 100 就是需要设置的rem的值),但是如果html的font-size不变,用rem和px一样,但是如果字体改变了,也就是改变了rem和px之间的换算比例,那么之前所有用rem做单位的样式都会按照最新的比例进行缩放(实现了改动html的font-size,整个页面中的元素都会跟着缩放了);
真实项目中:设计师会给我们一套设计稿,设计稿的常用宽度,640 和 750
常用的宽度是750px的,拿到设计稿后,我们严格按照设计稿中尺寸编写样式;此时设置html {font-size: 100px};
接下来写样式,把测量出来的px都除以100变为rem,所有的单位都基于rem来写;
=> 假设设计稿是750px,相当于在750的设备下,1rem = 100px
如果页面运行在375的设备上,我们需要修改html的字体大小,以此实现页面整体缩放;375 / 750 * 100 => 当前设备上HTML字体的大小。
如果现在页面运行在375的设备上,我们根据这个比例把html的font-size进行修改,页面中所有用rem的尺寸都会自动跟着修改;
rem计算方法
function computedFont() {
let winW = document.documentElement.clientWidth || document.body.clientWidth;
let desW = 750;
document.documentElement.style.fontSize = 100 * winW / 750 + 'px';
}
computedFont();
window.addEventListener('resize', computedFont)
三、移动端事件
移动端有单独的触摸事件,一般不使用click事件,因为在移动端有300ms的延迟;
let box = document.querySelector('#box');
- touchstart 触摸元素时触发
box.addEventListener('touchstart', function (e) {
console.log('toustart');
console.log(e); // TouchEvent 触摸事件对象
// 在触摸事件对象中,把触摸的信息存放在touches中;
console.log(e.touches[0].clientX);
});
- touchmove 在元素上滑动时触发
box.addEventListener('touchmove', function (e) {
console.log(e.touches);
});
- touchend 当手指离开元素时触发
box.addEventListener('touchend', function (e) {
console.log('touchend');
console.log(e.changedTouches); // touchend没有e.touches ,事件信息放到了e.changedTouches属性上
})
四、事件案例
- 如果在盒子上水平或者竖直滑动距离超过30px,让当前盒子的透明度变为1,否则盒子旋转540deg;
- HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
font-size: 100px;
}
#box {
width: 3rem;
height: 1.5rem;
background: lightgreen;
}
</style>
<script>
;(function (designWidth = 750) {
function computedFont() {
let winW = document.documentElement.clientWidth || document.body.clientWidth;
document.documentElement.style.fontSize = winW / designWidth * 100 + 'px';
}
computedFont();
window.addEventListener('resize', computedFont);
})(750)
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
- JS代码
let box = document.querySelector('#box');
box.addEventListener('touchstart', function (e) {
// dom2级事件中函数this仍然是绑定当前事件的元素
let {touches: {0: point}} = e;
this.x = point.clientX;
this.y = point.clientY;
this.style.transition = 'all 0s';
this.style.transform = 'rotate(0)'
});
box.addEventListener('touchmove', function (e) {
let {touches: {0: {clientX, clientY}}} = e;
let {x, y} = this;
this.moreThan30 = clientX - x > 30 || clientY - y >30;
});
box.addEventListener('touchend', function (e) {
this.style.transition = 'all 1s';
if (this.moreThan30) {
this.style.opacity = 1;
} else {
this.style.transform = 'rotate(540deg)';
}
})
五、swiper插件的使用
本例是讲解查阅文档的能力;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="swiper/swiper.min.css">
<style>
.swiper-container {
margin: 40px auto;
width: 800px;
height: 500px;
}
.swiper-slide img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src="banner/banner1.jpg" alt="">
</div>
<div class="swiper-slide">
<img src="banner/banner2.jpg" alt="">
</div>
<div class="swiper-slide">
<img src="banner/banner3.jpg" alt="">
</div>
<div class="swiper-slide">
<img src="banner/banner4.jpg" alt="">
</div>
<div class="swiper-slide">
<img src="banner/banner5.jpg" alt="">
</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
<!-- 如果需要导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- 如果需要滚动条 -->
<div class="swiper-scrollbar"></div>
</div>
<script src="swiper/swiper.min.js"></script>
<script>
var mySwiper = new Swiper ('.swiper-container', {
direction: 'horizontal', // 垂直切换选项
loop: true, // 循环模式选项
autoplay: true,
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
}
})
</script>
</body>
</html>