响应式布局:
根据不同的移动设备的尺寸,开发一套可以适应各种尺寸的页面,让页面以最好的视觉效果呈现在屏幕;

常见的响应式布局方法:

  • 媒体查询
  • rem布局
  • flexBox
  • 流式布局

一、1. flex布局

什么是flex?

flex 是Flex box的缩写,意为弹性布局,用来为盒模型提供最大的灵活性;

  • 容器指定为flex布局:
  1. 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

  1. <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计算方法

  1. function computedFont() {
  2. let winW = document.documentElement.clientWidth || document.body.clientWidth;
  3. let desW = 750;
  4. document.documentElement.style.fontSize = 100 * winW / 750 + 'px';
  5. }
  6. computedFont();
  7. window.addEventListener('resize', computedFont)

三、移动端事件

移动端有单独的触摸事件,一般不使用click事件,因为在移动端有300ms的延迟;

  1. let box = document.querySelector('#box');
  • touchstart 触摸元素时触发
  1. box.addEventListener('touchstart', function (e) {
  2. console.log('toustart');
  3. console.log(e); // TouchEvent 触摸事件对象
  4. // 在触摸事件对象中,把触摸的信息存放在touches中;
  5. console.log(e.touches[0].clientX);
  6. });
  • touchmove 在元素上滑动时触发
  1. box.addEventListener('touchmove', function (e) {
  2. console.log(e.touches);
  3. });
  • touchend 当手指离开元素时触发
  1. box.addEventListener('touchend', function (e) {
  2. console.log('touchend');
  3. console.log(e.changedTouches); // touchend没有e.touches ,事件信息放到了e.changedTouches属性上
  4. })

四、事件案例

  • 如果在盒子上水平或者竖直滑动距离超过30px,让当前盒子的透明度变为1,否则盒子旋转540deg;
  • HTML代码
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Title</title>
  7. <style>
  8. * {
  9. margin: 0;
  10. padding: 0;
  11. }
  12. html {
  13. font-size: 100px;
  14. }
  15. #box {
  16. width: 3rem;
  17. height: 1.5rem;
  18. background: lightgreen;
  19. }
  20. </style>
  21. <script>
  22. ;(function (designWidth = 750) {
  23. function computedFont() {
  24. let winW = document.documentElement.clientWidth || document.body.clientWidth;
  25. document.documentElement.style.fontSize = winW / designWidth * 100 + 'px';
  26. }
  27. computedFont();
  28. window.addEventListener('resize', computedFont);
  29. })(750)
  30. </script>
  31. </head>
  32. <body>
  33. <div id="box"></div>
  34. </body>
  35. </html>
  • JS代码
  1. let box = document.querySelector('#box');
  2. box.addEventListener('touchstart', function (e) {
  3. // dom2级事件中函数this仍然是绑定当前事件的元素
  4. let {touches: {0: point}} = e;
  5. this.x = point.clientX;
  6. this.y = point.clientY;
  7. this.style.transition = 'all 0s';
  8. this.style.transform = 'rotate(0)'
  9. });
  10. box.addEventListener('touchmove', function (e) {
  11. let {touches: {0: {clientX, clientY}}} = e;
  12. let {x, y} = this;
  13. this.moreThan30 = clientX - x > 30 || clientY - y >30;
  14. });
  15. box.addEventListener('touchend', function (e) {
  16. this.style.transition = 'all 1s';
  17. if (this.moreThan30) {
  18. this.style.opacity = 1;
  19. } else {
  20. this.style.transform = 'rotate(540deg)';
  21. }
  22. })

五、swiper插件的使用

本例是讲解查阅文档的能力;

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="swiper/swiper.min.css">
  7. <style>
  8. .swiper-container {
  9. margin: 40px auto;
  10. width: 800px;
  11. height: 500px;
  12. }
  13. .swiper-slide img {
  14. width: 100%;
  15. height: 100%;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <div class="swiper-container">
  21. <div class="swiper-wrapper">
  22. <div class="swiper-slide">
  23. <img src="banner/banner1.jpg" alt="">
  24. </div>
  25. <div class="swiper-slide">
  26. <img src="banner/banner2.jpg" alt="">
  27. </div>
  28. <div class="swiper-slide">
  29. <img src="banner/banner3.jpg" alt="">
  30. </div>
  31. <div class="swiper-slide">
  32. <img src="banner/banner4.jpg" alt="">
  33. </div>
  34. <div class="swiper-slide">
  35. <img src="banner/banner5.jpg" alt="">
  36. </div>
  37. </div>
  38. <!-- 如果需要分页器 -->
  39. <div class="swiper-pagination"></div>
  40. <!-- 如果需要导航按钮 -->
  41. <div class="swiper-button-prev"></div>
  42. <div class="swiper-button-next"></div>
  43. <!-- 如果需要滚动条 -->
  44. <div class="swiper-scrollbar"></div>
  45. </div>
  46. <script src="swiper/swiper.min.js"></script>
  47. <script>
  48. var mySwiper = new Swiper ('.swiper-container', {
  49. direction: 'horizontal', // 垂直切换选项
  50. loop: true, // 循环模式选项
  51. autoplay: true,
  52. // 如果需要分页器
  53. pagination: {
  54. el: '.swiper-pagination',
  55. },
  56. // 如果需要前进后退按钮
  57. navigation: {
  58. nextEl: '.swiper-button-next',
  59. prevEl: '.swiper-button-prev',
  60. }
  61. })
  62. </script>
  63. </body>
  64. </html>