CSS3制作旋转导航

慕课网学习CSS3时,遇到个习题,觉得有必要总结学习下:CSS3制作旋转导航

慕课网习题地址:http://www.imooc.com/code/1883

示例及源码地址:http://codepen.io/airen/pen/icFba

老师的源代码内容太多,太复杂,也没有逻辑讲解,所以我就从头捡重点,一边写,一边分析,并且去掉了兼容性,这样看起来简单,所以下面的代码都是在谷歌浏览器才可以适用的,尤其是CSS3部分!看目标效果图:

image

总结下要点:

1、特殊的字体样式

2、在鼠标移入时,

1)改变了背景色

2)出现了3D旋转

3)出现了下边框

3、这个情况

image

我觉得这里的核心应该是3D旋转,所以我的思路是:

1、在鼠标滑过时

1)实现单个 li 的3D旋转

2)实现单个 li 下边框

3)实现单个 li 背景颜色改变

2、考虑全局布局

3、考虑 Blog 下的特殊情况

那么好,思路有了,咱么来考虑这个单个 li 的3D旋转,不过在这之前先把静态页面写好(自己写哦,可以参考老师的嘛),Open-mouthed smile,做个小的 li ,代码如下:

body:

<body>    
    <ul class="nav-menu">
        <li class="three-d-box"> 
            <a href="#" class="cont">Home</a>    
            <a href="#" class="front">Home</a>            
            <a href="#" class="back">Home</a>                
        </li>
        <li class="three-d-box"> 
            <a href="#" class="cont">Html</a>    
            <a href="#" class="front">Html</a>            
            <a href="#" class="back">Html</a>    
        </li>            
    </ul>    
</body>

css:

       * {
            padding: 0;
            margin: 0;
        }
        body {
            padding: 20px;
        }
        .nav-menu {
            background-color: #74adaa;
            width: 950px;            
            height: 50px;            
            margin: 0 auto;                            
        }
        .three-d-box {
            display: inline-block;            
            position: relative;        
            padding: 0 20px;            
            list-style-type: none;                
        }        
        .three-d-box a {
            display: inline-block;
            width: 100%;
            height: 100%;
            text-align: center;
            line-height: 50px;            
            font-size: 25px;
            color: white;
            text-decoration: none;
            background-color: #74adaa;                
        }
        .three-d-box .cont {
            color: #74adaa;
        }
        .three-d-box .front,
        .three-d-box .back {
            position: absolute;
            left: 0;
            top: 0;            
            border-right: 1px solid #94c0be;
        }

这个大家问题应该不大,看看老师源码应该能明白,这只是静态页面!

image

这里可能需要解释下,为什么要用3个 a 标签,

<a href="#" class="cont">Home</a>
<a href="#" class="front">Home</a>
<a href="#" class="back">Home</a>
因为,这里至少要有两个 a ,用来翻转实现 3D 旋转,一前一后(front , back),这个大家应该明白,所以有了两个 a 标签,但是静态页面上,我们只看到一个,结合旋转效果可以发现,这里的多个 a 标签肯定是在同一个位置的,而且是重合的,所以这里在静态页面上实现,就要给 a 标签 absolute 一下,然后 left & top 肯定为 0;但是这样的话,会出错,因为 li 的内容不一定,导航条可长可短,所以每个 li 的长度应该是自适应内容的,所以宽度不能设置,而 li 里面的 a 又是 absolute ,所以这里 li 与 li 之间就会有各种问题,我不知道你是什么问题,我是这样的,当然一开始也有其他样式的,十分奇怪,

image

所以最后就想了办法,再加一个内容一模一样的 a 标签,className 为 cont ,解决了上述问题,所以你也看到 front 和 back 都做了 absolute 定位和 cont 重合,但是 cont 没有 absolute ,为的是根据导航 li 的长度自适应宽度,好,静态页面完成,看旋转!

1、在鼠标滑过时

1)实现单个 li 的3D旋转

首先要搞明白,这个3D旋转是怎么实现的 ,把老师的源码旋转速度降到 3秒 之后,我看了好些遍,终于明白了,原理是这样:上图!

一开始是这样,也就是静态页面,.front & .back 通过定位实现重合:

image

放到坐标系就是这样,你看到的就是XY对应浏览器宽高这一面;

image

然后,要实现旋转效果需要把静态页面做成这样,当鼠标滑过时, 让 .front 和 .back 这个整体(也就是包裹他两的父元素)顺时针翻转90度(transform: rotateX(90deg)),这样,眼睛会看到 front 从正前方翻过去,. back 从下方翻上来 ; 滑出时,回到原位(即逆时针翻转90度) ;这样就实现了3d 旋转动画!!!听不懂?看图!

静态页面要做成这样:(请忽略此处O)

image

鼠标滑过,包裹他俩的父元素,顺时针翻转90度 ,翻到这样:(请忽略此处O)

image

能明白么?不明白好好想想~~~;或者看看下图:

3D 旋转的时候,其实是在旋转 .front 和 .back 的父元素 ( 即 li :这个时候,li 的中心点应该 在L处,所以上述的变化,就是把这半个长方体,以 L 为原点,立体 顺时针 旋转 90 度。再想想~~

从这样:(请忽略此处O)

image

翻成这样:

image

所以,我们的主要任务就是要把静态页面做好,然后把 li transform:rotateX(90deg) 就好了,难点在静态页面!当然还有这个思路!

放在坐标轴里,我们要把静态页面改成这样就可以了:(请忽略此处O)

image

然而我们之前做的页面把 .front 和 .back 是放在这里的,如下图:

image

两张图一看,大家有思路了嘛?

说之前,先确定这里元素的原点:

注意,原点是居于元素X轴和Y轴的50%处,即O点,CSS变形进行的旋转、位移、缩放,扭曲等操作都是在原点O的基础上进行的;所以我们要在此基础上,完成上面两张图的转换,对,这是在 3d 动态

旋转 变换之前就要做好的;这里的O点既是 .front 和 .back的原点,也是 他们的父元素 li 的原点。

image

然后我们的思路就是:

先把 .back 绕X轴 逆时针旋转90度transform: rotateX(-90deg)

image

然后.back 沿着自身的Z轴(因为之前已经翻转过一次了,所以现在 .back 的Z轴 在图中就是Y轴(我猜的!!!))下移25px , transform: rotateX(-90deg) translateZ(25px);就是这样:

 

image

最后再把 .front 向用户正对面移动 25px 就可以了,即 transform: rotateX(0deg) translateZ(25px);

image

此时看看 .front 和 .back 的父元素(li)的 原点 L,还在原位置 ,但是 .front 和 .back都移到位了,而 L 正好在这个半长方体中间,所以,把 li 沿着X轴顺时针翻转90度,就是我们要的 3D 旋转!

image

上述代码放一起就这些:

        .three-d-box .front {
            height: 49px;
        }
        .three-d-box .front {
            -webkit-transform: rotateX(0deg) translateZ(25px);
            border-bottom: 1px solid #94c0be;            
        }
        .three-d-box .back {
            -webkit-transform: rotateX(-90deg) translateZ(25px) ;
            /* 面对浏览器,translateX(5px)往右5px,translateY(5px)往下5px,translateZ(5px)正对用户5px */
        }
        /* 准备翻转three-d-box
            鼠标滑过时 */
        .three-d-box:hover {
            -webkit-transform: rotateX(90deg);
        }
            /* 规定动画效果是3D和动画时间 */
        .three-d-box {
            -webkit-transform-style: preserve-3d;
            -webkit-transition: all 4s ease;
        }

好了,核心3D旋转就说完了~~~接着看思路:

1、在鼠标滑过时

1)实现单个 li 的3D旋转(已实现)

2)实现单个 li 下边框(已实现)

3)实现单个 li 背景颜色改变(未实现)

 

那么好,我们来改变 li 的背景颜色,感觉这个很简单,摆代码之前发现这个小问题,我们的 li 中间有个外边距,效果图没有,那么好,我们把 父层 li 的margin 改下;

imageimage

就加个margin-right: -7px;    其他的没动,这下就好了;

.three-d-box {
            display: inline-block;            
            position: relative;        
            padding: 0 20px;            
            list-style-type: none;    
            margin-right: -7px;        
        }

改鼠标移入时背景颜色:

        .three-d-box:hover .front,
        .three-d-box:hover .back {
            background-color: #51938f;
            background-image: -webkit-linear-gradient(45deg, #478480 25%, transparent 25%, transparent 75%, #478480 75%, #478480), linear-gradient(45deg, #478480 25%, transparent 25%, transparent 75%, #478480 75%, #478480);
            -webkit-background-size: 5px 5px;
        }

这个地方看不懂呢,可以三条样式一个个放,先放第一个,再放第二个,再放第三个,就很清楚了,其实就是,先加背景色,然后加背景图片,因为背景图片太大了,把背景图片尺寸变小;

至于默认的 HOME 的样式,就给 HOME li 加个className 就好了,比方加个 active , 样式里也加下,就变成这样:

        .three-d-box:hover .front,
        .three-d-box:hover .back,
        .active .front,
        .active .back {
            background-color: #51938f;
            background-image: -webkit-linear-gradient(45deg, #478480 25%, transparent 25%, transparent 75%, #478480 75%, #478480), linear-gradient(45deg, #478480 25%, transparent 25%, transparent 75%, #478480 75%, #478480);
            -webkit-background-size: 5px 5px;
        }

className 也要加哦:

        <li class="three-d-box active"> 
            <a href="#" class="cont">Home</a>    
            <a href="#" class="front">Home</a>                
            <a href="#" class="back">Home</a>                
        </li>

好了,这下进行第二步:

1、在鼠标滑过时(已实现)

1)实现单个 li 的3D旋转(已实现)

2)实现单个 li 下边框(已实现)

3)实现单个 li 背景颜色改变(已实现)

2、考虑全局布局(未实现)

把第一个做好的 li 复制几个就好了,注意去掉 active ,复制好了,可能会这样:

image

那么就把字体调小点就可以了,我是改成了 24px ,当然你也可以把 ul 改长点;

那么好,现在就进行第三步了:

1、在鼠标滑过时(已实现)

1)实现单个 li 的3D旋转(已实现)

2)实现单个 li 下边框(已实现)

3)实现单个 li 背景颜色改变(已实现)

2、考虑全局布局(已实现)

3、考虑 Blog 下的特殊情况(未实现)

当我们在 Blog 下放上 明细的代码时,其实也就是这样,

        <li class="three-d-box"> 
            <a href="#" class="cont">Blog</a>    
            <a href="#" class="front">Blog</a>                
            <a href="#" class="back">Blog</a>
            <ul class="dropMenu">
                <li class="three-d-box">
                    <a href="#" class="cont">Html5</a>
                    <a href="#" class="front">Html5</a>
                    <a href="#" class="back">Html5</a>
                </li>
                <li class="three-d-box">
                    <a href="#" class="cont">Css3</a>
                    <a href="#" class="front">Css3</a>
                    <a href="#" class="back">Css3</a>
                </li>
                <li class="three-d-box">
                    <a href="#" class="cont">Javascript</a>
                    <a href="#" class="front">Javascript</a>
                    <a href="#" class="back">Javascript</a>
                </li>
            </ul>                
        </li>

然后调整下格式:

        .dropMenu {
        position: absolute;        
        left: 0;        
        }        
        .dropMenu .three-d-box {
            width: 100%;
        }

结果就发现这样了:

image

然后当我们鼠标移上时,就这样: 
image

我们看效果图:下拉菜单 和 Blog 应该在两个元素内部,所以 Blog 的父元素 3D 翻转时,下拉菜单的父元素并没有翻转,而是 变长显示了出来,所以这个时候,应该是 横向导航里 li 里面有两个元

素,一个包裹了 Blog ,包括里面的三个 a, 一个包裹了下拉菜单 ul 及其内容。

imageimage

原来的结构:

 

        <li class="three-d-box"> 
            <a href="#" class="cont">Blog</a>    
            <a href="#" class="front">Blog</a>                
            <a href="#" class="back">Blog</a>
            <ul class="dropMenu">
                <li class="three-d-box">
                    <a href="#" class="cont">Html5</a>
                    <a href="#" class="front">Html5</a>
                    <a href="#" class="back">Html5</a>
                </li>
                <li class="three-d-box">
                    <a href="#" class="cont">Css3</a>
                    <a href="#" class="front">Css3</a>
                    <a href="#" class="back">Css3</a>
                </li>
                <li class="three-d-box">
                    <a href="#" class="cont">Javascript</a>
                    <a href="#" class="front">Javascript</a>
                    <a href="#" class="back">Javascript</a>
                </li>
            </ul>                
        </li>


为了方便起见,现在我们给这个 li 改下结构,把 Blog 和 下拉菜单分别包裹在不同的元素内: 

        <li> 
            <a href="#" class="three-d-box">
                <span href="#" class="cont">Blog</span>    
                <span href="#" class="front">Blog</span>                
                <span href="#" class="back">Blog</span>
            </a>            
            <ul class="dropMenu">
                <li>
                    <a href="#" class="three-d-box">
                        <span href="#" class="cont">Html5</span>    
                        <span href="#" class="front">Html5</span>                
                        <span href="#" class="back">Html5</span>
                    </a>                    
                </li>                
                <li>
                    <a href="#" class="three-d-box">
                        <span href="#" class="cont">Css3</span>    
                        <span href="#" class="front">Css3</span>                
                        <span href="#" class="back">Css3</span>
                    </a>                    
                </li>
                <li>
                    <a href="#" class="three-d-box">
                        <span href="#" class="cont">Javascript</span>    
                        <span href="#" class="front">Javascript</span>                
                        <span href="#" class="back">Javascript</span>
                    </a>                    
                </li>                
            </ul>                
        </li>

 

能明白么?现在咱们把所有代码和样式都改下:

<style>
    /* 基本样式 */
        * {
            padding: 0;
            margin: 0;
        }
        body {
            padding: 20px;
        }
        .navMenu {
            background-color: #74adaa;
            width: 950px;            
            height: 50px;            
            margin: 0 auto;                            
        }
        .navMenu>li {
            display: inline-block;    
            list-style-type: none;        
            margin-right: -7px;                                
        }        
        .navMenu li a {
            width: 100%;
            height: 100%;
            display: block;
            line-height: 50px;            
            font-size: 20px;
            color: white;
            text-decoration: none;
            text-align: center;                        
        }
        .three-d-box {                                    
            position: relative;                        
        }
        .three-d-box .cont {
            display: block;
            color: #74adaa;
            padding: 0 30px;
            height: 50px;
        }                            
        .three-d-box .front,
        .three-d-box .back {            
            display: block;
            width: 100%;
            height: 100%;            
            position: absolute;            
            left: 0;
            top: 0;            
            border-right: 1px solid #94c0be;
            background-color: #74adaa;
        }
        /* 3d旋转准备样式 */
        .three-d-box .front {
            height: 49px;
        }
        .three-d-box .front {
            -webkit-transform: rotateX(0deg) translateZ(25px);
            border-bottom: 1px solid #94c0be;            
        }
        .three-d-box .back {
            -webkit-transform: rotateX(-90deg) translateZ(25px) ;
            /* 面对浏览器,translateX(5px)往右5px,translateY(5px)往下5px,translateZ(5px)正对用户5px */

        }
        /* 准备翻转three-d-box
            鼠标滑过时 */
        .three-d-box:hover,
        .three-d-box:focus {
            -webkit-transform: rotateX(90deg);
        }
        .three-d-box:hover .front,
        .three-d-box:hover .back,
        .active .front,
        .active .back {
            background-color: #51938f;
            background-image: -webkit-linear-gradient(45deg, #478480 25%, transparent 25%, transparent 75%, #478480 75%, #478480), linear-gradient(45deg, #478480 25%, transparent 25%, transparent 75%, #478480 75%, #478480);
            -webkit-background-size: 5px 5px;
        }
            /* 鼠标移出时 */        
        .three-d-box {            
            -webkit-transform-style: preserve-3d;
            -webkit-transition: all 1s ease;
        }
        .dropMenu {
            position: absolute;        
            top: 70px;    
            background-color: #74adaa;    
        }        
        .dropMenu li a {
            width: 100%;
        }    
        .dropMenu li {            
            list-style-type: none;
            height: 0;        
            -webkit-transform: rotateX(90deg);    
            -webkit-transition: all 4s ease;
        }    
        .navMenu>li:hover .dropMenu li {
            -webkit-transform: rotateX(0deg);
            height: 50px;
        }            
    </style>

body:

<body>    
    <ul class="navMenu">
        <li>            
            <a href="#" class="three-d-box active">    
                <span href="#" class="cont">Home</span>            
                <span href="#" class="front">Home</span>                
                <span href="#" class="back">Home</span>
            </a>
        </li>        
        <li> 
            <a href="#" class="three-d-box">
                <span href="#" class="cont">Service</span>    
                <span href="#" class="front">Service</span>                
                <span href="#" class="back">Service</span>
            </a>
        </li>
        <li> 
            <a href="#" class="three-d-box">
                <span href="#" class="cont">Products</span>    
                <span href="#" class="front">Products</span>                
                <span href="#" class="back">Products</span>
            </a>
        </li>
        <li> 
            <a href="#" class="three-d-box">
                <span href="#" class="cont">About</span>    
                <span href="#" class="front">About</span>                
                <span href="#" class="back">About</span>
            </a>
        </li>
        <li> 
            <a href="#" class="three-d-box">
                <span href="#" class="cont">Contact</span>    
                <span href="#" class="front">Contact</span>                
                <span href="#" class="back">Contact</span>
            </a>
        </li>            
        <li> 
            <a href="#" class="three-d-box">
                <span href="#" class="cont">Blog</span>    
                <span href="#" class="front">Blog</span>                
                <span href="#" class="back">Blog</span>
            </a>            
            <ul class="dropMenu">
                <li>
                    <a href="#" class="three-d-box">
                        <span href="#" class="cont">Html5</span>    
                        <span href="#" class="front">Html5</span>                
                        <span href="#" class="back">Html5</span>
                    </a>                    
                </li>                
                <li>
                    <a href="#" class="three-d-box">
                        <span href="#" class="cont">Css3</span>    
                        <span href="#" class="front">Css3</span>                
                        <span href="#" class="back">Css3</span>
                    </a>                    
                </li>
                <li>
                    <a href="#" class="three-d-box">
                        <span href="#" class="cont">Javascript</span>    
                        <span href="#" class="front">Javascript</span>                
                        <span href="#" class="back">Javascript</span>
                    </a>                    
                </li>    
                <li>
                    <a href="#" class="three-d-box">
                        <span href="#" class="cont">Videogames</span>    
                        <span href="#" class="front">Videogamess</span>                
                        <span href="#" class="back">Videogamess</span>
                    </a>                    
                </li>            
            </ul>                
        </li>
        <li> 
            <a href="#" class="three-d-box">
                <span href="#" class="cont">Shop On-Line</span>    
                <span href="#" class="front">Shop On-Line</span>                
                <span href="#" class="back">Shop On-Line</span>
            </a>
        </li>                
    </ul>    
</body>

样式里最后几行就是处理 Blog 下的特殊情况的,太累了,不写了,自己看代码,不懂再问我,,,

原理就是:一开始,将 .dropMenu 下的 li 高度设为0且 顺时针旋转90度,这样用户就看不到了呀,鼠标滑过时,再将高度设为 50px , 不旋转,就回来了呀,,,

欢迎拍砖留言。。。

posted @ 2018-02-01 20:43  xianshenglu  阅读(357)  评论(0编辑  收藏  举报