35

image

前言

如同人类的的进化一样,CSS3CSS2的“进化”版本,在CSS2基础上,增强或新增了许多特性,弥补了CSS2的众多不足之处,使得Web开发变得更为高效和便捷。

1.选择器

CSS3新增了许多灵活查找元素的方法,极大的提高了查找元素的效率和精准度。CSS3选择器与jQuery中所提供的绝大部分选择器兼容。

1.1 属性选择器

属性选择器就是通过属性来选择元素。
选择器 含义
[attr] 存在attr属性即可
[attr=val] 属性值完全等于val
[attr*=val] 属性值里包含val字符并且在“任意”位置
[attr^=val] 属性值里包含val字符并且在“开始”位置
[attr$=val] 属性值里包含val字符并且在“结束”位置

1、[attr]

<style>
    /* 所有拥有class属性的标签,添加color样式 */
    [class]{
        color: #333;
    }
</style>

2、[attr=val]

<style>
    /* 所有拥有class属性全等于“one”的标签,添加color样式 */
    [class = "one"]{
        color: #333;
    }
</style>

3、[attr*=val]

<style>
    /* class属性的值里面包含“one”的标签,添加color样式 */
    [attr*="one"]{
        color: #333;
    }
</style>

4、[attr^=val]

<style>
    /* class属性的值以“one”开始的标签,添加color样式 */
    [attr ^= "one"]{
        color: #333;
    }
</style>

5、[attr$=val]

<style>
    /* class属性的值以“one”结束的标签,添加color样式 */
    [attr $= "one"]{
        color: #333;
    }
</style>

1.2 伪类选择器

除了以前介绍的的:link:active:visited:hoverCSS3又新增了其它的伪类选择器。

1、结构(位置)伪类

选择器 含义
:first-child 其父元素的第1个子元素
:last-child 其父元素的最后1个子元素
:nth-child(n) 其父元素的第n个子元素
:nth-last-child(n) 其父元素的第n个子元素(倒着数)

2、空伪类

:empty选中没有任何子节点的元素
<style>
   div:empty {   /* 没有子元素的div元素 */
        width: 100px;
        height: 100px;
        background-color: pink;
    }
</style>

<!-- css 样式不起作用 -->
<div class="one">阿斯蒂芬</div>   

<!-- css样式不起作用 -->
<div>
    <p></p>
</div>

<!-- css样式生效 -->
<div></div>

3、目标伪类

:target结合锚点进行使用,处于当前锚点的元素会被选中;
<style type="text/css">
    /* 使用锚链接指向当前标签的时候 */
    .one:target {
        background-color: pink;
        font-size: 30px;
    }
</style>

<a href="#hh">找笑脸去</a>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p id="hh" class="one">阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>
<p>阿斯顿发撒旦法撒打发放大法的撒双方都</p>

4、排除伪类

:not(selector)selector(任意选择器)外的元素会被选中;
<style>
    /* 除了类名是“.not”的div元素 */
    div:not(.one) {
        width: 100px;
        height: 100px;
        background-color: pink;
    }
</style>

<!-- css样式不生效 -->
<div class="one"></div>

<!-- css样式生效 -->
<p></p>

<!-- css样式生效 -->
<div></div>

1.3 伪元素选择器

  • 1、::first-letter文本的第一个单词或字(如中文、日文、韩文等)
  • 2、::first-line 文本第一行;
  • 3、::selection 可改变选中文本的样式;
  • 4、::before::after

示例代码:伪元素实现横竖分割线

<style type="text/css">
    * {
         margin: 0;
         padding: 0;
         list-style: none;
    }
    .box {
         width: 300px;
         height: 200px;
         background-color: pink;
         margin: 50px auto;
    }
    .box li {
         width: 100px;
         height: 100px;
         float: left;
         background-color: #555;
         position: relative;
         overflow: hidden;
    }

    li:before {
         content: "";
         display: block;
         width: 90px;
         height: 1px;
         background-color: #ccc;
         position: absolute;
         top: 97px;
         left: 5px;
    }
    li:after {
         content: "";
         display: block;
         width: 1px;
         height: 90px;
         background-color: #ccc;
         position: absolute;
         left: 0px;
         top: 4px;
    }
    li:nth-child(1):after,li:nth-child(4):after {
         display: none;
    }

    li:nth-last-child(-n+3):before {
         display: none;
    }
</style>

<div class="box">
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>

效果图:

image

:after:before在旧版本里是伪元素,CSS3的规范里“:”用来表示伪类,“::”用来表示伪元素,但是在高版本浏览器下:after:before会被自动识别为::after::before,这样做的目的是用来做兼容处理。

2. 颜色

新增了RGBAHSLA模式,其中的A表示透明度,即可以设置颜色值的透明度,相较opacity,它们不具有继承性,即不会影响子元素的透明度。

2.1 RGBA

RedGreenBlueAlphaRGBARGB取值范围0~255
<style>
    #box{
        width:100px;
        height:100px;
        background: rgba(200,200,200,.5);
    }
</style>

<div id="box"></div>

2.2 HSLA

  • H 色调 取值范围0~3600/360表示红色、120表示绿色、240表示蓝色
  • S 饱和度 取值范围0%~100%
  • L 亮度 取值范围0%~100%
  • A 透明度 取值范围0~1
<style>
    #box{
        width:100px;
        height:100px;
        background: hsla(200,50%,50%,.5);
    }
</style>

<div id="box"></div>

2.3 关于 CSS 的透明度

Alphaopacity的区别主要就是,opacity具有继承性,父盒子设置该属性,下面所有的子元素都会继承该属性。

transparent不可调节透明度,始终完全透明。

3. 文本阴影

text-shadow,可分别设置偏移量、模糊度、颜色(可设透明度)。

如:

text-shadow: 2px 2px 2px #CCC;
  • 1、水平偏移量 正值向右 负值向左;
  • 2、垂直偏移量 正值向下 负值向上;
  • 3、模糊度是不能为负值;
  • 4、阴影颜色。

示例代码:文字浮雕

<style>
     html,body {
          margin: 0;
          padding: 0;
          width: 100%;
          height: 100%;
          background-color: #999;
          font-size: 50px;
          text-align: center;
          line-height: 260px;
          color: #999;
     }
        
    .one {
         text-shadow: -1px -1px 1px #fff,1px 1px 1px #000;
    }

    .two {
         text-shadow: -1px -1px 1px #000,1px 1px 1px #fff;
    }
</style>

<div class="one">我是凸起文字</div>
<div class="two">我是凹下去的文字</div>

效果图:

image

4. 盒模型

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

可以分成两种情况:

  • 1、box-sizing: border-box盒子大小为width
  • 2、box-sizing: content-box盒子大小为width + padding + border

注:上面的标注的width指的是CSS属性里设置的width: lengthcontent的值是会自动调整的。

示例代码:

<style type="text/css">
     .box {
          width: 316px;
          height: 170px;
          float: left;
          margin-left: 20px;
          box-sizing: border-box;
     }
     .box img {
          width: 100%;
          height: 100%;
     }

     .box:hover {
          border: 10px solid #00eeff;
     }
</style>

<div class="box">
   <img src="1.jpg" alt="">
</div>

<div class="box">
   <img src="1.jpg" alt="">
</div>

效果图:

image

可以看出通过设置盒子模型后,虽然.box设置了边框,但是整个box的盒子大小没有改变。

5. 边框

边框中的边框圆角、边框阴影属性,应用十分广泛,兼容性也相对较好,具有符合渐进增强原则的特征。

5.1 边框圆角

通过border-radius属性,设置边框圆角,圆角处理时,脑中要形成圆、圆心、横轴、纵轴的概念,正圆是椭圆的一种特殊情况。

image

为了方便表述,我们将四个角标记成1234,如2代表右上角,CSS里提供了border-radius来设置这些角横纵轴半径值。

分别设置横纵轴半径,以“/”进行分隔,遵循“1234”规则,“/”前面的1~4个用来设置横轴半径(分别对应横轴1234位置),“/”后面1~4个参数用来设置纵轴半径(分别对应纵轴1234位置 )。

<style type="text/css">
    .box {
        margin: 50px auto;
        width: 300px;
        height: 500px;
        border: 1px solid #ccc;
        border-radius: 10px 20px 50px 70px / 10px 20px 50px 70px;
    }
</style>

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

效果图:

一般情况下,我们用不到这么复杂的,除非特殊需求的时候。

image

支持简写模式,具体如下:

  • 1、border-radius: 10px;表示四个角的横纵轴半径都为10px
  • 2、border-radius: 10px 5px;表示13角横纵轴半径都为10px24角横纵轴半径为5px
  • 3、border-radius: 10px 5px 8px;表示1角模纵轴半径都为10px24角横纵轴半径都为8px3角的横纵轴半径都为8px
  • 4、border-radius: 10px 8px 6px 4px;表示1角横纵轴半径都为10px,表示2角横纵轴半径都为8px,表示3角横纵轴半径都为6px,表示4角横纵轴半径都为6px

椭圆的画法:

<style type="text/css">
    .box {
        margin: 50px auto;
        width: 300px;
        height: 500px;
        border: 1px solid #ccc;
        /* 当盒子长宽不一致时,圆角属性 分别设置宽度的一半,以及长度的一半,即是椭圆 */
        /* 或者直接 border-radius:50%; */
        border-radius: 150px 250px;
    }
</style>

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

image

如果不想计算,直接设百分比:“50%”。

正圆的画法:

<style type="text/css">
    .box {
        margin: 50px auto;
        width: 200px;
        height: 200px;
        border: 1px solid #ccc;
        /* 当盒子长宽相等时,圆角属性分别设置宽度的一半,以及长度的一半,即是正圆 */
        /* 或者直接 border-radius:50%; */
        border-radius: 100px;
    }
</style>

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

image

示例代码:边框圆角合集

<style>
    * {
          margin: 0;
          padding: 0;
          list-style: none;
          background-color: wheat;
          overflow: hidden;
     }
    
     .box {
          width: 980px;
          height: 400px;
          background-color: #fff;
          margin: 50px auto;
     }
    
     .box li {
          float: left;
          width: 193px;
          height: 193px;
          background-color: #fff;
          margin:5px;
          box-shadow: 2px 3px 5px #aaa;
     }
    
     li:first-child:after {
          content: "";
          height: 130px;
          width: 130px;
          margin: 30px auto;
          display: block;
          border: 1px solid orangered;
          border-radius: 50%;
     }
     li:nth-child(2):after {
          content: "";
          display: block;
          height: 130px;
          width: 130px;
          border: 1px solid orangered;
          margin: 30px auto;
          border-radius: 65px 65px 0px 0px;
     }
    
     li:nth-child(3):after {
          content: "";
          display: block;
          width: 130px;
          height: 65px;
          border: 1px solid orangered;
          margin: 50px auto;
          border-radius: 65px 65px 0px 0px;
     }
    
     li:nth-child(4):after {
          content: "";
          display: block;
          width: 130px;
          height: 130px;
          border: 1px solid orangered;
          margin: 20px auto;
          border-radius: 65px 0px 0px 0px;
     }
    
     li:nth-child(5):after {
          content: "";
          width: 130px;
          height: 65px;
          display: block;
          border: 1px solid orangered;
          border-radius: 50%;
          margin: 50px auto;
     }
     li:nth-child(6):after{
          content: "";
          height: 130px;
          width: 65px;
          display: block;
          border: 1px solid orangered;
          border-radius: 50%;
          margin: 20px auto;
     }
    
     li:nth-child(7):after {
          content: "";
          height: 130px;
          width: 130px;
          display: block;
          border: 1px solid orangered;
          margin: 20px auto;
          border-radius: 135px 0px 0px 0px;
     }
    
     li:nth-child(8):after {
          content: "";
          width: 135px;
          height: 30px;
          display: block;
          margin: 30px auto;
          border: 1px solid orangered;
          border-radius: 65px 65px 0px 0px / 30px 30px 0px 0px;
     }
</style>

<div class="box">
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>

效果图:

image

5.2 边框阴影

box-shadow,与文字阴影类似,可分别设置盒子阴影偏移量、模糊度、颜色(可设透明度)。

如:

box-shadow: 5px 5px 5px #CCC
  • 1、水平偏移量 正值向右 负值向左;
  • 2、垂直偏移量 正值向下 负值向上;
  • 3、模糊度是不能为负值;
  • 4、inset可以设置内阴影;

注:设置边框阴影不会改变盒子的大小,即不会影响其兄弟元素的布局。可以设置多重边框阴影,实现更好的效果,增强立体感,符合渐进增强,实际开发中可以大胆使用。

示例代码:

<style>
    .box {
        width: 200px;
        height: 200px;
        margin: 50px auto;
        border: 1px dashed #000;
        box-shadow: 2px 3px 4px rgba(0, 247, 255, 0.452),inset 5px 6px 7px rgba(255, 0, 140, 0.562);
    }
</style>

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

效果图:

image

我们通过上图可以看到,虚线是盒子的位置,粉色阴影是inset属性设置的,所以是内阴影,浅蓝色是直接设置的外阴影,效果一目了然。

6. 背景

背景在CSS3中也得到很大程度的增强,比如背景图片尺寸、背景裁切区域、背景定位参照点、多重背景等。

6.1 background-size

通过background-size设置背景图片的尺寸,就像我们设置img的尺寸一样,在移动Web开发中做屏幕适配应用非常广泛。

其参数设置如下:

  • 可以设置长度单位(px)或百分比(设置百分比时,参照盒子的宽高)
  • 设置为cover时,会自动调整缩放比例,保证图片始终填充满背景区域,如有溢出部分则会被隐藏。
  • 设置为contain会自动调整缩放比例,保证图片始终完整显示在背景区域。

6.2 background-origin

通过background-origin可以设置背景图片定位(background-position)的参照原点。

其参数设置如下:

  • border-box以边框做为参考原点;
  • padding-box以内边距做为参考原点;
  • content-box以内容区做为参考点;

示例代码:

<style type="text/css">
    .box1,.box2,.box3 {
        width: 200px;
        height: 200px;
        display: inline-block;
        margin: 50px 30px;
        border: 10px dashed aquamarine;
        padding: 10px;
        background-image: url(bg.jpg);
        background-repeat: no-repeat;
    }
    .box1{
        background-origin: padding-box;
    }
    .box2{
        background-origin: content-box;
    }
    .box3{
        background-origin: border-box;
    }
</style>


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

效果图:

image

6.3 background-clip

通过background-clip,可以设置对背景区域进行裁切,即改变背景区域的大小。

其参数设置如下:

  • border-box裁切边框以内为背景区域;
  • padding-box裁切内边距以内为背景区域;
  • content-box裁切内容区做为背景区域;

image

6.4 多背景

以逗号分隔可以设置多背景,可用于自适应布局。在一个盒子里可以设置多个背景图片,通过背景定位的功能将两张图片组装起来。

示例代码:

<style type="text/css">
    .box {
        width: 320px;
        height: 410px;
        margin: 50px auto;
        background: url(head.jpg) no-repeat left top,
                      url(foot.jpg) no-repeat left bottom; 
        background-size: contain;
        background-color: #ccc;
    }
</style>

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

效果图:

image

从效果图中我们可以看到,在盒子里面设置了两张背景图,分别是上面一部分,下面一部分。这里故意给盒子高度拉长了一点,并且设置了一个灰色的背景,为的就是大家能够清楚的看到上下两部分的背景图。

7. 渐变

渐变是CSS3当中比较丰富多彩的一个特性,通过渐变我们可以实现许多炫丽的效果,有效的减少图片的使用数量,并且具有很强的适应性和可扩展性。

7.1 线性渐变

linear-gradient线性渐变指沿着某条直线朝一个方向产生渐变效果。

1、必要的元素:

借助Photoshop总结得出线性渐变的必要元素
  • a、方向
  • b、起始色
  • c、终止色
  • d、渐变距离

2、关于方向

通过具体的方位词指定
  • to left
  • to right
  • to top
  • to bottom
通过角度改变渐变的方向
  • ,从下往上渐变
  • 90°,从左向右渐变

示例代码:

<style type="text/css">
    .box {
        width: 400px;
        height: 150px;
        margin: 100px auto;
        /* 线性渐变 */
        background-image: linear-gradient(
            /*渐变的方向*/
            45deg,
            /*渐变开始的颜色*/
            #88f5ea,
            /*渐变结束的颜色*/
            #d36be7
        );
    }
</style>

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

效果图:

image

3、渐变范围

如果不设置范围,默认渐变的范围是父盒子的宽度,如果通过background-size设置宽度的话,渐变范围即为设置的宽度。
<style>
    .box {
        width: 500px;
        height: 100px;
        margin: 100px auto;
        background-image: linear-gradient(
            135deg,
            yellow 20%,
            black 20%,
            black 40%,
            yellow 40%,
            yellow 60%,
            black 60%,
            black 80%,
            yellow 80%,
            yellow 
        );
        background-size: 66px 100px;
    }
</style>

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

效果图:

image

7.2 径向渐变

radial-gradient径向渐变指从一个中心点开始沿着四周产生渐变效果。

1、必要的元素:

  • a、辐射范围即圆半径
  • b、中心点 即圆的中心
  • c、渐变起始色
  • d、渐变终止色
  • e、渐变范围

2、关于中心点

中心位置参照的是盒子的左上角,例如:
<style>
    #div{
        width:200px;
        height:200px;
        background: radial-gradient(
            /* 100px是渐变辐射的范围 0 0 指的是圆心在盒子的左上角 */
            100px at 0 0,
            /*渐变起始色*/
            orange,
            /*渐变终止色*/
            #ff4500
        )
    }
</style>

<div id="box"></div>

image

示例代码:镜像渐变画个球

<style type="text/css">
    * {
        margin: 0;
        padding: 0;
    }

    html,body {
        width: 100%;
        height: 100%;
        background-color: #ccc;
    }

    .box {
         width: 400px;
         height: 400px;
         background-color: #fff;
         margin: 50px auto;
         border-radius: 50%;

         background-image: radial-gradient(
               300px at 100px 100px,
               rgba(0,0,0,.1),
               rgba(0,0,0,.8)
         );
    }
</style>

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

效果图:

image

8. 过渡

过渡是CSS3中具有颠覆性的特征之一,可以实现元素不同状态间的平滑过渡(补间动画),经常用来制作动画效果。

8.1 帧动画

通过一帧一帧的画面按照固定顺序和速度播放,如电影胶片。

image

示例代码:

<!--
    baidu.png这个背景图由64张图片横向组成,我们通过动态改变图片的位置,实现动画效果
-->
<style>
    body {
        margin: 0;
        padding: 0;
        background-color: #F7F7F7;
    }

    .logo {
        width: 270px;
        height: 129px;
        margin: 100px auto;
        background-image: url(./baidu.png);
        background-position: 0 0;
    }
</style>

<div class="logo"></div>
<script>
    var logo = document.querySelector('.logo');

    var offset = -270;
    var n = 0;
    setInterval(function () {
        n++;
        logo.style.backgroundPosition = offset * n + 'px 0px';
        if(n >= 64) n = 0;
    },100);
</script>

效果图:

image

这里不做详细了解,主要是为了区分与补间动画的区别。

8.2 补间动画

自动完成从起始状态到终止状态的的过渡。

语法:transition

当前元素只要有“属性”发生变化时,可以平滑的进行过渡,并不仅仅局限于hover状态。
  • transition-property设置过渡属性
/*设置哪些属性要参加到动画效果中*/
transition-property: all;
  • transition-duration设置动画过渡执行时间
transition-duration: 2s;
  • transition-timing-function设置过渡速度类型
transition-timing-function:linear; 

/* ease| ease-in | ease-out | ease-in-out | linear; */
  • transition-delay设置过渡延时
/*1s后,过渡动画开始过渡*/
transition-delay: 1s;

连写:

/*          属性  执行时间 延时时间 过渡类型*/
transition: all   2s       1s       linear;

示例代码:

<style type="text/css">
    .box {
        width: 250px;
        height: 250px;
        background-color: pink;
        margin: 100px auto;
        transition: all 2s 1s linear;
    }
    
    .box:hover {
        width: 200px;
        height: 200px;
        border-radius:50%;
        background-color: rgb(25, 221, 247);
    }
</style>

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

效果图:

image

我们可以看到,触发hover事件的时候延迟1s后开始执行动画。

示例代码:过渡的实际应用

<style type="text/css">
    html,body {
         margin: 0;
         padding: 0;
         width: 100%;
         height: 100%;
    }

    .box {
         width: 100%;
         height: 100%;
         background-color: #eee;
    }

    .l_box {
         float: left;
         width: 234px;
         height: 300px;
         margin: 100px 50px;
         cursor: pointer;
         transition: all 0.5s linear;
    }

    .l_box:hover {
        box-shadow: -2px -2px 20px #777;
        margin-top: 90px;
    }

    .r_box {
         width: 234px;
         height: 300px;
         float: left;
         margin: 100px 0px;
         background-color: #fff;
         text-align: center;
         position: relative;
    }

    .cover {
        position: absolute;
        bottom: 0;
        height: 0px;
        width: 234px;
        background-color: orange;
        transition: all 1s linear;
    }

    .r_box:hover .cover {
        height: 100px;
    }
</style>

<div class="box">
    <div class="l_box">
        <img src="img/1.jpg" alt="">
    </div>
    <div class="r_box">
        <img src="img/2.jpg" alt="">
        <div class="cover"></div>
    </div>
</div>

效果图:

image

9. 2D转换

转换(transform)是CSS3中具有颠覆性的特征之一,可以实现元素的位移、旋转、变形、缩放,甚至支持矩阵方式,配合即将学习的过渡和动画知识,可以取代大量之前只能靠Flash才可以实现的效果。

9.1 位移

CSS3中,通过translate属性对元素进行位移。

移动translate(x, y)可以改变元素的位置,xy可为负值;

  • a、移动位置相当于自身原来位置
  • b、y轴正方向朝下
  • c、除了可以像素值,也可以是百分比,相对于自身的宽度或高度
transform: translate(100px, 30px);

示例代码

<style type="text/css">
    .line {
        height: 200px;
        background-color: pink;
    }
    
    .box {
        width: 100px;
        height: 100px;
        background-color: rgb(30, 230, 245);
        transition: all 1s linear;
    }
    
    .line:hover .box {
        /* 位移 */
        transform: translate(100px, 30px);
    }
</style>

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

效果图:

image

我们可以看到,鼠标移上去之后,蓝色盒子,分别向左和向下移动了一段距离。

9.2 缩放

缩放scale(x, y)可以对元素进行水平和垂直方向的缩放,xy的取值可为小数;
/*宽和高都放大1倍*/
transform: scale(1.5);

示例代码:

<style type="text/css">
    .box {
        width: 200px;
        height: 200px;
        background-color: pink;
        margin: 50px auto;
        transition: all 2s linear;
    }

    .box:hover {
        /* 缩放 */
        transform: scale(0.5);
    }
</style>

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

效果图:

image

9.3 旋转

旋转rotate(deg)可以对元素进行旋转,正值为顺时针,负值为逆时针;
  • a、当元素旋转以后,坐标轴也跟着发生的转变
  • b、调整顺序可以解决,把旋转放到最后
/* 顺时针旋转 90度 */
transform: rotate(90deg);

示例代码:

<style type="text/css">
    .box {
        width: 200px;
        height: 200px;
        background-color: #0df3cd;
        margin: 100px auto;
        transition: all 2s linear;
    }
    
    .box:hover {
        transform: rotate(-90deg);
    }
</style>

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

效果图:

image

旋转原点:

默认情况下,旋转是按照元素的中心点旋转的,但是我们可以手动设置元素旋转的中心点。
transform-origin: 30px 40px;

示例代码:

<style type="text/css">
    .box {
        width: 150px;
        height: 150px;
        background-color: cyan;
        margin: 100px auto;
        transition: all 1s linear;
        /* 设置旋转原点位置 */
        /* transform-origin: left top; */
        transform-origin: 30px 40px;
    }
    
    .box:hover {
        transform: rotate(90deg);
    }
</style>

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

效果图:

image

示例代码:扑克牌

<style type="text/css">
    * {
        margin: 0;
        padding: 0;
    }

    .box {
         width: 310px;
         height: 438px;
         border: 1px solid #ccc;
         margin: 50px auto;
         position: relative;
    }

    .box img {
         position: absolute;
         transform-origin:bottom;
         transition: all 2s linear;
    }

    .box:hover img:nth-child(1) {
         transform: rotate(10deg);
    }
    .box:hover img:nth-child(2) {
         transform: rotate(20deg);
    }
    .box:hover img:nth-child(3) {
         transform: rotate(30deg);
    }
    .box:hover img:nth-child(4) {
         transform: rotate(40deg);
    }
    .box:hover img:nth-child(5) {
         transform: rotate(50deg);
    }
    .box:hover img:nth-child(6) {
         transform: rotate(60deg);
    }
</style>


<div class="box">
      <img src="img/pk1.png" alt="">
      <img src="img/pk1.png" alt="">
      <img src="img/pk1.png" alt="">
      <img src="img/pk1.png" alt="">
      <img src="img/pk1.png" alt="">
      <img src="img/pk1.png" alt="">
</div>

效果图:

image

9.4 倾斜

倾斜skew(deg, deg)可以使元素按一定的角度进行倾斜,可为负值,第二个参数不写默认为0
transform: skew(30deg,30deg);

示例代码:

<style type="text/css">
    .box {
        width: 150px;
        height: 150px;
        background-color: cyan;
        margin: 100px auto;
        transition: all 2s linear;
    }
    
    .box:hover {
        /* 倾斜 */
        transform: skew(30deg, 30deg);
    }
</style>

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

效果图:

image

9.5 矩阵

矩阵matrix()把所有的2D转换组合到一起,需要6个参数。transform-origin可以调整元素转换的原点,但是对于transform: translate(x,y)没有影响。我们可以同时使用多个转换,其格式为:transform: translate() rotate() scale() ...等,其顺序会影转换的效果。

详细可参见

10. 3D 转换

10.1 3D 坐标轴

XYZ分别表示空间的3个维度,三条轴互相垂直。如下图:

image

网格状的正方形,可以想象成是我们的电脑桌面2D平面。

在 3D 转换中,前面 2D 转换的属性在这都可以使用:

  • 位移
transform:translate(100px,100px,100px);
  • 旋转
transform:rotate(30deg,30deg,30deg);
  • 缩放
transform:scale(2,0.5,0.5);
  • 倾斜
transform:skew(30deg,30deg,30deg);

3D转换中,一定要加上一个透视属性,才能在电脑2D平面中显示出3D的效果,透视属性请看下章。

10.2 透视(perspective)

电脑显示屏是一个2D平面,图像之所以具有立体感(3D效果),其实只是一种视觉呈现,通过透视可以实现此目的。perspective通过透视产生的3D效果,只是视觉呈现而已,并不是真正的3d立体的盒子;就是近大远小的效果。

透视的概念其实很简单,就是“近大远小”。

image

举个例子:

2D转换的时候,我们知道一个translate属性,他分别可以设置向左向右或者向上向下平移,但是却不能向里面或外面平移。
<style>
    .box{
        width: 550px;
        height: 150px;
        margin: 100px auto;
        padding: 6px;
        border: 1px dashed #ccc;
    }
    .box li{
        float: left;
        width: 150px;
        height: 150px;
        padding: 0;
        list-style: none;
        margin-right: 50px;
        transition: all 0.5s linear;
        
    }
    .box li:first-child{
        background: salmon;
    }
    .box li:nth-child(2){
        background: deepskyblue;
    }
    .box li:last-child{
        background: khaki;
        margin-right: 0px;
    }
    /* 第一个盒子向X轴的负方向移动100px */
    .box li:first-child:hover{
        transform: translateX(-100px);
    }
    /* 第二个盒子向Y轴的正方向移动100px */
    .box li:nth-child(2):hover{
        transform: translateY(100px);
    }
    /* 第三个盒子Z轴的负方向移动100px */
    .box li:last-child:hover{
        transform: translateZ(-100px);
    }
</style>

<ul class="box">
    <li></li>
    <li></li>
    <li></li>
</ul>

效果图:

image

没有加透视属性的时候,因为z轴是垂直电脑平面射出来的,translateZ是看不出效果的。

如何设置透视属性?

给当前元素的直接父元素添加perspective: 800px;透视属性,注意这个值可以是随意的,但是最佳展现距离是600px~1000px
<style>
    .box{
        width: 550px;
        height: 150px;
        margin: 100px auto;
        padding: 6px;
        border: 1px dashed #ccc;
        /* 给变换的 li 的直接父元素 ul 添加透视属性 perspective */
        perspective: 800px;
    }
    .box li{
        float: left;
        width: 150px;
        height: 150px;
        padding: 0;
        list-style: none;
        margin-right: 50px;
        transition: all 0.5s linear;
        
    }
    .box li:first-child{
        background: salmon;
    }
    .box li:nth-child(2){
        background: deepskyblue;
    }
    .box li:last-child{
        background: khaki;
        margin-right: 0px;
    }
    /* 第一个盒子向X轴的负方向移动100px */
    .box li:first-child:hover{
        transform: translateX(-100px);
    }
    /* 第二个盒子向Y轴的正方向移动100px */
    .box li:nth-child(2):hover{
        transform: translateY(100px);
    }
    /* 第三个盒子Z轴的负方向移动100px */
    .box li:last-child:hover{
        transform: translateZ(-100px);
    }
</style>

<ul class="box">
    <li></li>
    <li></li>
    <li></li>
</ul>

效果图:

image

如图所示,在ul加上透视属性后,第三个盒子向着z轴的负方向移动了100px

透视可以将一个2D平面,在转换的过程当中,呈现3D效果。(没有perspective,便“没有”Z轴)并非任何情况下都需要透视效果。

10.3 3D呈现(transform-style)

什么是3D呈现呢?不要与前面的透视搞混,透视只能使一个物体呈现近大远小的状态,不能呈现出一个立体感的东西,比如我在页面上用六个面组成一个正方形,通过透视你可能只能改变他的远近距离,并不能让他看起来像个立体的盒子,所以这里需要用到另一个属性:transform-style
transform-style: preserve-3d | flat
  • flat:所有子元素在2D平面呈现
  • preserve-3d:保留3D空间

必须设置在父元素身上并且父元素有转换(就是有变形)并且子元素也得有转换(变形)才能看得到效果。

1、示例代码:正方体

<style type="text/css">
    * {
         margin: 0;
         padding: 0;

    }

    .box {
         width: 200px;
         height: 200px;
         margin: 150px auto;

         position: relative;
        
         /* 透视 */
         /* perspective: 1000px; */

         /* 转为立方体 */
         transform-style: preserve-3d;

         transform: rotateY(45deg) rotateX(30deg);
    }

    .box>div {
         position: absolute;
         width: 100%;
         height: 100%;
    }

    .left {
        background-color: pink;
        transform: rotateY(-90deg) translateZ(150px);
    }

    .right {
        background-color: green;
        transform: rotateY(90deg) translateZ(150px);
    }

    .top {
        background-color: orange;
        transform: rotateX(90deg) translateZ(150px);
    }

    .bottom {
        background-color: blue;
        transform: rotateX(-90deg) translateZ(150px);
    }

    .before {
        background-color: red;
        transform: translateZ(150px);
    }

    .back {
        background-color: greenyellow;
        transform: translateZ(-150px);
    }

</style>

<div class="box">
    <div class="left"></div>
    <div class="right"></div>
    <div class="top"></div>
    <div class="bottom"></div>
    <div class="before"></div>
    <div class="back"></div>
</div>

效果图:

image

2、示例代码:3D 导航

<style type="text/css">
    
     * {
          margin: 0;
          padding: 0;
          list-style: none;
     }

     nav {
          width: 600px;
          height: 60px;
          line-height: 60px;
          margin: 200px auto;
     }

     li {
          height: 60px;
          width: 150px;
          float: left;
          position: relative;
          transform-style: preserve-3d;
          transition: all 0.5s ease-in;
     }

     span {
          position: absolute;
          width: 150px;
          height: 60px;
          display: block;
         color: #fff;
          text-align: center;
     }

     span:first-child{
          background-color: #ff287a;
         transform: rotateX(90deg) translateZ(30px);
     }

     span:last-child{
         transform: translateZ(30px);
         background-color: #00bdab;
     }

     li:hover {
          transform: rotateX(-90deg);
     }
</style>

<nav>
    <ul>
        <li>
            <span>Home</span>
            <span>主页</span>
        </li>
        <li>
            <span>Menu</span>
            <span>菜单</span>
        </li>
        <li>
            <span>Admin</span>
            <span>管理</span>
        </li>
        <li>
            <span>About</span>
            <span>关于我们</span>
        </li>
    </ul>
</nav>

效果图:

image

10.4 3D呈现案例:3D轮播图

1、普通版 3D 轮播图

实现思路:

  • 通过CSS3transform-style: preserve-3d的概念,将视图设置成3D展示模式;
  • 四张图片,分别设置其绕着X轴旋转的角度,分别对应四个立体面;
  • 将旋转好的图片沿着Z轴平移盒子宽度的一半;
  • 定义一个全局变量num,用来记录按钮点击的次数,当当按动按钮的时候,让ul旋转num*90°

示例代码:

<style>
    * {
        padding: 0;
        margin: 0;
        list-style-type: none;
    }
    
    .box {
        width: 960px;
        height: 540px;
        /* border: 5px solid #999; */
        margin: 150px auto;
    }
    
    .box ul {
        width: 960px;
        height: 540px;
        position: relative;
        transform-style: preserve-3d;
        transition: transform .6s;
    }
    
    .box ul li {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
    }
    
    img {
        width: 100%;
        height: 100%;
    }
    
    .box ul li:nth-child(1) {
        transform: rotateX(90deg) translateZ(270px);
    }
    
    .box ul li:nth-child(2) {
        transform: rotateX(-90deg) translateZ(270px);
    }
    
    .box ul li:nth-child(3) {
        transform: rotateX(180deg) translateZ(270px);
    }
    
    .box ul li:nth-child(4) {
        transform: translateZ(270px);
    }
    
    .btn {
        width: 1080px;
        margin: 0 auto;
        position: relative;
        height: 0px;
        top: -470px;
    }
    
    .btn button {
        width: 40px;
        height: 80px;
        border-radius: 10px;
        background: rgba(0, 0, 0, 0.2);
        border: none;
        outline: none;
        font: 900 24px/80px '宋体';
        color: #fff;
    }
    
    .btn button:frist-child {
        float: left;
    }
    
    .btn button:last-child {
        /* border-radius: 0 10px 10px 0; */
        float: right;
    }
</style>

<div class="box">
    <ul>
        <li><img src="./imgs/1.jpg" alt=""></li>
        <li><img src="./imgs/2.jpg" alt=""></li>
        <li><img src="./imgs/3.jpg" alt=""></li>
        <li><img src="./imgs/4.jpg" alt=""></li>
    </ul>
</div>
<div class="btn">
    <button>&lt;</button>
    <button>&gt;</button>
</div>

<script type="text/javascript">
    var btn = document.querySelectorAll('button');
    var box = document.querySelector('.box');
    var _ul = box.querySelector('ul');
    var num = 0;

    // btn 获取到的是一个伪数组
    btn[1].onclick = function () {
        num++;
        _ul.style.transform = 'rotateX(' + num * 90 + 'deg)'
    }

    btn[0].onclick = function () {
        num--;
        _ul.style.transform = 'rotateX(' + num * 90 + 'deg)';
    }
</script>

效果图:

image

2、切割版 3D 轮播图

实现思路:

  • 结构上将之前定义好的ul重复四次;
  • 设定延时,整个动画执行时间是0.8s,设定每一个ul延迟执行0.2s,即第一个延时0s,第二个延时0.2s,第三个延时0.4s,第四个延时0.6s
  • 其余步骤同上,着重强调的是,相对于上面的案例,本案例给按钮加了限制,监听第一次所有的ul旋转结束之后,按钮才能再一次被点击。

示例代码:

<style>
    * {
        padding: 0;
        margin: 0;
        list-style-type: none;
    }
    
    .box {
        width: 960px;
        height: 540px;
        margin: 150px auto;
        display: flex;
    }
    
    .box ul {
        width: 960px;
        height: 540px;
        position: relative;
        transform-style: preserve-3d;
        transition: transform .8s;
    }
    
    .box ul li {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
        overflow: hidden;
    }
    
    img {
        width: 960px;
        height: 540px;
    }
    
    /* 设定延时 */
    .box ul:nth-child(1) {
      transition-delay:0s;
    }
    .box ul:nth-child(2) {
      transition-delay:.2s;
    }
    .box ul:nth-child(3) {
      transition-delay:.4s;
    }
    .box ul:nth-child(4) {
      transition-delay:.6s;
    }
    
    /* 拼凑图片 */
    .box ul:nth-child(2) img {
      margin-left: -240px;
    }
    .box ul:nth-child(3) img {
      margin-left: -480px;
    }
    .box ul:nth-child(4) img {
      margin-left: -720px;
    }
    
    .box ul li:nth-child(1) {
        transform: rotateX(90deg) translateZ(270px);
    }
    
    .box ul li:nth-child(2) {
        transform: rotateX(-90deg) translateZ(270px);
    }
    
    .box ul li:nth-child(3) {
        transform: rotateX(180deg) translateZ(270px);
    }
    
    .box ul li:nth-child(4) {
        transform: translateZ(270px);
    }
    
    .btn {
        width: 1080px;
        margin: 0 auto;
        position: relative;
        height: 0px;
        top: -470px;
    }
    
    .btn button {
        width: 40px;
        height: 80px;
        border-radius: 10px;
        background: rgba(0, 0, 0, 0.2);
        border: none;
        outline: none;
        font: 900 24px/80px '宋体';
        color: #fff;
    }
    
    .btn button:frist-child {
        float: left;
    }
    
    .btn button:last-child {
        /* border-radius: 0 10px 10px 0; */
        float: right;
    }
</style>


<div class="box">
<ul>
  <li><img src="./imgs/1.jpg" alt=""></li>
  <li><img src="./imgs/2.jpg" alt=""></li>
  <li><img src="./imgs/3.jpg" alt=""></li>
  <li><img src="./imgs/4.jpg" alt=""></li>
</ul>

<ul>
  <li><img src="./imgs/1.jpg" alt=""></li>
  <li><img src="./imgs/2.jpg" alt=""></li>
  <li><img src="./imgs/3.jpg" alt=""></li>
  <li><img src="./imgs/4.jpg" alt=""></li>
</ul>

<ul>
  <li><img src="./imgs/1.jpg" alt=""></li>
  <li><img src="./imgs/2.jpg" alt=""></li>
  <li><img src="./imgs/3.jpg" alt=""></li>
  <li><img src="./imgs/4.jpg" alt=""></li>
</ul>

<ul>
  <li><img src="./imgs/1.jpg" alt=""></li>
  <li><img src="./imgs/2.jpg" alt=""></li>
  <li><img src="./imgs/3.jpg" alt=""></li>
  <li><img src="./imgs/4.jpg" alt=""></li>
</ul>
</div>
<div class="btn">
<button>&lt;</button>
<button>&gt;</button>
</div>

<script type="text/javascript">
    var btn = document.querySelectorAll('button');
    var box = document.querySelector('.box');
    var _ul = box.querySelectorAll('ul');
    var num = 0;
    var flag = true;
    // btn 获取到的是一个伪数组    
    btn[1].onclick = function () {
      if (flag) {
        flag = false;
        num++;
        for (var i = 0; i < _ul.length; i++) {
          _ul[i].style.transform = 'rotateX(' + num * 90 + 'deg)';
    
        }
        // 监听最后一个transition事件结束的时候 将flag 置为 true 防止重复点击
        _ul[_ul.length - 1].addEventListener('transitionend', function () {
          flag = true;
        })
      }
    }
    btn[0].onclick = function () {
      if (flag) {
        flag = false;
        num--;
        for (var i = 0; i < _ul.length; i++) {
          _ul[i].style.transform = 'rotateX(' + num * 90 + 'deg)';
    
        }
        _ul[_ul.length - 1].addEventListener('transitionend', function () {
          flag = true;
        })
      }
    
    }
</script>

效果图:

image

10.5 backface-visibility

backface-visibility属性定义当元素不面向屏幕时是否可见。

如果在旋转元素不希望看到其背面时,该属性很有用。有两个属性:

  • 1、visible背面是可见的
  • 2、hidden背面是不可见的

深海丶Deepsea
3.9k 声望1.4k 粉丝

Trust yourself,You know more than you think you do.