通过一个小案例学习高级CSS:Nature.Section 1 Banner

336 阅读6分钟

最终效果

Nature.gif

代码

<!-- html -->

    <header class="header">
      <div class="logo-box">
        <img class="logo" src="./images/logo-white.png" alt="logo" />
      </div>

      <h1 class="heading-primary">
        <span class="title">OUTDOORS</span>
        <span class="subtitle">is where life happens</span>

        <!-- pick out the color class from the entire class: a good practice -->
        <a href="#" class="btn btn-white btn-animated"> DISCOVER OUR TOURS </a>
      </h1>
    </header>

/* css */

/*
COLORS

Light green: #7ed56f

Medium green: #55c57a

Dark green: #28b485

*/

:root {
    --light-green: #7ed56f;
    --medium-green: #55c57a;
    --dark-green: #28b485;
}



* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}


body {
    font: "Lato", sans-serif, 400, 16px;
    line-height: 1.7;
    color: #777;
    padding: 30px;
}


.header {
    position: relative;
    height: 95vh;
    background-image: linear-gradient(
        to bottom,
        rgba(126, 213, 111, 0.781),
        rgba(85, 197, 122, 0.801),
        rgba(40, 180, 133, 0.801)),
    url("../images/header.png");
    background-size: cover;
    background-position: top;

    clip-path: polygon(0% 0%, 100% 0, 100% 75vh, 0 100%);

}


.logo-box{
    position:absolute;
    top:40px;
    left: 40px;
    width: 5vw;
}

.logo-box img{
    width: 100%;
}




.heading-primary{
    position: absolute;
    top: 40%;
    left: 50%;
    transform: translate(-50%, -50%);

    color: rgba(255, 255, 255, 0.863);

    text-align: center;



    text-transform: uppercase;
}

.heading-primary span{
    display: block;
}


.heading-primary .title{
    font-size: 65px;
    font-weight: 600;
    letter-spacing: 35px;

    animation: move-in-left 3s;
    backface-visibility: hidden;
}

.heading-primary .subtitle{
    font-size: 20px;
    font-weight: 700;
    letter-spacing: 19px;
    margin-bottom: 40px;

    animation: move-in-right 3s;
}



/* ctrl + D to select the same words */
@keyframes move-in-left {
    0%{
        opacity: 0;
        transform: translateX(-100px);
    }


    80%{
        transform: translateX(20px);
    }

    100%{
        opacity: 1;
        transform: translate(0);
    }
}

@keyframes move-in-right {
    0%{
        opacity: 0;
        transform: translateX(100px);
    }

    80%{
        transform: translateX(-20px);
    }

    100%{
        opacity: 1;
        transform: translate(0);
    }
}



.btn:link,
.btn:visited{
    position: relative;
    display: inline-block;
    text-transform: uppercase;
    text-decoration: none;
    padding:15px 40px;

    border-radius: 100px;

    font-size: 17px;

    transition: transform .4s;
}




/* the animation effect: fantastic */
.btn:hover{

    transform: translateY(-3px);
    box-shadow: 0 10px  20px rgba(0, 0, 0, .2);
}

.btn:active{

    transform: translateY(-1px);
    box-shadow: 0 5px 10px  rgba(0, 0, 0, .4);
}


.btn::after{
    position: absolute;
    top: 0;
    left: 0;
    content: '';
    height: 100%;
    width: 100%;
    border-radius: 100px;

    transition: all .4s;
    z-index: -1;
}


.btn:hover::after{
    transform: scaleX(1.4) scaleY(1.6);
    opacity: 0;
}

.btn-white{
    background-color: #fff;
    color: #777;
}


.btn-white::after{
    background-color: #fff
}

.btn-animated{
    animation: move-in-bottom 2s ease-in .75s;
    animation-fill-mode: backwards;
}



@keyframes move-in-bottom {
    0%{
        opacity: 0;
        transform: translateY(20px);
    }


    100%{
        opacity: 1;
        transform: translateY(0);
    }
}

Good Practice

颜色样式单独定义

<a href="#" class="btn btn-white btn-animated"> DISCOVER OUR TOURS </a>
.btn-white{ background-color: #fff; color: #777; }

.btn:link, .btn:visited{ 
    position: relative; 
    display: inline-block; 
    text-transform: uppercase; 
    text-decoration: none; 
    padding:15px 40px; 
    border-radius: 100px; 
    font-size: 17px; 
    transition: transform .4s; 
}

在上面的实践中, 将按钮的白色样式从总体的样式中单独提取出来, 由此提高了css样式的可复用性。

我们可以把css的样式理解为编程语言中的函数, 在编程时, 我们总是力求每个函数只做一件事, 每个函数做的事情越少, 那么可复用性则越。css的样式也是一样的, 如果css的不同样式块只表示一个样式, 拿按钮举例,比如按钮颜色、按钮字体、按钮大小、按钮动画的样式单独定义的话, 按钮样式的可复用性和自由度就高了。

具体的可以参考element-uibootstrap这两个UI框架。你会发现里面的样式定义也有着类似的思路。

CSS 变量

即使不使用sass或less, 我们也可以在css当中定义变量。使用变量的好处有很多, 语义化, 增强代码的可维护性等,总之是个好东西。

既然是变量, 那么一定就有其作用域,css变量受级联的约束,并从其父级继承其值(你定义了,你的子孙后代都可以用,因为从你这继承了), 最佳实践推荐我们在root当中定义变量,使用两个-号开头。

如下:

:root {
    --light-green: #7ed56f;
    --medium-green: #55c57a;
    --dark-green: #28b485;
}

使用变量时则var(--light-green)即可。

使用块元素包裹图片

因为图片属于行内块元素, 因此我们在放置图片时有时不是很好使。一般推荐先用div包裹住图片元素后,然后再让图片自适应div,接着我们只要操纵div这个块元素就行。

注意, 这只是一种推荐做法, 但其实只要能实现你的目标效果就行,并不一定得采取这种做法。

<div class="logo-box">
    <img class="logo" src="./images/logo-white.png" alt="logo" />
</div>
.logo-box{
    position:absolute;
    top:40px;
    left: 40px;
    width: 5vw;
}

.logo-box img{
    width: 100%;
}

CSS Properties

linear-gradient

线性渐变属性可以实现一种沿着某个角度的线性渐变效果。

可以添加一个角度, 用来指明渐变的方向(默认为180deg), 也可以添加颜色步长来确定每个颜色变化中点。

image.png

你可以使用该实例CSS linear-gradient overlay (codepen.io)深入探索linear-gradient。

clip-path

顾名思义,这个属性就好比“沿虚线剪开”。同时它定义了很多“虚线函数”。polygon就是其中的一个折线函数,只要在该函数内定义多个平面坐标,就会得到一个沿着这些坐标裁剪的盒子。

这是裁剪前的盒子:

image.png

.header {
    position: relative;
    height: 95vh;
    /* deg 0 degree means from bottom to top */
    /* how to make an effect that a picture covered by a transparent color */
    background-image: linear-gradient(
        rgba(126, 213, 111, 0.781),
        rgba(85, 197, 122, 0.801),
        rgb(40, 180, 133)),
    url("../images/header.png");
    background-size: cover;
    background-position: top;
}

接下来我们定义clip-path属性:

.header {
    position: relative;
    height: 95vh;
    /* deg 0 degree means from bottom to top */
    /* how to make an effect that a picture covered by a transparent color */
    background-image: linear-gradient(
        rgba(126, 213, 111, 0.781),
        rgba(85, 197, 122, 0.801),
        rgb(40, 180, 133)),
    url("../images/header.png");
    background-size: cover;
    background-position: top;

    /* the new thing: https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape/polygon */
    clip-path: polygon(0% 0%, 100% 0, 100% 75vh, 0 100%); 
}

polygon函数内分别定义了4个坐标(0% 0%, 100% 0, 100% 75vh, 0 100%),这四个坐标是按照顺时针方向定义的。在图中为以下4点:

image.png

裁剪后即为最终效果:

image.png

当然, polygon还有不少的别的玩法,理论上你可以定义无数点。你甚至可以定义一个箭头标识:

image.png

Animations

Effect - 1 Moving From A Certain Direction

Nature_text.gif

@keyframes move-in-left {
    0%{
        opacity: 0;
        transform: translateX(-100px);
    }


    80%{
        transform: translateX(20px);
    }

    100%{
        opacity: 1;
        transform: translate(0);
    }
}

element {
    animation: move-in-left 3s;
}

animation-fill-mode 设置为backwards可使得元素在一开始处于第一帧的状态,随后再开始接下来的关键帧的动画。

Effect - 2 Floating Box

让按钮向上移动的同时,给盒子一个阴影,产生一种按钮脱离网页上浮的效果。并且在按钮处在hover状态时漂浮的高一点,在按下按钮时即active状态下,向下降低,同时阴影效果变深,非常有意思的一个动画。

2.gif

// 按钮 基础样式
.btn:link,
.btn:visited{
    position: relative;
    display: inline-block;
    text-transform: uppercase;
    text-decoration: none;
    padding:15px 40px;

    border-radius: 100px;

    font-size: 17px;
    
    // 1 定义变换
    transition: transform .4s;
}

// 按钮 颜色样式
.btn-white{
    background-color: #fff;
    color: #777;
}


// 2 hover 时的状态
.btn:hover{
    // 向上移动
    transform: translateY(-3px);
    // 添加阴影
    box-shadow: 0 10px  20px rgba(0, 0, 0, .2);
}


// 3 点击时的状态
.btn:active{

    transform: translateY(-1px);
    // 阴影变窄, 颜色变深, 会给人一种更接近地面的感觉
    box-shadow: 0 5px 10px  rgba(0, 0, 0, .4);
}

Effect - 3 Flying Border

3.gif

.btn::after{
    position: absolute;
    top: 0;
    left: 0;
    content: '';
    height: 100%;
    width: 100%;
    border-radius: 100px;

    transition: all .4s;
    z-index: -1;
}


.btn:hover::after{
    transform: scaleX(1.4) scaleY(1.6);
    opacity: 0;
}

.btn-white{
    background-color: #fff;
    color: #777;
}


.btn-white::after{
    background-color: #fff
}

在上面的样式中, after伪元素的样式完全和按钮本身相同,将其放置到按钮背后,当hover时放大的同时消失,于是产生了如上效果。