CSS详解(下)

502 阅读37分钟

前言

大四应届生,已经签好工作了,准备七月份入职,细细算来学习前端已经一年有余,感觉日子真是不经过啊。现在趁着大四最后一点时光,重新将之前学过的基础知识捡起来,为入职做准备,也希望给刚入行的新人带来一些启发。

一、 CSS高级技巧

1.1 精灵图

1.1.1 为什么需要精灵图?

一个网页中往往会应用很多小的背景图像作为修饰,当网页中的图像过多时,服务器就会频繁地接收和发送 请求图片,造成服务器请求压力过大,这将大大降低页面的加载速度。

因此,为了有效地减少服务器接收和发送请求的次数,提高页面的加载速度,出现了 CSS 精灵技术(也称 CSS Sprites、CSS 雪碧)。

核心原理:将网页中的一些小背景图像整合到一张大图中 ,这样服务器只需要一次请求就可以了。

精灵技术目的:为了有效地减少服务器接收和发送请求的次数,提高页面的加载速度。

1.1.2 精灵图(sprites)的使用

使用精灵图核心:

  1. 精灵技术主要针对于背景图片使用。就是把多个小背景图片整合到一张大图片中

  2. 这个大图片也称为 sprites 精灵图 或者 雪碧图

  3. 移动背景图片位置以控制显示区域, 此时可以使用 background-position

  4. 移动的距离就是这个目标图片的 xy 坐标。注意网页中的坐标有所不同

  5. 通过PxCook测量小图片左上角坐标,分别取负值设置给盒子的background-position:x y

  6. 使用精灵图的时候需要精确测量每个小背景图片的大小和位置

  7. 精灵图一般使用行内标签 使用精灵图步骤:

  8. 创建一个盒子,设置盒子的尺寸大小和和精灵图中小图的大小相同

  9. 将精灵图设置为盒子的背景图片

  10. 修改背景图的位置 background-position

  11. 一般情况下精灵图都是负值(千万注意网页中的坐标: x轴右边走是正值,左边走是负值, y轴同理)

【王者荣耀案例】

20210420081150387.png

<!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>精灵图使用</title>
    <style>
        .box1 {
            width: 60px;
            height: 60px;
            margin: 100px auto;
            background: url(images/sprites.png) no-repeat -182px 0;

        }

        .box2 {
            width: 27px;
            height: 25px;
            /* background-color: pink; */
            margin: 200px;
            background: url(images/sprites.png) no-repeat -155px -106px;

        }
    </style>
</head>

<body>
    <div class="box1"></div>
    <div class="box2"></div>
</body>

</html>

202104200817544.png

1.1.3 案例:拼单词

20210420081150457.jpg

<!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>利用精灵图拼出自己名字</title>
    <style>
        span {
            display: inline-block;
            background: url(images/abcd.jpg) no-repeat;
        }

        .p {
            width: 100px;
            height: 112px;
            /* background-color: pink; */
            background-position: -493px -276px;
        }

        .i {
            width: 60px;
            height: 108px;
            /* background-color: pink; */
            background-position: -327px -142px;
        }

        .n {
            width: 115px;
            height: 112px;
            /* background-color: pink; */
            background-position: -255px -275px;
        }

        .k {
            width: 105px;
            height: 114px;
            /* background-color: pink; */
            background-position: -495px -142px;
        }
    </style>
</head>

<body>
    <span class="p">p</span>
    <span class="i">i</span>
    <span class="n">n</span>
    <span class="k">k</span>
</body>

</html>

20210420083302981.png

1.2 字体图标

1.2.1 字体图标的产生

字体图标使用场景:主要用于显示网页中通用、常用的一些小图标。

精灵图是有诸多优点的,但是缺点很明显。

  1. 图片文件还是比较大的
  2. 图片本身放大和缩小会失真
  3. 一旦图片制作完毕想要更换非常复杂

此时,有一种技术的出现很好的解决了以上问题,就是字体图标 iconfont。

字体图标可以为前端工程师提供一种方便高效的图标使用方式,展示的是图标,但本质却属于字体。

1.2.2 字体图标的优点

  • 轻量级:一个图标字体要比一系列的图像要小。一旦字体加载了,图标就会马上渲染出来,减少了服务器请求
  • 灵活性:本质其实是文字,可以很随意的改变颜色、产生阴影、透明效果、旋转等
  • 兼容性:几乎支持所有的浏览器,请放心使用

注意: 字体图标不能替代精灵技术,只是对工作中图标部分技术的提升和优化。

总结:

  1. 如果遇到一些结构和样式比较简单的小图标,就用字体图标
  2. 如果遇到一些结构和样式复杂一点的小图片,就用精灵图

字体图标是一些网页常见的小图标,我们直接网上下载即可。 因此使用可以分为:

  1. 字体图标的下载
  2. 字体图标的引入(引入到我们 html 页面中)
  3. 字体图标的追加(在原有的基础上添加新的小图标)

1.2.3 字体图标的下载

推荐下载网站:

IcoMoon 成立于 2011 年,推出了第一个自定义图标字体生成器,它允许用户选择所需要的图标,使它们成一字型。该字库内容种类繁多,非常全面,唯一的遗憾是国外服务器,打开网速较慢。

这个是阿里妈妈 M2UX 的一个 iconfont 字体图标字库,包含了淘宝图标库和阿里妈妈图标库。可以使用 AI 制作图标上传生成。 重点是,免费!

以下内容以 iconfont 字库 为例。

1.2.4 字体图标的引入

  1. 进入 iconfont 之后选择素材库中的官方图标库(这个是免费的,而且完全够用)
  2. 进入后选择合适的图标添加入库
  3. 添加完成之后,鼠标下滑网页右侧会显示出购物车图标,点击进入
  4. 进入后可以看到你添加的各种图标,可以选择新建项目或者添加进原有项目
  5. 然后在资源管理--我的项目中查看,然后选择下载至本地
  6. 文件解压后, 将 iconfont.ttficonfont.css两个文件拖入项目中的font文件夹下
  7. 导入样式文件,注意是font文件夹下的iconfont.css文件
<link rel="stylesheet" href="./font/iconfont.css" />
  1. html 标签内添加小图标,一般建议放在 <span></span> 标签里。
  2. span标签添加类名,注意:必须调用2个类名
//iconfont类:第一个为固定的类名,基本样式:包含字体的使用等 // icon-xxx:图标对应的类名
 <span class="iconfont icon-copy"></span>

如果工作中,原来的字体图标不够用了,我们便需要添加新的字体图标到原来的字体文件中,添加购物车完毕后重新下载至本地,用新文件夹代替旧文件夹。

<!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>字体图标基本使用-类名</title>
    <link rel="stylesheet" href="./font/iconfont.css" />
    <style>
     /* 本质是文字,可更改颜色,字体大小等
      .iconfont {
        font-size: 60px;
        color: aqua;
      }
      */
       
       /* 可以直接赋给标签类名改变样式,尽量不要使用iconfont类名更改样式,因为它是全部改变 */
      .zgc{
        font-size: 60px;
        color: aqua;
      }
    </style>
  </head>
  <body>
    <span class="iconfont icon-copy zgc"></span>
  </body>
</html>

Snipaste_2022-06-21_11-18-34.png

可以打开font文件夹下的demo_index.html文件查看类名和使用方法

1.2.5 字体图标的上传

思考:如果图标库没有项目所需的图标怎么办?

答:IconFont网站上传矢量图生成字体图标。

  1. 与设计师沟通,得到SVG矢量图
  2. IconFont网站上传图标,下载使用

Snipaste_2022-06-21_11-36-14.png

1.2.6 字体图标加载的原理

服务器只需接受一次浏览器请求便可以将 fonts 文件一次性返回,如此而来网页中所有用到 fonts 字体图标的部分便一次性加载好了,大大减轻了服务器压力。

1.3 网络字体

字体网站 网络字体意思是除了系统自带的字体之外的特殊字体.

  1. 网络字体他先是根据你给的地址,先下载到浏览器,然后在浏览器上应用.
  2. 字体的格式分别有:ttf, otf, eot, svg, svgz, woff,等等,这些格式有些浏览器是不支持的,所以我们添加字体的时候需要多添加几种字体格式,以便适配更多的浏览器.
  3. 添加字体只能是多添加几种字体的格式,而不是多种字体.如果需要多种字体,那么就需要把下载字体和应用字体的代码再写一遍进行添加.

应用代码:

   <style>
        @font-face {
            font-family: "zgc"; /*这里的zgc是我们给字体的名字*/
            src: url("字体路径"), /* 可以是本地路径,可以是网络路径*/
                url("另外一种格式的字体路径"),
                url("另外一种格式的字体路径");
        }
        p{
            /* 由font-family应用我们刚刚引入的字体 */
            font-family: "zgc";
        }
    </style>
</head>
<body>
    <p>我是一个段落</p>
/* 加载一种字体格式 */
@font-face{
  font-family: "zgc";
  src: url('./font.ttf') format('truetype');
}

/* 加载多个字体格式,兼容更多浏览器 */
/* `format`用于帮助浏览器快速识别该字体是什么格式 */
 @font-face{
    font-family: "zgc";
    src: url('./font.eot'); /* IE9, 注意这个src: url后面不是',' 而是';'*/
    src: url('./font.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('./font.woff') format('woff'), /* chrome、firefox */
    url('./font.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
    url('./font.svg#uxfonteditor') format('svg'); /* iOS 4.1- */
    font-style: normal;
    font-weight: normal;
}

1.4 CSS三角

网页中常见一些三角形,使用 CSS 直接画出来就可以,不必做成图片或者字体图标。

20210420102851826.png

CSS 三角是怎么来的?原理如下:

对一个没有大小的盒子设置边框,那么只要边框足够粗,就可以呈现三角效果。

如果只需要一个三角,那么对其他三个边框设置透明色即可。

通常 CSS 三角要配合定位来布局。

<!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>CSS 三角制作</title>
    <style>
        .box1 {
            width: 0;
            height: 0;
            /* border: 10px solid pink; */
            border-top: 30px solid hotpink;
            border-right: 30px solid black;
            border-bottom: 30px solid skyblue;
            border-left: 30px solid gray;
        }

        .box2 {
            width: 0;
            height: 0;
            border: 50px solid transparent;
            border-left-color: black;
            margin: 50px;
        }

        .jd {
            /* 子绝父相 */
            position: relative;
            width: 120px;
            height: 249px;
            background-color: black;
        }

        .jd span {
            /* 子绝父相 */
            position: absolute;
            right: 15px;
            top: -20px;
            width: 0;
            height: 0;
            /* 下面两行为了照顾兼容性 */
            line-height: 0;
            font-size: 0;
            border: 10px solid transparent;
            border-bottom-color: black;
        }
    </style>
</head>

<body>
    <div class="box1"></div>
    <div class="box2"></div>
    <div class="jd">
        <span></span>
    </div>
</body>

</html>

20210420104336278.png

1.5 CSS用户界面样式

1.5.1 什么是界面样式

所谓的界面样式,就是更改一些用户操作样式,以提高更好的用户体验。

  • 更改用户的鼠标样式
  • 表单轮廓
  • 防止表单域拖拽

1.5.2 鼠标样式 cursor

li { cursor: pointer; }

设置或检索在对象上移动的鼠标指针采用何种系统预定义的光标形状。

属性值描述
auto浏览器根据环境自动切换
default箭头
pointer小手
move十字移动
text文本竖杠
not-allowed禁止

注意:除了以上类型,还有其他很多类型。

<!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>用户界面样式-鼠标样式</title>
</head>

<body>
    <ul>
        <li style="cursor: default;">我是鼠标箭头样式</li>
        <li style="cursor: pointer;">我是鼠标小手样式</li>
        <li style="cursor: move;">我是鼠标移动样式</li>
        <li style="cursor: text;">我是鼠标文本样式</li>
        <li style="cursor: not-allowed;">我是鼠标禁止样式</li>
    </ul>
</body>

</html>

2021042011003289.gif

1.5.3 轮廓线 outline

给表单添加 outline: 0; 或者 outline: none; 样式之后,就可以去掉默认的边框。

input { outline: none; }

默认样式:

20210420111135354.gif

修改后样式:

<!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>轮廓线 outline</title>
    <style>
        input {
            /* 取消表单轮廓 */
            outline: none;
        }
    </style>
</head>

<body>
    <!-- 取消表单轮廓 -->
    <input type="text">
</body>

</html>

20210420111315285.gif

1.5.4 防止拖拽文本域 resize

实际开发中,我们文本域右下角是不允许拖拽的。(会破坏布局!)

textarea { resize: none; }

默认样式:

2021042011203862.gif

修改后样式:

<!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>防止拖拽文本域 resize</title>
    <style>
        textarea {
            /* 取消表单轮廓 */
            outline: none;
            /* 防止拖拽文本域 */
            resize: none;
        }
    </style>
</head>

<body>
    <!-- 防止拖拽文本域 -->
    <!-- <textarea></textarea>起始标签建议放在一行,因为这样不会导致文本域里文字前有空白,
    后期可以专门通过 padding 来设置文本周围的留白 -->
    <textarea name="" id="" cols="30" rows="10"></textarea>
</body>

</html>

202104201120370.gif

1.6 vertical-align 属性应用

CSS 的 vertical-align 属性使用场景:经常用于设置图片或者表单(行内块元素)与文字垂直对齐。

记住:只要是图片/表单等行内块元素在垂直方向上对不齐,就用vertical-align

官方解释:用于设置一个元素的垂直对齐方式,但是它只针对于行内元素或者行内块元素有效。

语法:

vertical-align: baseline | top | middle | bottom
描述
baseline默认。元素放置在父元素的基线上
top把元素的顶端与行中最高元素的顶端对齐
middle把此元素放置在父元素的中部
bottom把元素的顶端与行中最低的元素的顶端对齐

20210420124542850.png

1.6.1 图片、表单和文字对齐

图片、表单都属于行内块元素,默认的 vertical-align 是基线对齐。

此时可以给图片、表单这些行内块元素的 vertical-align 属性设置为 middle 就可以让文字和图片垂直居中对齐了。

<!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>利用vertical-align实现图片文字垂直居中对齐</title>
    <style>
        img {
            /* vertical-align: bottom; */
            /* 让图片和文字垂直居中 */
            vertical-align: middle;
            /* vertical-align: top; */
        }

        textarea {
            vertical-align: middle;
        }
    </style>
</head>

<body>
    <img src="images/ldh.jpg" alt=""> pink老师是刘德华

    <br>
    <textarea name="" id="" cols="30" rows="10"></textarea> 请您留言
</body>

</html>

20210420124932560.png

1.6.2 解决图片底部默认空白缝隙问题

图片底侧会有一个空白缝隙,原因是行内块元素会和文字的基线对齐。

20210420125635475.png

主要解决方法有两种:

  1. 给图片添加 vertical-align: middle | top | bottom 等(推荐)
  2. 把图片转换为块级元素 display: block;
<!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>图片底侧空白缝隙解决方案</title>
    <style>
        div {
            border: 2px solid black;
        }

        img {
            vertical-align: middle;
            /* display: block;因为图片、表单都属于行内块元素,默认的 vertical-align 是基线对齐,
            将其转化成块级元素,就不会出这种问题了*/
        }
    </style>
</head>

<body>
    <div>
        <img src="images/ldh.jpg" alt="">
    </div>
</body>

</html>

20210420125750954.png

我们知道,当对盒子设置 line-height: 盒子高度; 时,盒子内的 文字 会垂直居中,其实不只是文字可以垂直居中,盒子内的图片同样也能垂直居中,只不过图片默认是基于基线对齐的,所以要真正实现图片的 垂直居中 ,除了要在盒子上加上line-height:盒子高度之外,还需要在图片上加上:vertical-align: middle;

1.7 溢出的文字省略号显示

1.7.1 单行文本溢出省略号显示

三个必要条件:

/* 1. 先强制一行内显示文本 */ 
white-space: nowrap; 	/*( 默认 normal 自动换行)*/ 
/* 2. 超出的部分隐藏 */ 
overflow: hidden; 
/* 3. 文字用省略号替代超出的部分 */ 
text-overflow: ellipsis;

案例:

<!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>单行文本溢出显示省略号</title>
    <style>
        div {
            width: 150px;
            height: 80px;
            background-color: pink;
            margin: 100px auto;
            /* 这个单词的意思是如果文字显示不开自动换行 */
            /* white-space: normal; */
            /* 1.这个单词的意思是如果文字显示不开也必须强制一行内显示 */
            white-space: nowrap;
            /* 2.溢出的部分隐藏起来 */
            overflow: hidden;
            /* 3.文字溢出的时候用省略号来显示 */
            text-overflow: ellipsis;
        }
    </style>
</head>

<body>
    <div>
        啥也不说,此处省略一万字
    </div>
</body>

</html>

20210420132753998.png

1.7.2 多行文本溢出省略号显示

多行文本溢出显示省略号,有较大兼容性问题, 适合于 webkit 浏览器或移动端(移动端大部分是 webkit 内核)。

overflow: hidden;
text-overflow: ellipsis;
/* 弹性伸缩盒子模型显示 */
display: -webkit-box;
/* 限制在一个块元素显示的文本的行数 */
-webkit-line-clamp: 2;
/* 设置或检索伸缩盒对象的子元素的排列方式 */
-webkit-box-orient: vertical;

更推荐让后台人员来做这个效果,因为后台人员可以设置显示多少个字,操作更简单。

案例:

<!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>单行文本溢出显示省略号</title>
    <style>
        div {
            width: 150px;
            height: 65px;
            background-color: pink;
            margin: 100px auto;
            overflow: hidden;
            text-overflow: ellipsis;
            /* 弹性伸缩盒子模型显示 */
            display: -webkit-box;
            /* 限制在一个块元素显示的文本的行数 */
            -webkit-line-clamp: 3;
            /* 设置或检索伸缩盒对象的子元素的排列方式 */
            -webkit-box-orient: vertical;
        }
    </style>
</head>

<body>
    <div>
        啥也不说,此处省略一万字,啥也不说,此处省略一万字此处省略一万字
    </div>
</body>

</html>

Chrome 浏览器效果:

20210420132822674.png

二、 CSS3的新特性

2.1 CSS3的现状

  • 新增的 CSS3 特性有兼容性问题,IE9+ 才支持
  • 移动端支持优于 PC 端
  • 不断改进中
  • 应用相对广泛
  • 现阶段主要学习:新增选择器、盒子模型 以及 其他特性

2.2 CSS3新增选择器

CSS3 给我们新增了选择器,可以更加便捷,更加自由的选择目标元素。

  1. 属性选择器
  2. 结构伪类选择器
  3. 伪元素选择器

2.2.1 属性选择器

属性选择器可以根据元素特定属性来选择元素。这样就可以不用借助于类或者 id 选择器。

选择符简介
E[att]选择具有 att 属性的 E 元素
E[att="val"]选择具有 att 属性且属性值等于 val 的 E 元素
E[att^="val"]匹配具有 att 属性且值以 val 开头的 E 元素
E[arr$="val"]匹配具有 att 属性且值以 val 结尾的 E 元素
E[att*="val"]匹配具有 att 属性且值中含有 val 的 E 元素

注意:类选择器、属性选择器、伪类选择器,权重为 10。

<!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>CSS3新增属性选择器</title>
    <style>
      /* 选中必须是 input元素 同时具有 value 这个属性*/
      /*input[value] {*/
      /*    color: hotpink;*/
      /*}*/

      /* 可以不带元素, 这样表示选择所有具有value属性的元素 */
      /*[value] {*/
      /*    color: hotpink;*/
      /*}*/

      /* 只选择 type=text 文本框的 input 选取出来 */
      input[type="text"] {
        color: hotpink;
      }

      /* 选择首先是 div 然后具有 class 属性,并且属性值必须是 icon 开头的这些元素 */
      div[class^="icon"] {
        color: red;
      }

      /* 选择首先是 section 然后具有 class 属性,并且属性值必须是 data 结尾的这些元素 */
      section[class$="data"] {
        color: blue;
      }

      /* 类选择器 属性选择器 伪类选择器 权重都是 10 */
      div.icon1 {
        color: skyblue;
      }
    </style>
  </head>
  <body>
    <!-- 1. 利用属性选择器就可以不用借助于类或者 id 选择器 -->
    <!--<input type="text" value="请输入用户名">-->
    <!--<input type="text">-->
    <!-- 2. 属性选择器还可以选择属性=值的某些元素 重点务必掌握 -->
    <input type="text" name="" id="one" />
    <input type="password" name="" id="two" />
    <!-- 3. 属性选择器可以选择属性值开头的某些元素 -->
    <div class="icon1">小图标1</div>
    <div class="icon2">小图标2</div>
    <div class="icon3">小图标3</div>
    <div class="icon4">小图标4</div>
    <div>我是打酱油的</div>
    <!-- 4. 属性选择器可以选择属性值结尾的某些元素 -->
    <section class="icon1-data">我是安其拉</section>
    <section class="icon2-data">我是哥斯拉</section>
    <section class="icon3-ico">哪我是谁</section>
  </body>
</html>

20210423145746508.gif

2.2.2 结构伪类选择器

nth-child(n) 选择某个父元素的一个或多个特定的子元素(重点)。

  • n 可以是数字,关键字和公式
  • n 如果是数字,就是选择第 n 个子元素,里面数字从 1 开始……
  • n 可以是关键字:even 偶数,odd 奇数
  • n 可以是公式:常见的公式如下(如果 n 是公式,则从 n = 0 开始计算,但是第 0 个元素和超出了元素的个数会被忽略)
公式取值
2n偶数(2、4、6、……)
2n+1奇数(1、3、5、……)
5n5 10 15...
n+5从第 5 个开始(包含第 5 个)到最后
-n+5前 5 个(包含第 5 个)

结构伪类选择器主要根据文档结构来选择元素,常用于根据父级来选择其子元素。

选择器简介
E:first-child匹配父元素中的第一个子元素 E
E:last-child匹配父元素中最后一个 E 元素
E:nth-child(n)匹配父元素中的第 n 个子元素 E
E:first-of-type指定类型 E 的第一个
E:last-of-type指定类型 E 的最后一个
E:nth-of-type(n)指定类型 E 的第 n 个

区别:

  1. nth-child 对父元素里面所有孩子排序选择(序号是固定的) 先找到第 n 个孩子,然后看看是否和 E 匹配
  2. nth-of-type 对父元素里面指定子元素进行排序选择。 先去匹配 E,然后再根据 E 找第 n 个孩子

小结:

  • 结构伪类选择器一般用于选择父级里面的第几个孩子
  • nth-child 对父元素里面所有孩子排序选择(序号是固定的) 先找到第 n 个孩子,然后看看是否和 E 匹配
  • nth-of-type 对父元素里面指定子元素进行排序选择。 先去匹配 E,然后再根据 E 找第 n 个孩子
  • 若父元素内都是同一种标签(如:列表),优先用 nth-child,否则就只能使用 nth-of-type
  • 类选择器、属性选择器、伪类选择器,权重为 10
<!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>CSS3新增结构伪类选择器</title>
    <style>
        /* 1. 选择 ul 里面的第一个孩子 小 li */
        ul li:first-child {
            background-color: pink;
        }

        /* 2. 选择 ul 里面的最后一个孩子 小 li */
        ul li:last-child {
            background-color: pink;
        }

        /* 3. 选择 ul 里面的第 2 个孩子 小 li */
        ul li:nth-child(2) {
            background-color: skyblue;
        }

        /* 3. 选择 ul 里面的第 6 个孩子 小 li */
        ul li:nth-child(6) {
            background-color: skyblue;
        }
    </style>
</head>
<body>
<ul>
    <li>我是第1个孩子</li>
    <li>我是第2个孩子</li>
    <li>我是第3个孩子</li>
    <li>我是第4个孩子</li>
    <li>我是第5个孩子</li>
    <li>我是第6个孩子</li>
    <li>我是第7个孩子</li>
    <li>我是第8个孩子</li>
</ul>
</body>
</html>

20210423150342544.png

<!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>CSS3新增结构伪类选择器-nth-child</title>
    <style>
        /* 1.把所有的偶数 even 的孩子选出来 */
        ul li:nth-child(even) {
            background-color: #ccc;
        }

        /* 2.把所有的奇数 odd 的孩子选出来 */
        ul li:nth-child(odd) {
            background-color: gray;
        }

        /* 3.nth-child(n) 从 0 开始每次加 1 往后面计算,这里面必须是 n,不能是其他的字母,此处选择了所有的孩子 */
        /* ol li:nth-child(n) {*/
        /*    background-color: pink;*/
        /*}*/
        /* 4.nth-child(2n) 母选择了所有的偶数孩子 等价于 even */
        /*ol li:nth-child(2n) {*/
        /*    background-color: pink;*/
        /*}*/
        /* 5.nth-child(2n+1) 母选择了所有的奇数孩子 等价于 odd */
        /*ol li:nth-child(2n+1) {*/
        /*    background-color: skyblue;*/
        /*} */
        /* 6.从第 3 个开始(包含第 3 个)到最后 */
        /*ol li:nth-child(n+3) {*/
        /*    background-color: pink;*/
        /*} */
        /*7.前 3 个(包含第 3 个)*/
        ol li:nth-child(-n+3) {
            background-color: pink;
        }
    </style>
</head>

<body>
<ul>
    <li>我是第1个孩子</li>
    <li>我是第2个孩子</li>
    <li>我是第3个孩子</li>
    <li>我是第4个孩子</li>
    <li>我是第5个孩子</li>
    <li>我是第6个孩子</li>
    <li>我是第7个孩子</li>
    <li>我是第8个孩子</li>
</ul>
<ol>
    <li>我是第1个孩子</li>
    <li>我是第2个孩子</li>
    <li>我是第3个孩子</li>
    <li>我是第4个孩子</li>
    <li>我是第5个孩子</li>
    <li>我是第6个孩子</li>
    <li>我是第7个孩子</li>
    <li>我是第8个孩子</li>
</ol>
</body>

</html>

20210423151246867.png

<!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>CSS3新增选择器nth-type-of</title>
    <style>
        ul li:first-of-type {
            background-color: pink;
        }

        ul li:last-of-type {
            background-color: pink;
        }

        ul li:nth-of-type(even) {
            background-color: skyblue;
        }

        /* nth-child 会把所有的盒子都排列序号 */
        /* 执行的时候首先看 :nth-child(1) 之后回去看 前面 div */
        /* 所以此处先排序:*/
        /* 1号:<p>光头强</p> */
        /* 2号:<div>熊大</div> */
        /* 3号:<div>熊二</div> */
        /* 再回过头看,此时会发现,1号并不是 div,所以不生效!*/

        section div:nth-child(1) {
            background-color: red;	/* 不生效 */
        }

        /* nth-of-type 会把指定元素的盒子排列序号 */
        /* 执行的时候首先看 div 指定的元素 之后回去看 :nth-of-type(1) 第几个孩子 */
        section div:nth-of-type(1) {
            background-color: blue;
        }
    </style>
</head>

<body>
<ul>
    <li>我是第1个孩子</li>
    <li>我是第2个孩子</li>
    <li>我是第3个孩子</li>
    <li>我是第4个孩子</li>
    <li>我是第5个孩子</li>
    <li>我是第6个孩子</li>
    <li>我是第7个孩子</li>
    <li>我是第8个孩子</li>
</ul>
<!-- 区别 -->
<section>
    <p>光头强</p>
    <div>熊大</div>
    <div>熊二</div>
</section>
</body>

</html>

20210423152631225.png

2.2.3 伪元素选择器(重点)

伪元素选择器是利用 CSS 创建新标签元素,而不需要 HTML 标签,从而简化 HTML 结构。

选择器简介
::before在元素内容的前面插入内容
::after在元素内容的后面插入内容
::first-line可以选中首行文本进行设置
::first-letter可以选中首字母或者第一个文字进行设置

注意:

  • before 和 after 创建一个元素,属于行内元素,想要设置宽高必须设置成块元素/行内块元素,或者浮动/定位
  • 新创建的这个元素在文档树中是找不到的,所以我们称为伪元素
  • 语法:element::before{}, element:要进行设置的元素
  • before 和 after 必须有 content 属性
  • before 在父元素内容的前面创建元素,after 在父元素内容的后面创建元素
  • ::: 的写法都对,但推荐::
  • 伪元素选择器和标签选择器一样,权重为 1

(1)伪元素选择器使用场景1:伪元素字体图标

p::before {
	position: absolute;
	right: 20px;
	top: 10px;
	content: '\e91e';
	font-size: 20px;
}

(2)伪元素选择器使用场景2:仿土豆效果

/* 当我们鼠标经过了 土豆这个盒子,就让里面 before 遮罩层显示出来 */
.tudou:hover::before {
	/* 而是显示元素 */
    display: block;
}

(3)伪元素选择器使用场景3:伪元素清除浮动

  1. 额外标签法也称为隔墙法,是 W3C 推荐的做法
  2. 父级添加 overflow 属性
  3. 父级添加 after 伪元素
  4. 父级添加双伪元素

额外标签法也称为隔墙法,是 W3C 推荐的做法。

20210423160929744.png

注意:要求这个新的空标签必须是块级元素。

后面两种伪元素清除浮动算是第一种额外标签法的一个升级和优化。

.clearfix:after {
	content: "";			/* 伪元素必须写的属性 */
	display: block;			/* 插入的元素必须是块级 */
	height: 0;				/* 不要看见这个元素 */
	clear: both;			/* 核心代码清除浮动 */
	visibility: hidden;		/* 不要看见这个元素 */
}
.clearfix:before,
.clearfix:after {
	content: "";
	display: table;			/* 转换为块级元素并且一行显示 */
}

.clearfix:after {
	clear: both;
}

案例:

<!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>伪元素选择器before和after</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: salmon;
        }

        /* div::before 权重是 2 */
        div::before {
            /* 这个 content 是必须要写的 */
            /* display: inline-block; */
            content: '我';
            /* width: 30px;
            height: 40px;
            background-color: purple; */
        }

        div::after {
            content: '小猪佩奇';
        }
    </style>
</head>
<body>
<div></div>
</body>
</html>

20210423153316679.gif

<!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>伪元素选择器使用场景-字体图标</title>
    <style>
        @font-face {
            font-family: 'icomoon';
            src: url('fonts/icomoon.eot?1lv3na');
            src: url('fonts/icomoon.eot?1lv3na#iefix') format('embedded-opentype'),
            url('fonts/icomoon.ttf?1lv3na') format('truetype'),
            url('fonts/icomoon.woff?1lv3na') format('woff'),
            url('fonts/icomoon.svg?1lv3na#icomoon') format('svg');
            font-weight: normal;
            font-style: normal;
            font-display: block;
        }

        div {
            position: relative;
            width: 200px;
            height: 35px;
            border: 1px solid red;
        }

        div::after {
            position: absolute;
            top: 10px;
            right: 10px;
            font-family: 'icomoon';
            /* content: ''; */
            content: '\e91e';
            color: red;
            font-size: 18px;
        }
    </style>
</head>

<body>
<div></div>
</body>

</html>

20210423153507576.png

<!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>伪元素选择器使用场景2-仿土豆网显示隐藏遮罩案例</title>
    <style>
        .tudou {
            position: relative;
            width: 444px;
            height: 320px;
            background-color: pink;
            margin: 30px auto;
        }

        .tudou img {
            width: 100%;
            height: 100%;
        }

        .tudou::before {
            content: '';
            /* 隐藏遮罩层 */
            display: none;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, .4) url(images/arr.png) no-repeat center;
        }

        /* 当我们鼠标经过了土豆这个盒子,就让里面 before 遮罩层显示出来 */
        .tudou:hover::before {
            /* 而是显示元素 */
            display: block;
        }
    </style>
</head>

<body>
<div class="tudou">
    <img src="images/tudou.jpg" alt="">
</div>
</body>

</html>

20210423153911315.gif

2.3 CSS3盒子模型

CSS3 中可以通过 box-sizing 来指定盒模型,有 2 个值:即可指定为 content-box、border-box,这样我们计算盒子大小的方式就发生了改变。

可以分成两种情况:

  1. box-sizing: content-box 盒子大小为 width + padding + border (以前默认的)
  2. box-sizing: border-box 盒子大小为 width

如果盒子模型我们改为了 box-sizing: border-box, 那 padding 和 border 就不会撑大盒子了(前提 padding 和 border 不会超过 width 宽度)

<!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>CSS3盒子模型</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        div {
            width: 200px;
            height: 200px;
            background-color: pink;
            border: 20px solid red;
            padding: 15px;
            box-sizing: content-box;
        }

        p {
            width: 200px;
            height: 200px;
            background-color: pink;
            border: 20px solid red;
            padding: 15px;
            /* css3 盒子模型 盒子最终的大小就是 width 200 的大小 */
            box-sizing: border-box;
        }
    </style>
</head>
<body>
<div>
    小猪乔治
</div>
<p>
    小猪佩奇
</p>
</body>
</html>

20210423154934685.gif

2.4 圆角边框

CSS 3 新增了圆角边框样式。

border-radius 属性用于设置元素的外边框圆角。

语法:

border-radius: length; length是圆的半径长度

原理:

border-radius 顾名思义:边框半径。

(椭)圆与边框的交集形成圆角效果。

20210407171139155.jpg

<!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>圆角边框</title>
    <style>
        div {
            width: 300px;
            height: 150px;
            background-color: pink;
            border-radius: 24px;
        }
    </style>
</head>

<body>
    <div></div>
</body>

</html>

20210407171251321.jpg

注意:

  • 参数值可以为数值或百分比的形式
  • 如果是正方形,想要设置为圆形,那么只需要把数值修改为高度或者宽度的一半即可,或者直接写为 50%
  • 如果是个矩形,设置为高度的一半就可以做 “胶囊” 效果了
  • 该属性是一个简写属性,可以跟多个值
    • 四个值:左上角、右上角、右下角、左下角(从左上开始顺时针)
    • 三个值:左上、右上+左下、右下(对角为一组)
    • 两个值:左上+右下、右上+左下(对角为一组)
  • 同时可以对特定角单独设置
    • 左上角:border-top-left-radius
    • 右上角:border-top-right-radius
    • 右下角:border-bottom-right-radius
    • 左下角:border-bottom-left-radius
<!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>圆角边框常用写法</title>
    <style>
        .yuanxing {
            width: 200px;
            height: 200px;
            background-color: pink;
            /* border-radius: 100px; */
            /* 50% 就是宽度和高度的一半  等价于 100px */
            border-radius: 50%;
        }

        .juxing {
            width: 300px;
            height: 100px;
            background-color: pink;
            /* 圆角矩形设置为高度的一半 */
            border-radius: 50px;
        }

        .radius {
            width: 200px;
            height: 200px;
            /* border-radius: 10px 20px 30px 40px; */
            /* border-radius: 10px 40px; */
            border-top-left-radius: 20px;
            background-color: pink;
        }
    </style>
</head>

<body>
    1. 圆形的做法:
    <div class="yuanxing"></div>
    2. 圆角矩形的做法:
    <div class="juxing"></div>
    3. 可以设置不同的圆角:
    <div class="radius"></div>
</body>

</html>

20210407172402316.jpg

2.5 盒子阴影

CSS 3 新增了盒子阴影。

box-shadow 属性用于为盒子添加阴影。可以设置一个或者多个阴影, 多个阴影用逗号隔开, 从后叠加到前.

语法:

box-shadow: h-shadow v-shadow blur spread color inset;
描述
h-shadow必须。水平阴影偏移的距离,正数向右偏移, 允许负值(左偏移)。
v-shadow必须。垂直阴影偏移的距离,正数向下偏移, 允许负值(上偏移)。
blur可选。模糊程度(虚实程度)。
spread可选。扩散阴影。 (四边同时扩散)
color可选。阴影的颜色,请参阅 CSS 颜色值(阴影多为半透明颜色)。
inset可选。将外部阴影(outset)改为内部阴影(outset 不能指定,默认为空即可)。
<!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>盒子阴影</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: salmon;
            margin: 100px auto;
            /* box-shadow: 10px 10px; */
        }

        /* 伪类不仅仅可以用于 a 链接,还能用于其他标签 */
        /* 原先盒子没有影子,当我们鼠标经过盒子就添加阴影效果 */
        div:hover {
            box-shadow: 10px 10px 10px -4px rgba(0, 0, 0, .3);
        }
    </style>
</head>

<body>
    <div></div>
</body>

</html>

20210407181220613.gif

同时设置多个阴影

<!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>盒子阴影</title>
    <style>
      div {
        width: 200px;
        height: 200px;
        margin: 100px auto;
        background-color: salmon;
        box-shadow: 10px 10px 10px -4px rgba(0, 0, 0, 0.3), 5px 5px 20px 10px rgba(255, 0, 0, 0.3);
       }
    </style>
  </head>

  <body>
    <div></div>
  </body>
</html>

image.png

2.6 文字阴影

CSS 3 新增了文字阴影。

text-shadow 属性用于为文本添加阴影, 可以设置一个或者多个阴影, 多个阴影用逗号隔开, 从后叠加到前。

语法:

text-shadow: h-shadow v-shadow blur color;
描述
h-shadow必须。水平阴影的位置。允许负值。
v-shadow必须。垂直阴影的位置。允许负值。
blur可选。模糊的距离(虚实程度)。
color可选。阴影的颜色。参阅 CSS 颜色值。
<!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>文字阴影</title>
    <style>
        div {
            font-size: 50px;
            color: salmon;
            font-weight: 700;
            text-shadow: 5px 5px 6px rgba(0, 0, 0, .3);
        }
    </style>
</head>

<body>
    <div>
        你是阴影,我是火影
    </div>
</body>

</html>

20210407182002202.jpg

2.7 CSS3其他特性

2.7.1 CSS3滤镜 filter

filter CSS 属性将模糊或颜色偏移等图形效果应用于元素。

filter: 函数(); 例如:filter: blur(5px); blur 模糊处理,数值越大越模糊

20210423161020807.png

图片变模糊

<!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>图片模糊处理filter</title>
    <style>
        img {
            /* blur 是一个函数 小括号里面数值越大,图片越模糊 注意数值要加 px 单位 */
            filter: blur(15px);
        }

        img:hover {
            filter: blur(0);
        }
    </style>
</head>
<body>
<img src="images/pink.jpg" alt="">
</body>
</html>

20210423155143395.gif

2.7.2 CSS3 calc 函数

calc() 此 CSS 函数让你在声明 CSS 属性值时执行一些计算。

width: calc(100% - 80px);

括号里面可以使用 + - * / 来进行计算。 计算盒子宽度 width:calc 函数

<!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>CSS3属性calc函数</title>
    <style>
        .father {
            width: 500px;
            height: 500px;
            background-color: black;
        }

        .son {
            /* width: 300px; */
            /* width: calc(500px - 100px); */
            /* 符号的左右两边要有空白符 */
            width: calc(100% - 100px);
            height: 200px;
            background-color: salmon;
        }
    </style>
</head>
<body>
<!-- 需求:我们的子盒子宽度永远比父盒子小 100 像素 -->
<div class="father">
    <div class="son"></div>
</div>
</body>
</html>

20210423155710297-164235395082836.png

2.7.3 CSS3变量 -- var

var() 函数用于插入自定义的属性值,如果一个属性值在多处被使用,该方法就很有用。

css中可以自定义属性

  • 属性名需要以两个减号(--)开始
  • 属性值则是任意有效的css值

语法:

  • custom-property-name : 必须, 自定义属性的名称,必须以 -- 开头。
  • value: 可选, 备用值,在属性不存在的时候使用。
 var(custom-property-name, value) 

实例:

 /* 选择器 `:root` 匹配文档的根元素。在 HTML 中,根元素始终是 html 元素,除了优先级更高之外,
 与 `html` 选择器相同。 */
 :root {
    --main-bg-color: coral;
    --main-txt-color: blue;
    --main-padding: 15px;
  }

  #div1 {
    background-color: var(--main-bg-color);
    color: var(--main-txt-color);
    padding: var(--main-padding);
  }

  #div2 {
    background-color: var(--main-bg-color);
    color: var(--main-txt-color);
    padding: var(--main-padding);
  }

2.8 CSS3过渡

2.8.1 过渡

过渡(transition)是 CSS3 中具有颠覆性的特征之一,我们可以在不使用 Flash 动画或 JavaScript 的情况下,当元素从一种样式变换为另一种样式时为元素添加效果。

过渡动画:是从一个状态渐渐的过渡到另外一个状态。

可以让我们页面更好看,更动感十足,虽然低版本浏览器不支持(IE9 以下版本) 但是不会影响页面布局。

我们现在经常和 :hover 一起搭配使用。

语法:

transition: 要过渡的属性 花费时间 运动曲线 何时开始;
  1. 属性:想要变化的 css 属性,宽度高度、背景颜色、内外边距都可以 。如果想要所有的属性都变化过渡,写一个 all 就可以
  2. 花费时间:单位是秒(必须写单位)比如 0.5s
  3. 运动曲线:默认是 ease(可以省略)
  4. 何时开始:单位是秒(必须写单位)可以设置延迟触发时间默认是 0s(可以省略)

2021042316110482.png

记住过渡的使用口诀:谁做过渡给谁加!

<!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>CSS3过渡效果</title>
    <style>
        div {
            width: 200px;
            height: 100px;
            background-color: black;
            /* transition: 变化的属性 花费时间 运动曲线 何时开始; */
            /* transition: width .5s ease 0s, height .5s ease 1s; */
            /* 如果想要写多个属性,利用逗号进行分割 */
            /* transition: width .5s, height .5s; */
            /* 如果想要多个属性都变化,属性写 all 就可以了 */
            /* transition: height .5s ease 1s; */
            /* 谁做过渡,给谁加 */
            transition: all 0.5s;
        }

        div:hover {
            width: 400px;
            height: 200px;
            background-color: gray;
        }
    </style>
</head>
<body>
<div></div>
</body>
</html>

20210423160022413.gif

2.8.2 进度条案例

<!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>CSS3过渡练习-进度条</title>
    <style>
        .bar {
            width: 150px;
            height: 15px;
            border: 1px solid red;
            border-radius: 7px;
            padding: 1px;
        }

        .bar_in {
            width: 50%;
            height: 100%;
            border-radius: 7px;
            background-color: red;
            /* 谁做过渡给谁加 */
            transition: all .7s;
        }

        .bar:hover .bar_in {
            width: 100%;
        }
    </style>
</head>
<body>
<div class="bar">
    <div class="bar_in"></div>
</div>
</body>
</html>

20210423160237686.gif

三、 CSS3动画

3.1 CSS3 2D转换

转换(transform)是 CSS3 中具有颠覆性的特征之一。可以实现元素的位移、旋转、缩放等效果。

转换(transform)你可以简单理解为变形。

  • 移动:translate
  • 旋转:rotate
  • 缩放:scale

注意: 并非所有的元素都可以进行transform的转换(通常行内级元素不能进行形变)

3.1.1 二维坐标系

2D 转换是改变标签在二维平面上的位置和形状的一种技术,先来学习二维坐标系。

20210424224831926.png

3.1.2 2D 转换之移动 translate

2D 移动是 2D 转换里面的一种功能,可以改变元素在页面中的位置,类似定位。

20210424225359665.png

语法:

transform: translate(x, y); 
/* 或者分开写 */
transform: translateX(n);
transform: translateY(n);

重点:

  • 定义 2D 转换中的移动,沿着 X 和 Y 轴移动元素
  • translate 最大的优点:不会影响到任何其他元素的位置(元素移动之后还占有原来的位置, 同时不会影响其他元素的位置[有点像相对定位])
  • translate 中的百分比单位是相对于自身元素的尺寸计算 translate: (50%, 50%);
  • 对行内元素没有效果
  • translate()如果只给出一个值, 表示x轴方向移动距离
  • 单独设置某个方向的移动距离:translateX() & translateY()
<!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>2D转换之移动translate</title>
    <style>
        /* 移动盒子的位置:定位、盒子的外边距、2D转换移动 */

        div {
            width: 200px;
            height: 200px;
            background-color: hotpink;
            /* x就是x轴上移动位置,y就是y轴上移动位置,中间用英文逗号分隔 */
            /* transform: translate(x, y); */
            /* transform: translate(100px, 100px); */
            /* 1. 只移动x坐标 */
            /* transform: translate(100px, 0); */
            /* transform: translateX(100px); */
            /* 2. 只移动y坐标 */
            /* transform: translate(0, 100px); */
            /* transform: translateY(100px); */
        }

        div:first-child {
            transform: translate(30px, 30px);
        }

        div:last-child {
            background-color: black;
        }
    </style>
</head>

<body>
    <div></div>
    <div></div>
</body>
</html>

20210424230655649.png

3.1.3 2D 转换之旋转 rotate

2D 旋转指的是让元素在 2 维平面内顺时针旋转或者逆时针旋转。

2021042500110849.png

语法:

transform: rotate(度数)

重点:

  • rotate 里面跟度数,单位是 deg,比如 rotate(45deg)
  • 角度为正时,顺时针;负时,逆时针
  • 默认旋转的中心点是元素的中心点
<!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>2D转换之旋转rotate</title>
    <style>
        img {
            width: 150px;
            /* 顺时针旋转45度 */
            /* transform: rotate(45deg); */
            border-radius: 50%;
            border: 5px solid pink;
            /* 过渡写到本身上,谁做动画给谁加 */
            transition: all 0.5s;
        }

        img:hover {
            transform: rotate(360deg);
        }
    </style>
</head>

<body>
<img src="media/pic.jpg" alt="">
</body>

</html>

2021042500182360.gif

<!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>旋转三角</title>
    <style>
        div {
            position: relative;
            width: 249px;
            height: 35px;
            border: 1px solid #000;
        }

        /* 三角可以通过盒子来制作,不一定非得字体图标 */
        /* 让一个旋转45度的正方形(菱形)的两个边框显示出来 */
        div::after {
            content: "";
            position: absolute;
            top: 8px;
            right: 15px;
            width: 10px;
            height: 10px;
            border-right: 1px solid #000;
            border-bottom: 1px solid #000;
            transform: rotate(45deg);
            transition: all 0.2s;
        }

        /* 鼠标经过 div 里面的三角旋转 */
        div:hover::after {
            transform: rotate(225deg);
        }
    </style>
</head>

<body>
<div></div>
</body>

</html>

20210425075729489.gif

3.1.4 转换中心点 transform-origin

我们可以设置元素转换的中心点。

语法:

transform-origin: x y;

重点:

  • 注意后面的参数 x 和 y 用空格隔开
  • x y 默认转换的中心点是元素的中心点(50% 50%)--百分比参照盒子自身的尺寸
  • 还可以给 x y 设置 像素 或者 方位名词(top bottom left right center)
<!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>transform-origin</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            margin: 100px auto;
            transition: all 1s;
            /* 1.可以跟方位名词 */
            /* transform-origin: left bottom; */
            /* 2. 默认的是 50% 50% 等价于 center center */
            /* 3. 可以是 px 像素 */
            transform-origin: 25px 25px;
        }

        div:hover {
            transform: rotate(360deg);
        }
    </style>
</head>

<body>
<div></div>
</body>

</html>

20210425081548859.gif

<!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>旋转中心点</title>
    <style>
        div {
            /* 溢出隐藏 */
            overflow: hidden;
            width: 200px;
            height: 200px;
            border: 1px solid pink;
            margin: 10px;
            float: left;
        }

        div::before {
            content: "黑马";
            display: block;
            width: 100%;
            height: 100%;
            background-color: hotpink;
            transform: rotate(180deg);
            transform-origin: left bottom;
            transition: all 0.4s;
        }

        /* 鼠标经过 div 里面的 before 复原 */
        div:hover::before {
            transform: rotate(0deg);
        }
    </style>
</head>

<body>
<div></div>
<div></div>
<div></div>
</body>

</html>

20210425082315183.gif

3.1.5 2D 转换之缩放 scale

缩放,顾名思义,可以放大和缩小。只要给元素添加上了这个属性就能控制它放大还是缩小。

语法:

transform: scale(x, y);

注意:

  • 注意其中的 x 和 y 用逗号分隔
  • transform: scale(1, 1) :宽和高都放大一倍,相当于没有放大
  • transform: scale(2, 2) :宽和高都放大了 2 倍
  • transform: scale(2) :只写一个参数,第二个参数默认等于第一个参数,相当于 scale(2, 2)
  • transform: scale(0.5, 0.5) :缩小
  • scale 缩放最大的优势:可以设置缩放的基准点(默认以中心点缩放);并且缩放不会影响其他盒子的位置(以上两个特点都是直接设置 width 和 height 都无法做到的)
<!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>2D转换之缩放</title>
    <style>
      .container {
        margin: 100px auto;
        border: 5px solid red;
        /* 可以设置缩放的中心点 */
        /* transform-origin: left bottom; */
      }

      .box {
        /* 1. 里面写的数字不跟单位 就是倍数的意思, 1 就是 1 倍;2 就是 2 倍 */
        /* transform: scale(x, y); */
        /* transform: scale(2, 2); */
        /* 2. 修改了宽度为原来的 2 倍,高度不变 */
        /* transform: scale(2, 1); */
        /* 3. 等比例缩放 同时修改宽度和高度,我们有简单的写法以下是宽度修改了 2 倍,高度默认和第一个参数一样 */
        /* transform: scale(2); */
        /* 4. 我们可以进行缩小,小于 1就是缩小 */
        /* transform: scale(0.5, 0.5); */
        /* transform: scale(0.5); */
        
        /* 5. scale 的优势之处:而且可以设置缩放的中心点 */
        /*
          直接设置宽高时无法做到以上优点的!
          width: 300px;
          height: 300px;
        */
        width: 200px;
        height: 200px;
        background-color: forestgreen;
         /* 放大与缩小不会影响其他的盒子 */
        transform: scale(0.6);
      }
      
      .box:hover {
        transform: scale(2, 2);
      }
    </style>
  </head>

  <body>
    <div class="container">
      <div class="box"></div>
    </div>
  </body>
</html>

image.png

image.png

<!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>图片放大案例</title>
    <style>
        div {
            width: 225px;
            height: 137px;
            overflow: hidden;
            float: left;
            margin: 10px;
        }

        div img {
            transition: all .4s;
        }

        div img:hover {
            transform: scale(1.1);
        }
    </style>
</head>

<body>
<div>
    <a href="#"><img src="media/scale.jpg" alt=""></a>
</div>
<div>
    <a href="#"><img src="media/scale.jpg" alt=""></a>
</div>
<div>
    <a href="#"><img src="media/scale.jpg" alt=""></a>
</div>
</body>
 
</html>

20210425085900832.gif

<!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>
        li {
            float: left;
            width: 30px;
            height: 30px;
            border: 1px solid hotpink;
            margin: 10px;
            text-align: center;
            line-height: 30px;
            list-style: none;
            border-radius: 50%;
            cursor: pointer;
            transition: all .4s;
        }

        li:hover {
            transform: scale(1.2);
        }
    </style>
</head>

<body>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
</ul>
</body>

</html>

20210425090230504.gif

3.1.6 2D 转换综合写法 -- 多重转换

注意:

  1. 同时使用多个转换,其格式为:transform: translate() rotate() scale() ...等
  2. 其顺序会影转换的效果。(先旋转会改变坐标轴方向)
  3. 当我们同时有位移和其他属性的时候,记得要将位移放到最前
<!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>
        div {
            width: 200px;
            height: 200px;
            background-color: pink;
            transition: all 1s;
        }

        div:hover {
            /* transform: rotate(180deg) translate(150px, 50px); */
            /* 我们同时有位移和其他属性,我们需要把位移放到最前面 */
            transform: translate(150px, 50px) rotate(180deg) scale(1.2);
            /* 层叠性 --一个标签中同时写两个transform只有最后一个生效*/
            /* transform: translate(600px);
            transform: rotate(360deg); */
        }
    </style>
</head>

<body>
<div></div>
</body>

</html>

readme-164241763228313.gif

3.1.7 2D 转换总结

  • 转换 transform 我们简单理解就是变形,有 2D 和 3D 之分
  • 我们暂且学了三个,分别是:位移、旋转 和 缩放
  • 2D 移动 translate(x, y) 最大的优势是不影响其他盒子,里面参数用 %,是相对于自身宽度和高度来计算的
  • 可以分开写比如 translateX(x) 和 translateY(y)
  • 2D 旋转 rotate(度数) 可以实现旋转元素,度数的单位是 deg
  • 2D 缩放 sacle(x, y) 里面参数是数字,不跟单位,可以是小数。最大的优势在于不影响其他盒子
  • 设置转换中心点 transform-origin : x y; 参数可以百分比、像素或者是方位名词
  • 当我们进行综合写法,同时有位移和其他属性的时候,记得要将位移放到最前

3.2 CSS3 动画

动画(animation)是 CSS3 中具有颠覆性的特征之一,可通过设置多个节点来精确控制一个或一组动画,常用来实现复杂的动画效果。

相比较过渡,动画可以实现多个状态间的变化过程,过程可控(重复播放、最终画面、是否暂停)。

3.2.1 动画的基本使用

制作动画分为两步:

  1. 先定义动画
  2. 再使用(调用)动画

3.2.1.1 用 @keyframes 定义动画(类似定义类选择器)

@keyframes 动画名称 {
   0% {
        width: 100px;
   }  
   50% {
        width: 200px;
   }
   100% {
        width: 300px;
   }
}

动画序列

  • 0% 是动画的开始,100% 是动画的完成。这样的规则就是动画序列
  • 在 @keyframes 中规定某项 CSS 样式,就能创建由当前样式逐渐改为新样式的动画效果
  • 动画是使元素从一种样式逐渐变化为另一种样式的效果。您可以改变任意多的样式任意多的次数
  • 请用百分比来规定变化发生的时间,或用关键词 "from" 和 "to",等同于 0% 和 100%
  • 如果动画的开始状态与盒子的默认样式是相同的,可以省略开始状态的代码
 @keyframes run {
 /* 省略开始*/
      100% {
        background-position: -1680px 0;
      }
    }

3.2.1.2 元素使用动画

div {
	width: 200px;
	height: 200px;
	background-color: aqua;
	margin: 100px auto;
	/* 调用动画 */
	animation-name: 动画名称;
	/* 持续时间 */
	animation-duration: 持续时间;
}

3.2.1.3 案例

<!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>CSS3动画的基本使用</title>
    <style>
        /* 我们想页面一打开,一个盒子就从左边走到右边 */
        /* 1. 定义动画 */
        @keyframes move {
            /* 开始状态 */
            0% {
                transform: translateX(0px);
            }
            /* 结束状态 */
            100% {
                transform: translateX(1000px);
            }
        }

        div {
            width: 200px;
            height: 200px;
            background-color: pink;
            /* 2. 调用动画 */
            /* 动画名称 */
            animation-name: move;
            /* 持续时间 */
            animation-duration: 2s;
        }
    </style>
</head>

<body>
<div></div>
</body>

</html>

20210425104436533.gif

<!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>动画序列</title>
    <style>
        /* from to 等价于 0% 和 100% */
        /*
        @keyframes move {
            from {
                transform: translate(0, 0);
            }
            to {
                transform: translate(1000px, 0);
            }
        }
        */

        /* 动画序列 */
        /* 1. 可以做多个状态的变化 keyframe 关键帧 */
        /* 2. 里面的百分比要是整数 */
        /* 3. 里面的百分比是动画总时长的占比 */
        @keyframes move {
            0% {
                transform: translate(0, 0);
            }
            25% {
                transform: translate(1000px, 0)
            }
            50% {
                transform: translate(1000px, 500px);
            }
            75% {
                transform: translate(0, 500px);
            }
            100% {
                transform: translate(0, 0);
            }
        }

        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            animation-name: move;
            animation-duration: 10s;
        }
    </style>
</head>

<body>
<div>

</div>
</body>

</html>

20210425103016385.gif

3.2.2 动画常用属性

属性描述
@keyframes规定动画
animation所有动画属性的简写属性,除了animation-play-state 属性
animation-name规定 @keyframes 动画的名称(必须的)
animation-duration规定动画完成一个周期所花费的秒或毫秒,即动画时长(必须的)
animation-timing-function规定动画的速度曲线,默认是 “ease”
animation-delay规定动画何时开始,默认是 0,即立即开始执行
animation-iteration-count规定动画被播放的次数,可以是数字,默认是 1,还有 infinite(无限循环)
animation-direction规定动画是否在下一周期逆向播放,默认是 "normal", alternate 逆播放
animation-play-state规定动画是否正在运行或暂停。默认是 "running", 还有 "paused"
animation-fill-mode规定动画结束后状态,保持完成forwards;回到起始backwards(默认值),需要去掉执行次数与动画方向

3.2.3 动画简写属性

animation:动画名称 持续时间 运动曲线 延迟时间 播放次数 动画方向 动画结束后的状态。

animation: move 5s linear 2s infinite alternate;
  • 必须包括 动画名称 持续时间 两个属性
  • 取值不分先后顺序
  • 如果有2个时间值,第一个时间表示动画时长,第二个时间表示延迟时间
  • 简写属性里面不包含 animation-play-state
  • 暂停动画:animation-play-state: puased; 经常和鼠标经过等其他配合使用
  • 想要动画走回来,而不是直接跳回来:animation-direction: alternate
  • 盒子动画结束后,停在结束位置:animation-fill-mode: forwards
<!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>动画属性</title>
    <style>
        @keyframes move {
            0% {
                transform: translate(0, 0);
            }
            100% {
                transform: translate(1000px, 0);
            }
        }

        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            /* 动画名称 */
            animation-name: move;
            /* 持续时间 */
            /* animation-duration: 2s; */
            /* 运动曲线 */
            /* animation-timing-function: ease; */
            /* 延迟时间-何时开始 */
            animation-delay: 1s;
            /* 重复次数 iteration 重复的 conut 次数 infinite 无限 */
            /* animation-iteration-count: infinite; */
            /* 是否反方向播放 默认的是 normal 如果想要反方向进行下一周期动画就写 alternate */
            /* animation-direction: alternate; */
            /* 动画结束后的状态 默认的是 backwards 回到起始状态 我们可以让他停留在结束状态 forwards */
            /* animation-fill-mode: forwards; */
            /* animation: name duration timing-function delay iteration-count direction fill-mode; */
            /* animation: move 2s linear 0s 1 alternate forwards; */
            /* 前面 2 个属性 name duration 一定要写 */
            /* animation: move 2s linear alternate forwards; */
        }

        div:hover {
            /* 鼠标经过 div 让这个 div 停止动画,鼠标离开就继续动画 */
            animation-play-state: paused;
        }
    </style>
</head>

<body>
<div>

</div>
</body>

</html>

3.2.4 速度曲线细节

animation-timing-function:规定动画的速度曲线,默认是 "ease"。

描述
linear动画从头到尾的速度是相同的(匀速)
ease默认。动画以低速开始,然后加快,在结束前变慢
ease-in动画以低速开始
ease-out动画以低速结束
ease-in-out动画以低速开始和结束
steps()指定了时间函数中的间隔数量(步长),即分成多少段去执行
<!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>速度曲线步长</title>
    <style>
        div {
            overflow: hidden;
            font-size: 20px;
            width: 0;
            height: 30px;
            background-color: pink;
            /* 让我们的文字强制一行内显示 */
            white-space: nowrap;
            /* steps 就是分几步来完成我们的动画 有了 steps 就不要在写 ease 或者 linear 了 */
            animation: w 4s steps(10) forwards;
        }

        @keyframes w {
            0% {
                width: 0;
            }
            100% {
                width: 200px;
            }
        }
    </style>
</head>

<body>
<div>世纪佳缘我在这里等你</div>
</body>

</html>

20210425105455354.gif

<!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>奔跑的熊大案例</title>
    <style>
        body {
            background-color: #ccc;
        }

        div {
            position: absolute;
            /* 单个精灵图的大小 1600/8 = 200 */
            width: 200px;
            height: 100px;
            background: url(media/bear.png) no-repeat;
            /* 我们元素可以添加多个动画,用逗号分隔 */
            animation: bear .4s steps(8) infinite, move 3s linear forwards;
        }

        @keyframes bear {
            0% {
                background-position: 0 0;
            }
            100% {
                background-position: -1600px 0;
            }
        }

        @keyframes move {
            0% {
                left: 0;
            }
            100% {
                left: 50%;
                /* margin-left: -100px; */
                transform: translateX(-50%);
            }
        }
    </style>
</head>

<body>
<div></div>
</body>

</html>

20210425105628305.png

20210425105802965.gif

3.3 CSS3 3D转换

我们生活的环境是 3D 的,照片就是 3D 物体在 2D 平面呈现的例子。

有什么特点

  • 近大远小
  • 物体后面遮挡不可见

当我们在网页上构建 3D 效果的时候参考这些特点就能产出 3D 效果,使用transform属性实现元素在空间内的位移、旋转、缩放等效果。

3.3.1 三维坐标系

三维坐标系其实就是指立体空间,立体空间是由3个轴共同组成的。

20210425110200341.png

  • x 轴:水平向右(注意:x 右边是正值,左边是负值)
  • y 轴:垂直向下(注意:y 下面是正值,上面是负值)
  • z 轴:垂直屏幕,z轴位置与视线方向相同。(注意:往外面是正值,往里面是负值)

3D 转换我们主要学习工作中最常用的 3D 位移 和 3D 旋转。

主要知识点

  • 3D 位移:translate3d(x, y, z)
  • 3D 旋转:rotate3d(x, y, z)
  • 透视:perspective
  • 3D 呈现:transfrom-style

3.3.2 3D移动 translate3d

3D 移动在 2D 移动的基础上多加了一个可以移动的方向,就是 z 轴方向。

  • transform:translateX(100px):仅仅是在 X 轴上移动
  • transform:translateY(100px):仅仅是在 Y 轴上移动
  • transform:translateZ(100px):仅仅是在 Z 轴上移动(注意:translateZ 一般用 px 单位)
  • transform:translate3d(x, y, z):其中 x、y、z 分别指要移动的轴的方向的距离

因为 z 轴是垂直屏幕,由里指向外面,所以默认是看不到元素在 z 轴的方向上移动,要借助透视

取值(正负均可)

  • 像素单位数值
  • 百分比

3.3.3 透视 perspective

思考:生活中,同一个物体,观察距离不同,视觉上有什么区别?

答:近大远小、近清楚远模糊

思考:默认情况下,为什么无法观察到Z轴位移效果?

答:Z轴是视线方向,移动效果应该是距离的远或近, 电脑屏幕是平面,默认无法观察远近效果

所以我们需要使用perspective属性实现透视效果

属性(添加给父级):

perspective: 值; 
取值:像素单位数值, 数值一般在8001200

作用 : 空间转换时,为元素添加近大远小、近实远虚的视觉效果

Snipaste_2022-06-22_14-44-41.png

d:就是视距,视距就是一个距离人的眼睛到屏幕的距离。

z:就是 z 轴,物体距离屏幕的距离,z 轴越大(正值)我们看到的物体就越大。

在 2D 平面产生近大远小视觉立体,但是效果只是二维的。

  • 如果想要在网页产生 3D 效果需要透视(理解成 3D 物体投影在 2D 平面内)
  • 模拟人类的视觉位置,可认为安排一只眼睛去看
  • 透视我们也称为视距:视距就是人的眼睛到屏幕的距离
  • 距离视觉点越近的,在电脑平面成像越大,越远成像越小
  • 透视的单位是像素

透视写在被观察元素的父盒子上面。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>透视效果</title>
    <style>
      /* 透视写到被观察元素的父盒子上面 */
      body {
        perspective: 1000px;
        /* 如果设置的透视视距特别大或者特别小,在实际表现上会显得特别差,不推荐 */
        /* perspective: 200px; */
        /* perspective: 10000px; */
      }

      .box {
        width: 200px;
        height: 200px;
        margin: 100px auto;
        background-color: pink;
        transition: all 0.5s;
      }

      .box:hover {
        /* transform: translateX(100px) translateY(100px) translateZ(100px); */
        /* 1. translateZ 沿着 Z 轴移动 ; translateZ:往外是正值; translateZ:往里是负值*/
        /* 2. translateZ 后面的单位我们一般跟 px */
        /* 3. translateZ(100px) 向外移动 100px(向我们的眼睛来移动的) */
        /* 4. 3D 移动有简写的方法 */
        /* transform: translate3d(x, y, z); */
        /* transform: translate3d(100px, 100px, 100px); */
        /* 5. xyz 是不能省略的,如果没有就写 0 */
        transform: translateZ(200px);
        /* transform: translateZ(-200px); */
      }
    </style>
  </head>

  <body>
    <div class="box"></div>
  </body>
</html>

3.3.4 3D旋转 rotate3d

3D旋转指可以让元素在三维平面内沿着 x轴,y轴,z轴或者自定义轴进行旋转。

语法

  • transform: rotateX(45deg):沿着 x 轴正方向旋转 45 度
  • transform: rotateY(45deg):沿着 y 轴正方向旋转 45deg
  • transform: rotateZ(45deg):沿着 z 轴正方向旋转 45deg,跟transform: rotate(45deg)效果一致
  • transform: rotate3d(x, y, z, deg):沿着自定义轴旋转 deg 为角度,x,y,z 取值为0-1之间的数字

20210425115234419.gif

对于元素旋转的方向的判断,我们需要先学习一个左手准则。

左手准则:

判断旋转方向: 左手握住旋转轴, 拇指指向正值方向, 手指弯曲方向为旋转正值方向

  • 左手的手拇指指向 x 轴的正方向
  • 其余手指的弯曲方向就是该元素沿着 x 轴旋转的方向
<!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>rotateX</title>
    <style>
        body {
            /* 利用透视产生近大远小效果 */
            perspective: 800px;
        }

        img {
            display: block;
            margin: 100px auto;
            transition: all 1s;
        }

        img:hover {
            transform: rotateX(45deg);
        }
    </style>
</head>

<body>
<img src="media/pig.jpg" alt="">
</body>

</html>

20210425120806628.gif

  • 左手的手拇指指向 y 轴的正方向
  • 其余手指的弯曲方向就是该元素沿着 y 轴旋转的方向(正值)
<!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>rotateY</title>
    <style>
        body {
            perspective: 800px;
        }

        img {
            display: block;
            margin: 100px auto;
            transition: all 1s;
        }

        img:hover {
            transform: rotateY(45deg);
        }
    </style>
</head>

<body>
<img src="media/pig.jpg" alt="">
</body>

</html>

20210425121401130.gif

  • 左手的手拇指指向 z 轴的正方向
  • 其余手指的弯曲方向就是该元素沿着 z 轴旋转的方向(正值)
<!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>rotateZ</title>
    <style>
        body {
            perspective: 800px;
        }

        img {
            display: block;
            margin: 100px auto;
            transition: all 1s;
        }

        img:hover {
            transform: rotateZ(180deg);
        }
    </style>
</head>

<body>
<img src="media/pig.jpg" alt="">
</body>

</html>

20210425121713541.gif

transform: rotate3d(x, y, z, deg):沿着自定义轴旋转 deg 为角度(了解即可)。

xyz 是表示旋转轴的矢量,表示你是否希望沿着该轴旋转,最后一个表示旋转的角度。

  • transform: rotate3d(1, 0, 0, 45deg):就是沿着 x 轴旋转 45deg
  • transform: rotate3d(0, 1, 0, 45deg):就是沿着 y 轴旋转 45deg
  • transform: rotate3d(0, 0, 1, 45deg):就是沿着 z 轴旋转 45deg
  • transform: rotate3d(1, 1, 0, 45deg):就是沿着对角线(矢量计算)旋转 45deg

20210425122158983.png

<!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>rotate3d</title>
    <style>
        body {
            perspective: 500px;
        }

        img {
            display: block;
            margin: 100px auto;
            transition: all 1s;
        }

        img:hover {
            /* transform: rotate3d(x,y,z,deg); */
            /* transform: rotate3d(1, 0, 0, 45deg); */
            /* transform: rotate3d(0, 1, 0, 45deg); */
            transform: rotate3d(1, 1, 0, 45deg);
        }
    </style>
</head>

<body>
<img src="media/pig.jpg" alt="">
</body>

</html>

20210425121831607.gif

3.3.5 3D呈现 transfrom-style

思考:使用perspective透视属性能否呈现立体图形?

答:不能,perspective只增加近大远小、近实远虚的视觉效果。

目标: 使用transform-style: preserve-3d呈现立体图形

  • 控制子元素是否开启三维立体环境
  • transform-style: flat; 子元素不开启 3d 立体空间(默认的)
  • transform-style: preserve-3d; 子元素开启立体空间
  • 代码写给父级,但是影响的是子盒子
  • 这个属性很重要,后面必用

20210425123348956.png

<!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>transform-style</title>
    <style>
        body {
            perspective: 500px;
        }

        .box {
            position: relative;
            width: 200px;
            height: 200px;
            margin: 100px auto;
            transition: all 2s;
            /* 让子元素保持3d立体空间环境 */
            transform-style: preserve-3d;
        }

        .box:hover {
            transform: rotateY(60deg);
        }

        .box div {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: pink;
        }

        .box div:last-child {
            background-color: purple;
            transform: rotateX(60deg);
        }
    </style>
</head>

<body>
<div class="box">
    <div></div>
    <div></div>
</div>
</body>

</html>

20210425124112130.gif

3.3.6 使用scale实现空间缩放效果~几乎不用

语法 :

  • transform: scaleX(倍数);
  • transform: scaleY(倍数);
  • transform: scaleZ(倍数);
  • transform: scale3d(x, y, z);

3.3.7 案例

【案例:两面翻转的盒子】

20210425124741907.gif

实现步骤:

  1. 搭建 HTML 结构
<div class="box">
	<div class="front">黑马程序员</div>
    <div class="back">pink老师等你</div>
</div>
  • box 父盒子里面包含前后两个子盒子
  • box 是翻转的盒子 front 是前面盒子 back 是后面盒子
  1. CSS 样式
  • box 指定大小,切记要添加 3d 呈现
  • back 盒子要沿着 Y 轴翻转 180 度
  • 最后鼠标经过 box 沿着 Y 旋转 180deg

代码:

<!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>两面翻转的盒子</title>
    <style>
        body {
            perspective: 400px;
        }

        .box {
            position: relative;
            width: 300px;
            height: 300px;
            margin: 100px auto;
            transition: all .4s;
            /* 让背面的紫色盒子保留立体空间 给父级添加的 */
            transform-style: preserve-3d;
        }

        .box:hover {
            transform: rotateY(180deg);
        }

        .front,
        .back {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            font-size: 30px;
            color: #fff;
            text-align: center;
            line-height: 300px;
        }

        .front {
            background-color: pink;
            z-index: 1;
        }

        .back {
            background-color: purple;
            /* 像手机一样 背靠背 旋转 */
            transform: rotateY(180deg);
        }
    </style>
</head>

<body>
<div class="box">
    <div class="front">黑马程序员</div>
    <div class="back">pink老师这里等你</div>
</div>
</body>

</html>

【案例:3D 导航栏】

20210425125609662.gif

实现步骤:

  1. 搭建 HTML 结构
<ul>
    <li>
        <div class="box">
            <div class="front">黑马程序员</div>
            <div class="bottom">pink老师等你</div>
         </div>
    </li>
</ul>
  • li 做导航栏
  • .box 是翻转的盒子 front 是前面盒子 bottom 是底下盒子
  1. CSS 样式
  • li 设置大小,加透视和 3d 呈现
  • front 需要前移 17.5 像素
  • bottom 需要下移 17.5 像素并且要沿着 x 轴翻转 负 90 度
  • 鼠标放到 box 让盒子旋转 90 度
<!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>3D导航栏案例</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        ul {
            margin: 100px;
        }

        ul li {
            float: left;
            margin: 0 5px;
            width: 120px;
            height: 35px;
            list-style: none;
            /* 一会我们需要给 box 旋转 也需要透视 干脆给 li 加 里面的子盒子都有透视效果 */
            perspective: 500px;
        }

        .box {
            position: relative;
            width: 100%;
            height: 100%;
            transform-style: preserve-3d;
            transition: all .4s;
        }

        .box:hover {
            transform: rotateX(90deg);
        }

        .front,
        .bottom {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
        }

        .front {
            background-color: pink;
            z-index: 1;
            transform: translateZ(17.5px);
        }

        .bottom {
            background-color: purple;
            /* 这个x轴一定是负值 */
            /* 我们如果有移动 或者其他样式,必须先写我们的移动 */
            transform: translateY(17.5px) rotateX(-90deg);
        }
    </style>
</head>

<body>
<ul>
    <li>
        <div class="box">
            <div class="front">黑马程序员</div>
            <div class="bottom">pink老师等你</div>
        </div>
    </li>
    <li>
        <div class="box">
            <div class="front">黑马程序员</div>
            <div class="bottom">pink老师等你</div>
        </div>
    </li>
    <li>
        <div class="box">
            <div class="front">黑马程序员</div>
            <div class="bottom">pink老师等你</div>
        </div>
    </li>
    <li>
        <div class="box">
            <div class="front">黑马程序员</div>
            <div class="bottom">pink老师等你</div>
        </div>
    </li>
    <li>
        <div class="box">
            <div class="front">黑马程序员</div>
            <div class="bottom">pink老师等你</div>
        </div>
    </li>
    <li>
        <div class="box">
            <div class="front">黑马程序员</div>
            <div class="bottom">pink老师等你</div>
        </div>
    </li>
</ul>
</body>

</html>

【综合案例:旋转木马】

20210425130327326.gif

  1. 搭建 HTML 结构
<section>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</section>
  • 里面的 6 个 div 分别是 6 个狗狗图片
  • 注意最终旋转是 section 标签旋转
  1. CSS 样式
  • 给 body 添加 透视效果 perspective: 1000px;
  • 给 section 添加大小,一定不要忘记添加 3d 呈现效果控制里面的 6 个 div
    • 别忘记子绝父相,section 要加相对定位
  • 里面 6 个 div 全部绝对定位叠到一起,然后移动不同角度旋转和距离
    • 注意:旋转角度用 rotateY 距离肯定用 translateZ 来控制
  • 给 section 添加动画 animation,让它可以自动旋转即可
<!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>综合案例:旋转木马</title>
    <style>
        body {
            perspective: 1000px;
        }

        section {
            position: relative;
            width: 300px;
            height: 200px;
            margin: 150px auto;
            transform-style: preserve-3d;
            /* 添加动画效果 */
            animation: rotate 10s linear infinite;
            background: url(media/pig.jpg) no-repeat;
        }

        section:hover {
            /* 鼠标放入 section 停止动画 */
            animation-play-state: paused;
        }

        @keyframes rotate {
            0% {
                transform: rotateY(0);
            }
            100% {
                transform: rotateY(360deg);
            }
        }

        section div {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: url(media/dog.jpg) no-repeat;
        }

        section div:nth-child(1) {
            transform: rotateY(0) translateZ(300px);
        }

        section div:nth-child(2) {
            /* 先旋转好了再 移动距离 */
            transform: rotateY(60deg) translateZ(300px);
        }

        section div:nth-child(3) {
            /* 先旋转好了再 移动距离 */
            transform: rotateY(120deg) translateZ(300px);
        }

        section div:nth-child(4) {
            /* 先旋转好了再 移动距离 */
            transform: rotateY(180deg) translateZ(300px);
        }

        section div:nth-child(5) {
            /* 先旋转好了再 移动距离 */
            transform: rotateY(240deg) translateZ(300px);
        }

        section div:nth-child(6) {
            /* 先旋转好了再 移动距离 */
            transform: rotateY(300deg) translateZ(300px);
        }
    </style>
</head>

<body>
<section>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</section>
</body>

</html>

3.4 浏览器私有前缀

浏览器私有前缀是为了兼容老版本的写法,比较新版本的浏览器无须添加

3.4.1 私有前缀

  • -moz-:代表 firefox 浏览器私有属性
  • -ms-:代表 ie 浏览器私有属性
  • -webkit-:代表 safari、chrome 私有属性
  • -o-:代表 Opera 私有属性

3.4.2 提倡的写法

-o-border-radius: 10px; 
-ms-border-radius: 10px; 
-moz-border-radius: 10px; 
-webkit-border-radius: 10px; 
border-radius: 10px;

四、 CSS布局技巧

4.1 margin负值的运用

如何实现以下效果呢?

多个盒子紧挨在一起,当鼠标放在其中一个盒子上时该盒子的边框自动变色。

20210422102946635.png

  1. 让每个盒子 margin 往左侧移动 -1px 正好压住相邻盒子边框(否则边框会发生叠加 * 2)
  2. 鼠标经过某个盒子的时候,提高当前盒子的层级即可(如果周围盒子没有定位,则对当前盒子加相对定位(保留位置并显示在其他盒子之上);如果周围有定位,则提高当前盒子的 z-index)
<!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>margin负值的巧妙运用</title>
    <style>
        ul li {
            position: relative;
            float: left;
            list-style: none;
            width: 150px;
            height: 200px;
            border: 1px solid red;
            margin-left: -1px;
        }

        /* ul li:hover {
           1. 如果盒子没有定位,则鼠标经过添加相对定位即可
        position: relative;
        border: 1px solid blue;

       } */
        ul li:hover {
            /* 2.如果li都有定位,则利用 z-index提高层级 */
            z-index: 1;
            border: 1px solid blue;
        }
    </style>
</head>

<body>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
</body>

</html>

20210422131248993.gif

4.2 文字围绕浮动元素

20210422131515567.png

在制作文字位于图片周围的效果时,可以巧妙运用浮动元素不会压住文字的特性。

<!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>文字围绕浮动元素的妙用</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .box {
            width: 300px;
            height: 70px;
            background-color: #d4d4d4;
            margin: 0 auto;
            padding: 5px;
        }

        .pic {
            float: left;
            width: 120px;
            height: 60px;
            margin-right: 5px;
        }

        .pic img {
            width: 100%;
        }
    </style>
</head>
<body>
<div class="box">
    <div class="pic">
        <img src="images/img.png" alt="">
    </div>
    <p>【集锦】热身赛-巴西0-1秘鲁 内马尔替补两人血染赛场</p>
</div>
</body>
</html>

20210422131929234.png

4.3 行内块的巧妙运用

20210422132128826.png

页码在页面中间显示:

  1. 把这些链接盒子转换为行内块, 之后给父级指定 text-align: center;
  2. 利用行内块元素中间有缝隙,并且给父级添加 text-align: center; 行内块元素会水平会居中
<!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>行内块的巧妙运用</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .box {
            text-align: center;
        }

        .box a {
            display: inline-block;
            width: 36px;
            height: 36px;
            background-color: #f7f7f7;
            border: 1px solid #ccc;
            line-height: 36px;
            text-decoration: none;
            color: #333;
            font-size: 14px;
        }

        .box .prev,
        .box .next {
            width: 85px;
        }

        .box .current,
        .box .elp {
            background-color: #fff;
            border: none;
        }

        .box input {
            height: 36px;
            width: 45px;
            border: 1px solid #ccc;
            outline: none;
        }

        .box button {
            width: 60px;
            height: 36px;
            background-color: #f7f7f7;
            border: 1px solid #ccc;

        }
    </style>
</head>
<body>
<div class="box">
    <a href="#" class="prev"><<上一页</a>
    <a href="#" class="current">2</a>
    <a href="#">3</a>
    <a href="#">4</a>
    <a href="#">5</a>
    <a href="#">6</a>
    <a href="#" class="elp">...</a>
    <a href="#" class="next">>>下一页</a>
    到第
    <input type="text"><button>确定</button>
</div>
</body>
</html>

image-20220116233824235.png

4.4 CSS三角强化

20210422132739686.png

代码:

width: 0;
height: 0;
border-color: transparent red transparent transparent;
border-style: solid;
border-width: 22px 8px 0 0;

案例:

<!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>CSS三角强化的巧妙运用</title>
    <style>
        .box1 {
            width: 0;
            height: 0;
            /* 把上边框宽度调大 */
            /* border-top: 100px solid transparent;
            border-right: 50px solid skyblue; */
            /* 左边和下边的边框宽度设置为0 */
            /* border-bottom: 0 solid blue;
            border-left: 0 solid green; */
            /* 1. 只保留右边的边框有颜色 */
            border-color: transparent red transparent transparent;
            /* 2. 样式都是solid */
            border-style: solid;
            /* 3. 上边框宽度要大, 右边框 宽度稍小, 其余的边框该为 0 */
            border-width: 100px 50px 0 0;
        }

        .price {
            width: 160px;
            height: 24px;
            line-height: 24px;
            border: 1px solid red;
            margin: 0 auto;
        }

        .miaosha {
            position: relative;
            float: left;
            width: 90px;
            height: 100%;
            background-color: red;
            text-align: center;
            color: #fff;
            font-weight: 700;
            margin-right: 8px;

        }

        .miaosha i {
            position: absolute;
            right: 0;
            top: 0;
            width: 0;
            height: 0;
            border-color: transparent #fff transparent transparent;
            border-style: solid;
            border-width: 24px 10px 0 0;
        }

        .origin {
            font-size: 12px;
            color: gray;
            text-decoration: line-through;
        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="price">
            <span class="miaosha">
                ¥1650
                <i></i>
            </span>
    <span class="origin">¥5650</span>
</div>
</body>
</html>

20210422132922414.png

4.5 CSS初始化

不同浏览器对有些标签的默认值是不同的,为了消除不同浏览器对 HTML 文本呈现的差异,照顾浏览器的兼容,我们需要对 CSS 初始化。

简单理解:CSS 初始化是指重设浏览器的样式。(也称为 CSS reset)

每个网页都必须首先进行 CSS 初始化。

这里我们以 京东 CSS 初始化代码为例。

Unicode 编码字体:

把中文字体的名称用相应的 Unicode 编码来代替,这样就可以有效的避免浏览器解释 CSS 代码时候出现乱码的问题。

比如:

黑体 \9ED1\4F53

宋体 \5B8B\4F53

微软雅黑 \5FAE\8F6F\96C5\9ED1

/* 把我们所有标签的内外边距清零 */
* {
    margin: 0;
    padding: 0
}

/* em 和 i 斜体的文字不倾斜 */
em,
i {
    font-style: normal
}

/* 去掉 li 的小圆点 */
li {
    list-style: none
}

img {
    /* border 0 照顾低版本浏览器,如果图片外面包含了链接会有边框的问题 */
    border: 0;
    /* 取消图片底侧有空白缝隙的问题 */
    vertical-align: middle
}

button {
    /* 当我们鼠标经过 button 按钮的时候,鼠标变成小手 */
    cursor: pointer
}

a {
    color: #666;
    text-decoration: none
}

a:hover {
    color: #c81623
}

button,
input {
    /* "\5B8B\4F53" 就是宋体的意思,这样浏览器兼容性比较好 */
    font-family: Microsoft YaHei, Heiti SC, tahoma, arial, Hiragino Sans GB, "\5B8B\4F53", sans-serif
}

body {
    /* CSS3 抗锯齿形,让文字显示的更加清晰 */
    -webkit-font-smoothing: antialiased;
    background-color: #fff;
    font: 12px/1.5 Microsoft YaHei, Heiti SC, tahoma, arial, Hiragino Sans GB, "\5B8B\4F53", sans-serif;
    color: #666
}

.hide,
.none {
    display: none
}

/* 清除浮动 */
.clearfix:after {
    visibility: hidden;
    clear: both;
    display: block;
    content: ".";
    height: 0
}

.clearfix {
    *zoom: 1
}

参考资料: