CSS 总结

164 阅读16分钟

css

calc()

  • 语法
    • width:calc(100% - 80px);
    • 此calc()函数用一个表达式作为它的参数,用这个表达式的结果作为值。
    • 此表达式可以是(+ - * /)操作符的组合,规定运算符的左右必须有空白符。
  • 例子
    • /* 使用指定的外边距指定一个对象 */
      .banner {
        position: absolute;
        /* fallback for browsers which still doesn't support for `calc()` */
        left: 5%;
        width: 90%;
        /* overwrite, if the browsers support for `calc()`*/
        left: calc(40px);
        width: calc(100% - 80px);
        border: 1px solid black;
        background-color: #f00;
        text-align: center;
      }
      
    • <div class="banner">this is a banner</div>
      
    • /* 设置内部元素不超出外部元素的范围 */
      input{
        padding: 2px;
        display: block;
        width: 98%;
        /* fallback for browsers without support for calc() */
        width: calc(100% - 1em);
      }
      #formbox {
        width: 130px;
        /* fallback for browsers without support for calc() */
        width: calc(100% / 6);
        border: 1px solid black;
        padding: 4px;
      }
      
    • <form>
        <div id="formbox">
        <label>Type something:</label>
        <input type="text">
        </div>
      </form>
      
    • /* 使用CSS变量来嵌套 calc() */
      .foo {
        --widthA: 100px;
        --widthB: calc(var(--widthA) / 2);
        --widthC: calc(var(--widthB) / 2);
        width: var(--widthC);
        /* 在所有的变量都被展开后, widthC 的值就会变成 calc( calc( 100px / 2) / 2),
      	简而言之:一个 calc() 里面的 calc() 就仅仅相当于是一个括号。  
        */
      }
      

视口单位 vw、vh

  • pc端,视口指的是浏览器的可视区域。
  • 移动端,涉及三个视口:Layout Viewport(布局视口)、Visual Viewport(视觉视口)、Ideal Viewport(理想视口)。
  • 视口单位的“视口”,pc端指浏览器的可视区域;移动端指Layout Viewport。
    • 视口单位主要包括以下4个:
      • vw: 1vw等于视口宽度的1%
      • vh: 1vh等于视口高度的1%
      • vmin: 选取vw、vh中最小的那个
      • vmax: 选取vw、vh中最大的那个
    • vh和vw:相对于视口的高度和宽度,而不是父元素的。
    • /* 
      	比如:浏览器高度950px,宽度为1920px, 
      	1 vh = 950px/100 = 9.5 px,1vw = 1920px/100 =19.2 px。 
      */
      .left {
              float: left;
              width: 50vw;
              height: 20vh;
              background-color: blue;
              text-align: center;
              line-height: 20vh;
              font-size: 3rem
       }
      
       .right {
              float: right;
              width: 50vw;
              height: 20vh;
              background-color: green;
              text-align: center;
              line-height: 20vh;
              font-size: 3rem
       }
      

BFC

  1. what is BFC?

BFC: 块级格式上下文

以下条件都会为他们的内容创建新的BFC

  • 浮动元素
  • 绝对/固定定位元素
  • 非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions
  • 以及overflow值不为"visiable"的块级盒子
  1. BFC 渲染规则
  • 两个块同一个BFC会造成外边距折叠
  • BFC的区域不会与浮动元素的box重叠
  • BFC是一个独立的容器,外面的元素不会影响里面的元素
  • 计算BFC高度的时候浮动元素也会参与计算
  1. 应用场景
  • 防止浮动导致父元素高度塌陷

  • 避免外边距折叠 两个块同一个BFC会造成外边距折叠,如果对这两个块分别设置BFC,那么边距重叠的问题就不存在了。

position

  1. css布局的三种机制

页面布局的核心:使用CSS来摆放盒子的位置

css提供了3种机制来设置盒子的摆放位置,分别是:普通流、浮动、定位

  1. 普通流(标准流):

    • 页面内的标签元素按照从上到下,从左到右的顺序排列
  2. 浮动:

    • 让盒子从普通流中浮起来,多个盒子(div)水平排列成一行
  3. 定位:

    • 将盒子定在一个位置,可以使其漂浮在其它盒子上面,而不影响其它盒子
  4. 认识定位

概念:定位 = 定位模式 + 边偏移,将盒子定在某一位置

  1. 边偏移:

    • top:定义元素相对于其父元素上边线的距离
    • bottom:定义元素相对于其父元素下边线的距离
    • left:定义元素相对于其父元素左边线的距离
    • right:定义元素相对于其父元素右边线的距离
    1. 边偏移需要和定位模式联合使用,单独使用无效
    2. top和bottom不能同时使用
    3. left和right不能同时使用
  2. 定位模式(分类): 选择器 {position: 属性值 }

    • static:静态定位,默认定位方式
    • relative:相对定位,自恋,相对于其原标准流的位置进行定位
    • absolute:绝对定位,拼爹,相对于其上一个已定位的父元素定位
    • fixed:固定定位,浏览器,相对于浏览器窗口定位
    • sticky:粘性定位,relative和fixed的结合体
  3. 定位模式间的区别

    • 静态定位(static) 元素默认的定位方式,不脱标,且边偏移无效
    • 相对定位(relative) 相对定位不脱标
      1. 以自己在标准流位置左上角为基点 +边偏移属性定位元素的位置
      2. 原来在标准流中的区域继续占有,后面的盒子仍以标准流方式对待它 与浮动对比
      • 浮动:多个块级元素在一行显示,脱离标准流
      • 相对定位:移动盒子位置,不脱标
    • 绝对定位(absolute) 有两个重要概念:
      1. 完全脱标,不占位置
      2. 父元素要有定位(相对、绝对、固定定位) 定位口诀:子绝父相
    • 固定定位(fixed) 完全脱标,不占位置 只认浏览器的可视窗口
    • 粘性定位(sticky) relative + fixed
  4. 定位的扩展(position)

3.1. 绝对定位的盒子居中

绝对定位不能通过设置`margin:auto设置水平居中

  1. 水平居中
  2. 垂直居中
  3. 水平垂直居中

3.2. 粘性定位

example: MDN

当元素在屏幕内,表现为relative,就要滚出显示器屏幕时,表现为fixed

<style>
  article {
    max-width: 600px;
    margin: 0 auto;
  }
  article h4,
  article footer {
    position: -webkit-sticky;
    position: sticky;
  }
  article h4 {
    top: 0;
    z-index: 1;
  }
  article footer {
    bottom: 50vh;
    z-index: -1;
  }
</style>

<article>
  <section>
    <h4>123</h4>
    <content>...</content>
    <footer>321</footer>
  </section>
  <section>
    <h4>456</h4>
    <content>...</content>
    <footer>654</footer>
  </section>
</article>
  1. 堆叠顺序(z-index)

在使用定位布局时,可能出现盒子堆叠的情况

应用z-index层叠等级属性来调整盒子的堆叠顺序

z-index的特性如下:

  1. 属性值:正整数、负整数、0;默认值为0,值越大,盒子越靠上
  2. 属性值相同,按照书写顺序,后来者居上
  3. 数字后无单位
  4. 只能用于相对定位、绝对定位、固定定位的元素,其它元素无效

REM 布局

rem布局的核心就是设置好根元素的font-size

  1. rem计算
  • 适配过程 width: 640px;
    1. 人为将UI的psd图等分(20份)
    2. 计算一份的宽度1rem = 640/20 = 32px
    3. 设置html根元素的font-size = 32px;
    4. 页面中css的尺寸统一使用rem单位表示
  1. less 语法

2.1. 介绍

less预处理器: 依然使用css语法,引入变量,混合,运算,嵌套等功能,简化css编写,降低维护成本

2.2. 变量

  • 语法:@变量名:值 @sz: 100px; p { font-size: @sz; } // 可运算 h2 { font-size: @sz - 2; }

2.3. 嵌套

.box {
  p {
    font-size: 14px;
  }
  ul {
    list-style: none;
    li {
      float: left;
    }
  }
}

2.4. 混合(函数)

  • 定义和调用 // 定义: #函数名() {} / .函数名() {} #public() { width: 200px; height: 200px; } .public() { width: 200px; height: 200px; } div { // 调用 #public() } h2 { .public() }
  • 传参/默认值 #public(@w:200px, @h:200px) { width: @w; height: @h; } div { #public(500px, 600px) }

2.5. 在浏览器中预览less文件

  • 在html中引入less文件 /** 引入less文件 **/
  • 在html中引入less.js文件 // 引入less.js文件
  1. 媒体查询
  • 媒体查询 通过查询当前属于哪种设备,让网页能够在不同设备下正常预览
  • 媒体类型 将不同的设备划分为不同的类型,称为媒体类型
    • all 所有设备
    • print 打印设备
    • screen 电脑/平板/手机屏幕
  • 媒体特性
    • width
    • height
    • max-width / max-height
    • min-width / min-height
  • 语法关键字 @media not|only 媒体类型 and (特性条件)
    • and: 将多个媒体特性链接到一块,相当于且

    • not: 排除某个媒体特性,相当于非,可省略

    • only: 指定某个特定的媒体类型,可省略 /** 通过不同的屏幕大小设置 font-size */

      /* 功能:计算1rem等于多少font-size的大小 参数: @w 表示屏幕的宽度 @c 表示分割的份数 */ .adapter(@w,@c) { html { font-size: @w/@c; } }

      @media screen and (width:320px) { .adapter(320px,20); }

      @media screen and (width:360px) { .adapter(360px,20); } ...

  1. 实战项目

  2. 目录结构

    index.html css --adapter.css --adapter.less --base.css --index.css --index.less

  3. index.html

    Document
     <!-- 全场优惠S -->
     <div class="all-special">
       <!-- 标题 -->
       <div class="title">
         <h4 class="fl">全场优惠</h4>
         <span class="fr">1/1</span>
       </div>
       <!-- 内容 -->
       <div class="content">
         <!-- 上 -->
         <div class="top">
           <p>全场满300减10</p>
           <p>双十一特价优惠全场满就减</p>
           <p><span class="icon-time"></span>14-11-12 20:12 至 14-11-12 23:12</p>
           <a href="#">即将开始</a>
           <img src="./images/sale.png" alt="">
         </div>
         <!-- 下 -->
         <div class="bottom">
           <a href="#">
             <span class="icon-edit"></span>编辑
           </a>
           <i></i>
           <a href="#">
             <span class="icon-share"></span>分享
           </a>
         </div>
       </div>
     </div>
     <!-- 全场优惠E -->
    
  4. adapter.less

    /* 功能:计算1rem等于多少font-size的大小 参数: @w 表示屏幕的宽度 @c 表示分割的份数 */ .adapter(@w,@c) { html { font-size: @w/@c; } }

    @media screen and (width:320px) { .adapter(320px,20); } @media screen and (width:360px) { .adapter(360px,20); } @media screen and (width:375px) { .adapter(375px,20); } @media screen and (width:414px) { .adapter(414px,20); } @media screen and (width:412px) { .adapter(412px,20); }

  5. index.less

    .main { width: 100%; max-width: 640px; min-width: 320px; margin:0 auto; } // 默认按照640/20 html { font-size: 32px; }

    // 顶部导航 .top-title { img { width: 100%; } }

    // ----------------------将有关的尺寸全部转换为rem------------------------

    // 全场优惠 .all-special { padding:0 26/32rem; // 标题 .title { height: 78/32rem; line-height: 78/32rem; font-size: 28/32rem; span { color: #666; } } // 下 .bottom { height: 80/32rem; background: #fff; display: flex; i { height: 48/32rem; width: 1px; background: #666; display: block; margin-top: 15/32rem; } a { flex: 1; text-align: center; line-height: 80/32rem; font-size: 26/32rem; span { color: #55bc75; } } } } }

移动端1px解决方案

产生原因: DPR(devicePixelRatio) 设备像素比

  • window.devicePixelRatio = 物理像素/css像素

目前主流屏幕DPR=2(iphone8)、3(iphone 8 pluse)

设备的物理像素要实现1px,而DPR=2,故css的像素只能是0.5

ios 8+系统支持,安卓系统不支持

一、使用box-shadow实现***

box-shadow: 0  -1px 1px -1px #e5e5e5,   //上边线
            1px  0  1px -1px #e5e5e5,   //右边线
            0  1px  1px -1px #e5e5e5,   //下边线
            -1px 0  1px -1px #e5e5e5;   //左边线

优点: 使用简单,圆角可实现

缺点: 模拟实现

二、使用伪元素

  • 单条border .set-onepx { position: relative; &::after { content: ''; position: absolute; display: block; background-color: #000; width: 100%; height: 1px; transform: scale(1, 0.5); // Y方向缩小0.5倍 top: 0; left: 0; } }
  • 四条border .set-onepx-all { position: relative; &::after { content: ''; position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform-origin: left top; transform: scale(0.5); box-sizing: border-box; border: 1px solid #000; border-radius: 4px; } }
  • 总结:
    1. 全机型兼容,实现了真正的1px,而且可以圆角
    2. 暂用了after伪元素,影响清除浮动

三、设置viewport的scale值*

利用viewport + rem + js实现

<html>
  <head>
      <title>1px question</title>
      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
      <meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">        
      <style>
          html {
              font-size: 1px;
          }            
          * {
              padding: 0;
              margin: 0;
          }
          .top_b {
              border-bottom: 1px solid #E5E5E5;
          }
          .a,.b {
              box-sizing: border-box;
              margin-top: 1rem;
              padding: 1rem;                
              font-size: 1.4rem;
          }
          .a {
              width: 100%;
          }
          .b {
              background: #f5f5f5;
              width: 100%;
          }
      </style>
      <script>
          var viewport = document.querySelector("meta[name=viewport]");
          //下面是根据设备像素设置viewport
          if (window.devicePixelRatio == 1) {
              viewport.setAttribute('content', 'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');
          }
          if (window.devicePixelRatio == 2) {
              viewport.setAttribute('content', 'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');
          }
          if (window.devicePixelRatio == 3) {
              viewport.setAttribute('content', 'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');
          }
          var docEl = document.documentElement;
          var fontsize = 32* (docEl.clientWidth / 750) + 'px';
          docEl.style.fontSize = fontsize;
      </script>
  </head>
  <body>
      <div class="top_b a">下面的底边宽度是虚拟1像素的</div>
      <div class="b">上面的边框宽度是虚拟1像素的</div>
  </body>
</html>

CSS3

一、2D 转换

可实现元素的位移、旋转、缩放、倾斜

  1. translate-位移

语法: transform:translate(x,y)

  • 代码 盒子居中总结 .box { position: relative; width: 600px; height: 600px; } .item1 { position: absolute; width: 100px; height: 100px; background: #0f0; /* 方案一 / / left: 0; right: 0; top: 0; bottom: 0; margin: auto; / / 方案二 / / left: 50%; top: 50%; margin-left: -50px; margin-top: -50px; / / 方案三 */ left: 50%; top: 50%; transform: translate(-50%, -50%); }
  • 总结
    1. translate最多设置两个值,x水平,y垂直
    2. translate偏移的位置,参照自身原有的位置
    3. translate设置负值,会实现逆向移动
    4. 设置一个值,只有水平方向有效
    5. 可以设置百分比,百分比参照的是自身的大小
  • 轮子滚动
  1. rotate-旋转

语法: transform:rotate(+-deg)

  • 代码 .item { width: 100px; height: 100px; /* 顺时针45deg, 逆时针-45deg */ transform: rotate(-90deg); background: #000; }

  • 总结

    1. 单位: deg
    2. 正值: 顺时针
    3. 负值: 逆时针
  1. transform-origin: 旋转源点

语法: transform-origin: 水平 垂直;

  • 代码 .item { transform-origin: left top; }
  • 总结
    1. 默认按照中心点旋转
    2. 水平: left|center|right|px|%
    3. 垂直: top|center|bottom|px|%
  1. scale-缩放

语法: transform:scale(number,number);

  • 代码 .item { width: 100px; height: 100px; margin: 100px auto; transform: scale(2); background: #000; }
  • 总结
    1. 最多设置两个值,第一个表缩放宽度,第二个表高度
    2. 0~1 表缩小,>1 表放大
    3. 只有一个值,表示宽高一起缩放
  1. skew-倾斜

语法: transform:skew(deg,deg);

  • 代码 .item { width: 100px; height: 100px; margin: 100px auto; transform: skew(45deg, 0deg); background: #000; }
  • 总结
    1. 值1表示左右倾斜,值2表示上下倾斜
    2. 单位deg,可以是负值

二、3D 转换

  1. 位移

语法:

  • transform: translateX(100px);

  • transform: translateY(100px);

  • transform: translateZ(100px);

  • 代码

  • 总结

    1. perspective:px;设置3D透视,可实现进大远小
    2. 给设置了transform属性元素的上级设置
  1. 透视

语法: perspective:600px;

  • 总结
    1. 设置3D透视,可实现近大远小
    2. 主要给设置了transform属性元素的上级元素设置透视
  1. 旋转

语法: 围绕XYZ轴旋转

  1. transform: rotateX(deg)
  2. transform: rotateY(deg)
  3. transform: rotateZ(deg)
  • 代码

  • 立方体案例 body: 设置 perspective:1000px;实现近大远小效果 父元素.box: 设置

    1. transform-style:preserve-3d;通知浏览器此元素按照3D效果渲染
    2. transition: 2s;开启过渡效果 XYZ轴: 永远都是顺时针旋转为正

三、动画-animation

语法:

  1. animation-name: name(动画名称);
  2. animation-duration: 时间(s/ms);
  3. animation-timing-function: linear(匀速)|ease(慢快慢)|ease-in(缓慢开始)|ease-out(缓慢结束)ease-in-out(慢开慢结);
  4. animation-delay: 时间(s/ms);
  5. animation-iteration-count: 次数|infinite(无限);
  6. animation-play-state: paused(暂停)|running(运行);
  7. animation: name 1s infinite 3s linear;
  • 实例-地图大数据热点

    ```html
      <div class="origin">
        <span class="shire shire1"></span>
        <span class="shire shire2"></span>
      </div>
    

浏览器的回流与重绘(Reflow&Repaint)

一、写在前面

预备知识

  1. 浏览器使用流式布局模型(Flow Based Layout)
  2. 浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了Render Tree
  3. 有了Render Tree,我们就知道了所有节点的样式,然后计算它们在页面上的大小和位置,最后把节点绘制到页面上
  4. 由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,它们可能需要多次计算,通常要花3倍同等元素的时间,因此要避免使用table布局

一句话: 回流必将引起重绘,重绘不一定会引起回流

二、回流 (Reflow)

当Render Tree中部分或全部元素的尺寸、结构或某些属性发生变化时,浏览器重新渲染部分或全部文档的过程称为回流

  • 会导致回流的操作:
    • 页面首次渲染
    • 浏览器窗口大小发生改变
    • 元素尺寸或位置改变
    • 元素内容变化(文字数量/图片大小等)
    • 元素字体大小变化
    • 添加或删除可见的DOM元素
    • 激活CSS伪类(如: :hover...)
    • 查询某些属性或调用某些方法
  • 一些常用且会导致回流的属性和方法:
    • clientWidth、clientHeight、clientTop、clientLeft
    • offsetWidth、offsetHeight、offsetTop、offsetLeft
    • scrollWidth、scrollHeight、scrollTop、scrollLeft
    • scrollIntoView()、scrollIntoViewIfNeeded()
    • getComputedStyle()
    • getBoundingClientRect()
    • scrollTo()

三、重绘 (Repaint)

当页面中元素样式的改变并不影响它在文档流中的位置时(如: color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,此过程称为重绘

四、性能影响

回流比重绘的代价要更高

  1. 有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也要产生回流
  2. 现代浏览器会对频繁的回流或重绘操作进行优化
  3. 浏览器会维护一个队列,将所有引起回流和重绘的操作放入队列中,当队列中的任务数量或时间间隔达到一个阈值时,浏览器将会清空队列,进行一次批处理,这样可将对此回流和重绘变成一次

当访问以下属性后方法时,浏览器会立刻清空队列:

因为队列中可能会有影响到这些属性或方法返回值的操作,所以浏览器会强行清空队列,确保获取的值是最精确的

  • clientWidth、clientHeight、clientTop、clientLeft
  • offsetWidth、offsetHeight、offsetTop、offsetLeft
  • scrollWidth、scrollHeight、scrollTop、scrollLeft
  • width、height
  • getComputedStyle()
  • getBoundingClientRect()

五、如何避免

CSS

  1. 避免使用table布局
  2. 尽可能在DOM树的最末端改变class
  3. 避免设置多层内联样式
  4. 将动画效果应用到position属性为absolute或fixed的元素上
  5. 避免使用css表达式(如: calc())

JavaScript

  1. 避免频繁操作样式,最好一次性重写style属性,或将样式列表定义为class并一次性更改class属性
  2. 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中
  3. 也可以先为元素设置display:none; 操作结束后再把它显示出来。因为在display属性为none的元素上进行DOM操作不会引发回流和重绘
  4. 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来
  5. 对具有复杂动画的元素使用绝对定位absolute,使其脱离文档流,否则就会引起父元素及后续元素频繁回流