[深入18] CSS-interview

1,301 阅读20分钟

导航

[深入01] 执行上下文
[深入02] 原型链
[深入03] 继承
[深入04] 事件循环
[深入05] 柯里化 偏函数 函数记忆
[深入06] 隐式转换 和 运算符
[深入07] 浏览器缓存机制(http缓存机制)
[深入08] 前端安全
[深入09] 深浅拷贝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模块化
[深入13] 观察者模式 发布订阅模式 双向数据绑定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手写Promise
[深入20] 手写函数

[react] Hooks

[部署01] Nginx
[部署02] Docker 部署vue项目
[部署03] gitlab-CI

[源码-webpack01-前置知识] AST抽象语法树
[源码-webpack02-前置知识] Tapable
[源码-webpack03] 手写webpack - compiler简单编译流程
[源码] Redux React-Redux01
[源码] axios
[源码] vuex
[源码-vue01] data响应式 和 初始化渲染
[源码-vue02] computed 响应式 - 初始化,访问,更新过程

前置知识

一些单词

sticky:粘性
triangle:三角形
rectangle:矩形
alternate:轮流的
orient:方向,朝向

vh 和 vw

  • vh:表示浏览器视口高度
  • vw:表示浏览器视口宽度
  • 注意:vh 和 vw 包括滚动条的宽度和高度
    • 需要满屏时,记得减去浏览器滚动条的宽和高

2022/03/28 添加

(1) pointer-events - 设置事件穿透

  • 作用:可以设置 ( 事件穿透 )
  • 具体:指定在什么特定的情况下,target 可以设置为 ( 鼠标事件 ) 的 ( target )
  • 详细
    • pointer-events: none; ------- 表示 ( 该 css 选择器对应的 target 永远不会成为鼠标事件的 target ),即不会对 ( 鼠标事件进行响应 )
    • pointer-events: auto -------- 默认值,对鼠标事件进行响应

(2) 如何实现 平行四边形

  • 可以利用 transform 中的 ( skew ) 来实现
  • transform: skew(x-angle,y-angle) 表示 ( 水平倾斜的角度 ) 和 ( 垂直倾斜的角度 )
  • 注意:参数有两个,第一个表示水平倾斜的角度,第二个表示垂直倾斜的角度
  • 详细:juejin.cn/post/702970…

(3) transform 修改原点

    1. 默认原点:transform 进行变换时 ( 默认原点 ) 是 ( 中心点 )
    1. 修改原点:transform-origin 可以修改 ( 原点 )
  • transform-origin
    • transform-origin: x-axis y-axis z-axis;
    • 单位:可以是 百分数,px,top 等等

(4) css如何控制移动端小于 12px 的字体

1. 前置知识
- 浏览器上能设置的最小字体是 12px,当小于12px的汉子会当作12px来处理

2. 解决方案有
- zoom
- transform: scale() + transform-origin: left;

zoom
- zoom表示变焦,可以改变页面上元素的尺寸
- zoom:50% 和 zoom:0.5 都表示缩小到原来的一半

transform
- transform: scale(0.5)
- transform-origin: left;
- 注意:
  - 出现问题:transform: scale(0.5) 进行字体缩放后,字体虽然变小了,但是位置缺变化了
  - 分析原因:因为transform的操作,默认的 ( 原点 ) 是 ( 正中心位置 )
  - 如何解决:transform-origin: left;
- 额外知识
  - 描述:transfrom 是 不会 引起reflow回流的
  - 原因:
    - 浏览器渲染会经过 parseHTML -> parseStylesheet -> evaluteScript -> layout -> paint -> composite
    - transform ------------ 是在 composite合成层
    - width,left,margin --- 是在 layout 层,不在同一层
    - 分层是为了减少重绘制的时间
    - transform还能开启 GPU 加速

(5) css如何实现右箭头

- transform: rotate(45deg)
- border-top + border-right

sticky-footer (三种方法)

sticky-footer效果:是在内容不足一屏时,footer固定在底部,内容超出一屏时,在内容最底部

  • padding margin
  • flex
  • calc

(1) margin 和 padding 组合

  • 适用性:适用于footer固定的情况,兼容性好
  • 原理
    • content
      • padding-bottom: 50px; 保证空出footer的高度距离,避免footer挡住了content的内容
      • min-height: 100%; 保证内容不足时,撑满屏幕
        • 注意min-height: 100%是针对父元素来说的
        • 所以要将content的父元素,父父元素,body,html的height都设置成100%
      • box-sizing: border-box; 保证width,height包括content,padding,border
    • footer
      • margin-top: -50px; 为负数,保证往上移动50px在内容不足时,正好在屏幕底部
方法1
- margin pading组合
- 适用于 footer固定的情况,兼容性较好

- footer
  - margin-top: -50px;
  - 因为内容区设置了
    - min-height: 100%;在内容不足时候,沾满整个网页
    - padding-bottom: 50px; 主要是为了防止footer往上移动到可视区域底部后,内容区的内容被footer遮挡
    - footer的margin-top的负值则是往上移动,正好和padding-bottom区域重合
- content 
  - min-height:100%,保证内容不全时,沾满整个网页
  - 注意:min-height: 100%是根据父元素计算的,和父元素高度一样,所以content-wrap的所有外层元素都要设置height: 100%
- 注意清掉所有默认样式的padding和margin


- 代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }
    html, body {
      height: 100%;
    }
    .wrap {
      height: 100%;
    }
    .content {
      min-height: 100%; // 内容不足占满整个内容空间
      padding-bottom: 60px; // 避免contentfooter覆盖而看不到内容
      box-sizing: border-box; // width,height包括content,padding,border
      background: blueviolet;
    }
    .footer {
      margin-top: -60px; // 当content内容不足,占满屏幕后,margin-top则让footer显示在底部
      height: 60px;
      background: red;
    }
  </style>
</head>
<body>
  <div class="wrap">
    <div class="content">
      <div>content <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div>
      <!-- <div>content <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div>
      <div>content <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div> -->
    </div>
    <div class="footer">footer</div>
  </div>
</body>
</html>

(2) flex布局

  • 固定footer通常不太好,不太灵活
  • 所以flex布局能让footer不固定的情况下实现 sticky-footer 布局
  • wrap
    • display: flex;
    • flex-direction: column; // 纵向排列
    • min-height: 100%; // 当然其父元素高度也要是100%,以上的所有父元素都必须是100%
  • content
    • flex: 1; // 表示放大比例,在存在剩余空间时,放大占满剩余空间
2. flex布局

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }
    html, body {
      height: 100%;
    }
    .wrap {
      /* height: 100%; */
      min-height: 100%;
      display: flex;
      flex-direction: column;
    }
    .content {
      /* min-height: 100%; */
      flex: 1;
      /*
      padding-bottom: 60px;
      box-sizing: border-box;
      */
      background: yellow;
    }
    .footer {
      /* margin-top: -60px; */
      height: 60px;
      background: blue;
    }
  </style>
</head>
<body>
  // 在最层元素上设置 min-height: 100% 内容不住沾满空间
  // 在最层元素上设置flex作为容器,注意flex-direction: column竖直方向为主轴
  // 让content项目的flex: 1; 这样就能让cotent占满主轴的剩余空间,即除了footer以外的所有高度,主轴方向min-height: 100%
  <div class="wrap">
    <div class="content">
      <div>content <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div>
      <div>content <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div>
      <div>content <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div>
    </div>
    <div class="footer">footer</div>
  </div>
</body>
</html>

(3) calc属性

  • calc(表达式)
    • 以一个表达式为参数,表达式的 ( 结果 ) 作为 ( 值 )
    • 表达式可以是:任意 + - * / 的组合
    • 注意:+ - 的运算子之间必须有空格,* / 不必有空格
  • calculate:是计算的意思
方法三
- calc属性
- calculate: 计算

<!DOCTYPE html>
 <html lang="en">
 <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Document</title>
   <style>
     * {
       margin: 0;
       padding: 0;
     }
     .content {
       min-height: calc(100vh - 30px) 
       // 参数是表达式,可以使用 + - * /
       // 2021/10/22 更新如下
       // 注意:
       // - vh 和 vw 是包含了 ( 滚动条 ) 的释口高度和宽度
       // - vh = window.innerHeight
     }
     .footer {
       height: 30px;
       background: black;
       color: white;
     }
   </style>
 </head>
 <body>
  <div class="content">
    content <br><br><br><br>
    content <br><br><br><br>
    content <br><br><br><br>
  </div>
  <div class="footer">
    footer
  </div>
 </body>
 </html>

清除浮动

BFC

  • BFC ( Block Formatting Context ) 块级格式化上下文,是一种特性
    • BFC指页面的一块渲染区域,并有一套渲染规则,它决定了其子元素如何定位,以及和其他元素的关系和相互作用
    • 具有BFC元素特性的元素,可以看作是隔离了的独立元素,容器里的元素不会在布局上影响其他元素
  • 如何触发BFC特性
    • 根元素
    • 浮动 flot
    • 绝对定位 position: absolute 和 fixed
    • display 为 inline-block、table-cells、flex
    • overflow 除了 visible 以外的值( hidden, auto, scroll )
  • BFC布局规则
    • margin折叠
      • 属于同一个BFC的两个相邻块级元素会发生margin折叠
    • 独立容器
      • 容器里面的元素不会相应到元素外面的元素
  • 利用BFC清除浮动的原理
    • 具有BFC特性的元素在计算高度时,包含所有子元素 ( 包括浮动元素 )
    • 所以能解决 ( 浮动 ) 造成的 ( 父元素高度塌陷 ) 的问题
  • 为什么要清楚浮动
    • 原因:浮动元素脱离文档流后,造成父元素高度塌陷 ( 在父元素没有设置高度时 )
    • 解决办法:触发BFC特性,或者在浮动元素的兄弟元素使用 clear 属性

清除浮动的方法 - 解决父元素高度塌陷

  • 在父元素没有设置高度时,比如存在两个子元素,一个子元素设置float后,父元素会发生高度塌陷

(1) overflow: hidden

  • 方法:在浮动元素的父元素上设置overflow: hidden
  • 原理:触发BFC,具有BFC特性的元素在计算高度时,会把所有子元素计算在内,报错浮动的元素,则不会高度塌陷
  • 所以:overflow: hidden scroll auto都可以,只要不是 ( overflow: visible ) 都可以
  • 哪些属性可以触发BFC,即都可以用来清除浮动
    • 根元素
    • 浮动
    • 绝对定位:absolute fixed
    • overflow: hidden/auto/scroll, 不是visible就行
    • display: inline-block/flex/table-cell

(2) 伪元素 ( ::before ) ( ::after )

  • 方法:给浮动元素的父元素,添加伪元素
  • 原理:
    • 1.伪元素是当前元素的子元素,再给伪元素设置 clear 属性,注意 clear 属性只适用于块级元素
      • 注意区分伪元素和伪类
        • 伪元素:是一个元素 ::after ::before
        • 伪类:是一个class类 :hover :link ...
    • 2.给浮动元素的父元素添加伪元素,然后设置clear:both,相当于浮动元素的兄弟元素设置clear属性

(3) 给浮动元素的父元素插入一个子元素,比如span,在设置clear属性,display要为block

  • 和添加伪元素是一个道理,用子元素去撑开父元素的高度

(4) 把浮动元素的父元素也设置浮动,从而触发BFC (重复了,但是容易忘记写上把)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .father {
      background: yellow;
      padding: 30px;
      position: relative;
      /* float: left; */
      /* position: absolute; */
      /* overflow: hidden; */
      /* display: inline-block; */
    }
    .father::before {
      content: '.';
      height: 100PX;
      width: 100PX;
      position: absolute;
      top: 0;
      left: 0;
      display: block;
      background: greenyellow;
      clear: both;
    }
    .brother {
      height: 200px;
      width: 200px;
    }
    .child {
      height: 200px;
      width: 200px;
      background: red;
      float: left;
    }
  </style>
</head>
<body>
  <div class="father">
    <div class="child">child</div>
    <div class="brother"></div>
  </div>
</body>
</html>

css选择器

  • 元素选择器
  • 关系选择器
  • 属性选择器
  • 伪类选择器
  • 伪对象选择器

元素选择器

选择器名称描述
*通配符选择器选择所有元素
E元素选择器选择指定元素
#idNameid选择器选择id属性等于idName的元素
.className类选择器选择class属性等于className的元素

关系选择器

选择器名称描述
E>F子选择器子选择器只能选中子元素,不能选中孙子元素,孙孙子元素
E F后代选择器除了能选择子元素外,还能选中孙子元素,孙孙子元素
E+F相邻选择器相邻选择器只能选中符合条件的相邻的兄弟元素, ( E元素之后的相邻的F元素 )
E~F兄弟选择器兄弟选择器会选中符合条件的所有兄弟元素,不强调相邻 ( E元素之后的所有兄弟F元素 )

属性选择器

选择器描述
E[att]选择具有att属性的E元素
E[att="val"]选择att属性值为val的E元素
E[att~="val"]选择具有att属性且属性值其中一个等于val的E元素(包含只有一个值且该值等于val的情况)
E[att^="val"]选择具有att属性且属性值为以val开头的字符串的E元素
E[att$="val"]选择具有att属性且属性值为以val结尾的字符串的E元素
E[att*="val"]选择具有att属性且属性值为包含val的字符串的E元素

E[att|="val"] 选择具有att属性且属性值为以val开头并用连接符-分隔的字符串的E元素,如果属性值仅为val,也将被选择

伪类选择器

  • E:link 设置超链接a在未被访问前的样式
  • E:visited 设置超链接a在其链接地址已被访问过时的样式
  • E:hover 设置元素鼠标在其悬停时的样式
  • E:active 设置元素在被用户激活(在鼠标点击与释放之间发生的事件)时的样式
  • E:focus 设置元素在成为输入焦点(该元素的onfocus事件发生)时的样式。(一般应用于表单元素)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    div[class~="xy"] div[class$="2"]{ 
    // ------------------------------------- 属性选择器,后代选择器
    // div[class~="xy"] -------------------- div属性是class,并且class的值其中一个是xy的div,即(father)
    // div[class~="xy"] div[class$="2"] ---- 后代选择器,包括子元素,孙子元素,孙孙子元素
    // div[class$="2"] --------------------- div的class属性的值以2结尾的div被选中,即(child2,children2)
      border: 2px solid red;
      margin: 10px;
    }
    div[class="child4"]+div {
    // ------------------------------------- 相邻选择器,(区分兄弟选择器)
      background: blue;
    }
  </style>
</head>
<body>
  <div class="father xy">
    <div class="child1">
      <div class="children1">children1</div>
      <div class="children2">children2</div>
    </div>
    <div class="child2">child2</div>
    <div class="child3">child3</div>
    <div class="child4">child4</div>
    <div class="child5">child5</div>
  </div>
</body>
</html>

选择器优先级

  • !important > 行内样式 > id > 属性 > class > 元素选择器或伪元素选择器 > 通配符选择器

伪类和伪元素

伪类

  • 伪类:和class一样是一个类,表示一些动态状态------------------------- 伪类是一个类,一个冒号:

伪元素

  • 伪元素:是一个元素,不再DOM文档中,( 当前元素的子元素 ) --------- 伪元素是一个元素,两个冒号::
    • 注意:伪元素是当前元素的子元素,并且不再DOM文档中,无法用js获取,可以用来做性能优化,比如分割线等
伪类和伪元素

1.
伪类:和class一样,是一个类,表示一些动态状态 --------------------------------- 伪类是一个类,一个冒号:
伪元素:是一个元素,不在dom文档树中,( 当前元素的子元素 ) ---------------------- 伪元素是一个元素,两个冒号::


2. 
伪类一个冒号,伪元素两个冒号


3.常见的伪类和伪元素
伪类:
:hover 
:active 
:focus  ------------- 设置输入框的样式,比如改变背景颜色
:visited 
:link 
:firsh-child .....
伪元素: 
::before 
::after
::first-letter  ------------ 选取指定选择器得首字母
::first-line --------------- 选取指定选择器得首行
::selection ---------------- 匹配用户选取得部分,比如选取文字得背景颜色等
::placeholder -------------- 设置placeholder的样式


4.总结:
- 伪类是一个类,定义的是状态:hover,:active,:focus,:visited,:link,:first-child,:last-child等等
- 伪元素是元素的子元素,不在DOM树中,无法用js获取
- 伪元素是行内元素,设置宽高无效,当可以是指display:block改变

实例:
1. 伪元素动画
- 当设置position: absolute后,元素的的display会变成 ----  display:inline-block
- float和position都会改变 display
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<style>
.pseudo {
  height: 150px;
  width: 300px;
  background: rgb(3, 173, 185);
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  position: relative; // ---- 作为绝对定位的定位点
}
.pseudo::after { ------------ 伪元素是当前元素的子元素
  content: ''; -------------- 必须设置内容,这里内容为空
  position: absolute; ------- 绝对定位会改变display 为 inline-block
  left: 50%; // ------------- 绝对定位把leftright都设置为50%,即宽度被压缩成一点,在居中位置
  right: 50%;
  bottom: 0;
  height: 2px;
  background: rgb(255, 230, 0);
  transition: all .3s; // --- 定义transition,状态改变变化时触发
}
.pseudo:hover::after { // ---- 注意给伪元素::after添加伪类:hover的写法是:  ( .pseudo:hover::after )
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  background: rgb(255, 230, 0);
  left: 0; // ---------------- hover时展开,状态触发transition
  right: 0;
}
.pseudo::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 2px;
  background: rgb(255, 0, 0);
  top: 50%;
  bottom: 50%;
  transition: all .3s;
}
.pseudo:hover::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 2px;
  background: rgb(255, 0, 0);
  top: 0;
  bottom: 0;
}
</style>
<body>
  <div class="pseudo">伪类和伪元素</div>
</body>
</html>

冲击波动效

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .button {
      margin: 200px;;
      width: 100px;
      height: 40px;
      background: black;
      border-radius: 30px;
      text-align: center;
      line-height: 40px;
      color: white;
      position: relative;
    }
    .button::before {
      content: '';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%); // --------------------- 居中
      width: 200px;
      height: 200px;
      opacity: 0;
      background: white;
      border-radius: 50%;
      z-index: 9999;
      transition: all .5s; // ---------------------------------- 0.5s过度动画
    }
    .button:active::before { // -------------------------------- 伪类:active => 点击改变状态
      content: '';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%); 
      width: 0;
      height: 0;
      opacity: 1;
      background: white;
      border-radius: 50%;
      z-index: 9999;
      transition-duration: 0s; 
      // ------------------------------------------------------ active时持续时间为0,瞬间改变到active时的状态
      // ------------------------------------------------------ 即瞬间透明度10;大小从2000
      // ------------------------------------------------------ 点击完成时,则执行.5秒的过度动画
      
      // --------------------------- 触发时的状态,用transition-duration: 0s; 立即结束掉,原始状态 --> 目标状态
    }
  </style>
</head>
<body>
  <div class="button">button</div>
</body>
</html>

css画三角形

  • triangle:三角形
css画三角形

1.宽高都设置为0border的四边用不同颜色区分,将出现四个三角形
2.为什么会出现4个三角形,因为四个border相互遮挡了
3.#b是向上的三角形
  - 三角形底边长度是border的两倍 ( border-left+border-right的长度 )
  - 三角形高都就是border-bottom的值,所以改变border-bottom就能得到高度不同的三角形
4.其他方向的三角形同理


5. 实例
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .triangle { // --------------------------------- 三角形,把div宽高都设置为0;四个border就是四个三角形
      width: 0;
      height: 0;
      border: 100px solid transparent; // ----------- 四个边设置为透明,用底边覆盖后,就显示向上的三角形,其他方向同理
      border-bottom: 100px solid red; //------------- 向上三角形的底边=left+right的长度,高就是bottom的长度
    }
    .rectangle {
      width: 200px;
      height: 200px;
      background: blue;
    }
  </style>
</head>
<body>
  <div class="triangle"></div>
  <div class="rectangle"></div>
</body>
</html>

visibility:hidden 和 display:node 的区别

  • visibility:hidden 隐藏后,会占据原来的位置
  • display:none 隐藏后,不会占据原来的位置
  • 但是他们都还是会在DOM节点中

display: inline-block存在间隙的原因和解决办法

  • 原因:标签之间有空白字符
  • 解决办法:
  1. 父元素设置font-size=0;然后再在各个子元素中设置自己需要的大小(因为是字符,所以font-size可以改变字符的大小)
  2. 各个标签之间不要换行,而是仅仅贴合在一起<div>1</div><div>2</div>

@media媒体查询

  • @media 查询,可以针对不同的屏幕尺寸定义不同的样式。
  • 使用:
    • 可以在link标签中
    • 可以在css中
(1) @media语法

@media mediatype and|not|only (media feature) {
    CSS-Code;
}


1.媒体类型
mediatype:媒体类型
- screen:电脑,平板,手机
- print:打印机
- all:所有设备


2.媒体特性
media feature:媒体特性
- 每条媒体特性表达式都必须用括号括起来。


3. 逻辑操作符
- and
    - and运算符用于将多个媒体功能组合到一个媒体查询中
    - 要求每个链接功能都返回true才能使查询为true // --------------------------- 要都为tru才会为true
    - 它还用于将媒体功能与媒体类型结合在一起。
- not
- only



4.代码
@media screen and (max-width: 300px) { // ----- 文档宽度小于 300 像素则修改背景颜色(background-color)
    body {
        background-color:lightblue;
    }
}


@media only screen and (min-width: 640px) and (max-width: 1136px) {
    // 表示( 媒体类型仅仅是screen ) 并且 ( 设备宽度在 640px-1136px之间 ) 就会命中
}


@media screen and (max-width: 680px), screen and (orientation: landscape) and (max-width: 750px) {
    aside {
        display: none;
    }
    // 表示 ( 屏幕宽小于680px ) 或者 ( 屏幕宽小于750px并且横屏 ) 时触发
    // 逗号 , 就是或者的意思
}

在link标签中使用媒体查询

<link rel="stylesheet" media="screen and (max-width: 600px)" href="small.css" />

<link 
  rel="stylesheet"
  media="screen and (min-width:600px) and (max-width:900px)"
  href="style.css"
  type="text/css" 
/>
表示:屏幕宽度大于600px并且小于900px时,使用style.css文件

在css中使用媒体查询

        @media only screen and (max-width: 765px) {
            .media {
                background: red;
            }
        }
        @media only screen and (min-width: 1200px) {
            .media {
                background: yellow;
            }
        }
        @media only screen and (min-width: 766px) and (max-width: 1199px) {
            .media {
                background: blueviolet;
            }
        }

表示:屏幕宽度
(1)小于765px,背景色red
(2)大于1200px,背景色yellow
(3)在766px-1199px之间,背景色blueviolet

em

  • em是相对单位,em作为font-size的单位时,表示父元素的字体大小;em作为其他属性单位时,表示自身字体大小
  • em布局的缺点
    • em做弹性布局的缺点在于牵一发而动全身,一旦某个节点的字体大小发生变化,那么其后代元素都得重新计算
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .father {
      font-size: 20px;
    }
    .child {
      font-size: 5em;  // ----------- 当em是font-size的单位时,1em表示的是父元素的font-size的大小 ( 100px )
      width: 5em; // ---------------- 当em是其他属性的单位时,表示的是自身font-size的大小 ( 100 * 5 = 500px )
      height: 5em;
      background: red;
    }
  </style>
</head>
<body>
  <div class="father">
    <div>father</div>
    <div class="child">child</div>
  </div>
</body>
</html>

rem

  • 原理:根据根元素的font-size的大小来计算,1rem=根元素的字体大小

css像素,物理像素,倍屏(像素比)

  • 物理像素 = css像素(设备独立像素) * 像素比(几倍屏)

rem布局

  • px绝对单位
  • em,rem,vw等都是相对单位
  1. 动态设置html的font-size大小
  2. 将px和rem做适当的比例换算(比如让1px=1rem)
  3. font-size的大小可以继承,为了避免设置html的font-size影响后代的font-size,不要在body上重新设置font-size
设计稿:750px为基准的前提下


1. 动态设置htmlfont-size大小
2. 将px和rem做适当的比例换算(比如让1px=1rem3. font-size的大小可以继承,为了避免设置htmlfont-size影响后代的font-size,不要在body上重新设置font-size



12. 
动态设置htmlfont-size大小 ----------- (可以用js实现,也可以用css的calc方法实现)
(1) js
document.documetElement.style.fontSize = document.documetElement.client / 750 + 'px'
- 即一个等式:设备实际宽度deviceWidth / 设计稿宽度750 = 某个元素的实际宽度x / 某个元素的设计稿宽度designWidth
- 得出结果:x = deviceWidth/750 * designWidth
- 最终结果:x = 1rem * designWidth = designWidth rem
(2) css-calc()
.html {
    font-size: calc(100vw / 750);
}

3. body
body {
    font-size: 16px; // 浏览器默认字体大小是 16px
}

rem布局 - 实例1 - 手动

rem布局:
- 原理:rem是根据htmlfont-size的大小来计算元素的大小,1rem = htmlfont-size的大小
- 方法:用js或者css的calc()动态设置htmlfont-size的大小

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    html {  
      /* font-size: calc(100vw / 750); */
      // -------------------------------- 用css的calc()动态设置htmlfont-size
      // -------------------------------- 注意单位vw,vw表示视口的宽度,即浏览器的视口总宽度是100vw
      // ------ calc(100vw / 750)表示把浏览器宽度分成750份,设计稿基于750px设计
      // ------ 1rem = calc(100vw / 750)
      // ------ 根据公式:设备实际宽度deviceWidth / 设计稿宽度750 = 某个元素的实际宽度x / 某个元素的设计稿宽度designWidth
      // ------ 如果:设计稿上有一个 div=100px
      // ------ 开发:div=100rem 就是该div在屏幕中实际的大小
      
    }
    body {
      font-size: 16px; // -------------- 重设font-size避免继承htmlfont-size影响后代元素
    }
    .father {
      width: 100rem; // ---------------- 11的关系
      height: 100rem;
      background: goldenrod;
      font-size: 50rem;
    }
  </style>
</head>
<body>
  <div class="father">father</div>
  <script>
    document.documentElement.style.fontSize = (document.documentElement.clientWidth / 750) + 'px';
  </script>
</body>
</html>

rem布局 - 实例2 - 如何直接写px达到实际是rem单位的效果,即在开发时还是使用px为单位

  • 自己写一个pxtorem的函数,转换
  • 利用第三方依赖 (postcss-pxtorem)
(1) 
// 定义 px 转化为 rem 的函数
@function px2rem ($px) {
    @return $px + rem; // ----------- 按照上面的设置,px和rem其实就是11的关系了
}
.demo {
    width: px2rem(100);
    height: px2rem(100);
}






(2) 插件
postcss-pxtorem
地址:https://github.com/cuth/postcss-pxtorem

如果是基于webpack的项目,则可以新建postcss.config.js文件

-------------- app.vue -------------- 
* {
  margin: 0;
  padding: 0;
}
html {
  font-size: calc(100vw / 750);
}

--------------- postcss.config.js ---------------
--------------- 也可以在vue.config.js中配置 ---------------
module.exports = {
  plugins: {
    'autoprefixer': {------------------ 解决浏览器前缀的兼容性
      browsers: ['Android >= 4.0', 'iOS >= 7']
    },
    'postcss-pxtorem': { // ------------ 自动转换,注意该插件只是将px转成rem,还是要动态设置htmlfont-size大小
        rootValue: 1, // 基数,即1px = 1rem
        unitPrecision: 5,
        propList: ['*'],
        selectorBlackList: [],
        replace: true,
        mediaQuery: false,
        minPixelValue: 0,
        exclude: /node_modules/i
    }
  }
}


--------------- ue.config.js ---------------
module.exports = {
  lintOnSave: true,
  css: {
      loaderOptions: {
          postcss: {
              plugins: [
                  require('postcss-pxtorem')({
                      rootValue : 1, // 换算的基数
                      selectorBlackList  : ['weui','mu'], // 忽略转换正则匹配项
                      propList   : ['*'],
                  }),
              ]
          }
      }
  },
}

animation

  • animation: name duration timing-function delay iteration-count animation-direction;
  • animation: 动画名 持续时间 速度曲线 延时执行 播放次数 是否轮流反向执行;
  • iteration-count: n | infinite 播放的次数
  • animation-direction: normal|alternate; 是否轮流反向执行
  • alternate:是轮流的意思
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    @keyframes go { // -------------------------------------------------- @keyframes
      from {
        left: 0;
      }
      to {
        left: 100px;
      }
    }
    .father {
      width: 200px;
      height: 200px;
      background: red;
      position:relative;
      animation: go 1s ease-in-out 2s infinite alternate; // ------------- animation
    }
  </style>
</head>
<body>
  <div class="father">father</div>
</body>
</html>

1像素物理边框

  • 利用 ( 伪元素, 媒体查询, transform, 设备像素比 ) 实现1物理像素边框
  • 设备像素比: window.devicePixelRatio
  • 物理像素 = css像素(设备独立像素) * 像素比(几倍屏)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .one-px-border {
      height: 200px;
      width: 200px;
      position: relative;
    }
    .one-px-border::before { // ------------------------- 伪元素,当前元素的子元素,不在DOM中,提升效率
      content: ''; // ----------------------------------- 必须设置content
      position: absolute;
      left: 0;
      bottom: 0;
      width: 100%;
      height: 1px;
      background: red;
    }
    @media screen and (-webkit-min-device-pixel-ratio: 2) { // ---------------- 像素比是2,则缩放y方向的尺寸为0.5
      .one-px-border::before {
        transform: scaleY(0.5);
      }
    }
    @media screen and (-webkit-min-device-pixel-ratio: 3) {// ---------------- 像素比是3,则缩放y方向的尺寸为0.333
      .one-px-border::before {
        transform: scaleY(0.33333);
      }
    }
  </style>
</head>
<body>
  <div class="one-px-border"></div>
</body>
</html>

元素水平垂直居中

  • 绝对定位
    • 已知盒子宽高,margin为负的一半
    • 为止盒子宽高,transform:translate(-50%, -50%)
  • flex布局
  • grid布局
  • table-cell布局
table-cell布局


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .father {
      height: 300px;
      width: 300px;
      border: 1px solid black;
      display: table-cell; // ----------------------------- 父元素   display: table-cell
      vertical-align: middle; // -------------------------- 垂直居中 vertical-align: middle 
      text-align: center; // ------------------------------ 水平居中 text-align: center
      // 注意:
      // 1. 如果子元素的 ( 宽高已知 ),那么不需要( 父元素text-align: center ),而直接 ( 子元素margin: 0 auto );
      // 2. 如果子元素的 ( 宽高未知 ),( 父元素text-align: center );并且子元素设置 ( display: inline-block; )
    }
    .child {
      // height: 100px;
      // width: 100px;
      background: red; 
      display: inline-block; 
      // --------------------------- 注意: 这里的display: inline-block是必须的,因为宽高未知
      // --------------------------- 宽高已知,就用margin: 0 auto;而且父元素也不需要text-align:center;
    }
  </style>
</head>
<body>
  <div class="father">
    <div class="child">child</div>
  </div>
</body>
</html>
table-cell布局 - 不知道子元素的宽高

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .father {
      height: 300px;
      width: 300px;
      border: 1px solid black;
      display: table-cell;
      vertical-align: middle;
      text-align: center;
    }
    .child {
      background: red; 
      display: inline-block;
    }
  </style>
</head>
<body>
  <div class="father">
    <div class="child">child</div>
  </div>
</body>
</html>

  • grid 布局实现水平垂直居中
grid 布局实现水平垂直居中1 
---
.father {
  display: grid; // --------------------------------- display: grid;
  justify-items: center; // ------------------------- justify-items: center;
  align-items: center; // --------------------------- align-items: center;
}
.child {}
grid 布局实现水平垂直居中2
---
.father {
    display: grid;
}
.child {
    justify-self: center;
    align-self: center;
}

单行省略号 和 多行省略号

单行省略号 和 多行省略号

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .content1 { // ------------------------------------------ 单行省略号
      background: yellow;
      width: 200px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .content2 { // ------------------------------------------ 多行省略号
      background: red;
      width: 100px;
      overflow: hidden;
      display: -webkit-box; // ------------------------------ display: -webkit-box
      -webkit-box-orient: vertical; // ---------------------- 方向
      -webkit-line-clamp: 2; //------------------------------ 行数
    }
  </style>
</head>
<body>
  <div class="content1">
    单行省略号
    单行省略号
    单行省略号
    单行省略号
    单行省略号
  </div>
  <div class="content2">多行省略号,多行省略号,多行省略号,多行省略号</div>
</body>
</html>

word-wrap 和 word-break 的区别

  • word-wrap: break-word --------------------- 整个单词一次换行
  • word-break: break-all ----------------------- 单词内换行
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .word-wrap {
      word-wrap: break-word;
      width: 120px;
      background: yellow;
      margin: 10px;
    }
    .word-break {
      word-break: break-all;
      width: 120px;
      background: red;
      margin: 10px;
    }
  </style>
</head>
<body>
  <div class="word-wrap">abcdefgh go home sdfasdfasdfadfasdfasdfadfafd</div>
  <div class="word-break">abcdefgh go home sdfasdfasdfadfasdfasdfadfafd</div>
</body>
</html>

block,inline,inline-block

常见的块级元素: div, form, table, p, pre, h1~h6, dl, ol, ul,li等;
常见的内联元素有 span, a, img, input, textarea, i,strong, em, lable, select, br 等


1. block
  - 块级元素,独占一行
  - block元素可以设置宽,高等属性
  - block可以设置marginpadding属性
  - 默认情况下,block元素的宽度自动填满其父元素的宽度

2. inline
  - 不独占一行,多个相邻行内元素排列在同一行,直到排不下才换行
  - inline元素设置widthheight无效
  - inline元素设置margin,在水平方向有效,在垂直方向无效
  - inline元素设置padding对自身有效,但是在垂直方向上不能撑开父元素

3. inline-block
  - 同时具有block的特性可以设置宽度和高度属性,又具有line元素的不占一行的属性

双栏布局 - 左侧固定,右侧自适应

  • float
  • flex
  • 绝对定位
(1) 左侧固定,右侧自适应 - float布局
- 左侧flot: left; width = 200px;
- 右侧无需设置

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    html, body {
      width: 100%;
      height: 100%;
    }
    .container {
      width: 100%;
      height: 100%;
    }
    .left {
      background: red;
      height: 100%;
      float: left; // ------------------------ float: left
      width: 200px;
    }
    .right { // ------------------------------ 右侧 margin-left: 200px;
      margin-left: 200px; // ----------------- 这里必须设置的,不然在换行时会发生文字环绕
      background: yellow;
      height: 100%;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
  </div>
</body>
</html>
(2)左侧固定,右侧自适应 - flex布局


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    html, body {
      width: 100%;
      height: 100%;
    }
    .container {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: flex-start;
      align-items: flex-start;
    }
    .left {
      width: 200px;
      flex: 0 0 200px;
      background: red;
      height: 100%;
    }
    .right {
      flex: 1;
      background: yellow;
      height: 100%;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
  </div>
</body>
</html>
(3) 绝对定位
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    html, body {
      width: 100%;
      height: 100%;
    }
    .container {
      width: 100%;
      height: 100%;
      position: relative;
    }
    .left {
      background: red;
      height: 100%;
      width: 200px;
      position: absolute;
    }
    .right {
      position: absolute;
      left: 200px;
      right: 0;
      background: yellow;
      height: 100%;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
  </div>
</body>
</html>

三栏布局 - 圣杯布局

  • flex
  • 绝对定位
  • 浮动
圣杯布局 - flex

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    html, body {
      width: 100%;
      height: 100%;
    }
    .container {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: flex-start;
      align-items: flex-start;
    }
    .left {
      height: 100%;
      background: red;
      flex: 0 0 200px;
    }
    .center {
      height: 100%;
      background: blue;
      flex: 1;
    }
    .right {
      height: 100%;
      background: yellow;
      flex: 0 0 200px;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="left">left</div>
    <div class="center">center</div>
    <div class="right">right</div>
  </div>
</body>
</html>
圣杯布局 - 浮动


<div class="container">
    <div class="left"></div>
    <div class="right"></div>
    <div class="main"></div> ## main放最后
</div>

.left {
    float: left;
    width: 100px;
}
.right {
    width: 200px;
    float: right;
}
.main {
    margin-left: 120px;
    margin-right: 220px;
}
## 或者 触发bfc,BFC区域,不会与浮动元素重叠
.main {
    overflow: hidden;
}

position

  • static inherit absolute relative fixed
  • static :默认值,没有定位的意思
    • static:是静止的意思
  • inherit:规定应该从父元素继承 position 属性的值
    • inherit:是继承的意思
  • absolute
    • 绝对定位,必须要有 ( 参照物 ),脱离文档流
    • 该 ( 参照物 ) 必须具有 ( 定位属性 ),并且两者要具有 ( 包含 ) 关系
    • 如果找不到具有定位属性且是包含关系的参照物,则会相对于 浏览器窗口进行定位
  • relative
    • 相对定位,参照物是元素偏移前的位置,左右 margin为auto仍然有效、并且不会脱离文档流
  • fixed
    • 窗口定位
  • absolute 和 fixed 的区别:
    • 当出现滚动条时,fixed定位的元素不会跟随滚动条滚动,absolute绝对定位会跟随滚动条滚动
  • sticky
    • 该属性可以用纯css的方式实现吸顶效果 - ceiling
    • 粘性定位,是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位
    • 设置了position: sticky的元素并不脱离文档流,仍然保留元素原本在文档流中的位置。
      • 当元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置。亦即如果你设置了top: 50px,那么在sticky元素到达距离相对定位的元素顶部50px的位置时固定,不再向上移动(相当于此时fixed定位)。
      • 元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素
      • 如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量。
      .wrap {position: relative;}
      .ceiling {position: sticky;top: 0;}
      

盒模型

  • 分为标准盒模型,ie盒模型
  • box-sizing
    • content-box 标准盒模型 --- 宽高包括:content
    • border-box ie盒模型 ------- 宽高包括:content,padding,border
    • inherit 继承

@import 和 link 的区别

  • 从属关系
    • @import是css语法 - 只有导入样式的作用
    • link是html标签 - 除了加载css,还可以设置link标签的其他属性,比如RSS,rel
  • 加载顺序
    • link标签引入的css和页面一起加载 - 先
    • @import引入的css将在页面加载完成后才会被加载 - 后
  • 兼容性
    • @import是css2的语法,ie5上才可用 - 兼容性差
    • link是html标签,不存在兼容性 - 兼容性好
  • 权重
    • link引入的样式 权重 大于@import引入的样式
  • DOM可控性
    • js操作DOM,可以插入link标签,但是不能插入@import

资料

sticky-footer juejin.im/post/684490…
sticky-footer aotu.io/notes/2017/…

BFC zhuanlan.zhihu.com/p/25321647
BFC juejin.im/entry/68449…
BFC www.w3ctrain.com/2016/03/28/…
BFC www.jianshu.com/p/7e04ed3f4…
CSS选择器 juejin.im/entry/68449…
伪元素 伪类动画 (全) zhuanlan.zhihu.com/p/36502282
伪元素 伪类动画 www.haorooms.com/post/css_wl…
伪元素 伪类动画 segmentfault.com/a/119000000…
行内块级元素有间隙 juejin.im/post/684490…
媒体查询 zhuanlan.zhihu.com/p/26882107
rem布局:juejin.im/post/684490…
rem布局原理:juejin.im/entry/68449…
rem不不不巨巨巨:juejin.im/post/684490…
rem juejin.im/post/684490…
rem可用:juejin.im/post/684490…
两栏三栏布局:juejin.im/post/684490…