最终效果
代码
<!-- 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-ui和bootstrap这两个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), 也可以添加颜色步长来确定每个颜色变化中点。
你可以使用该实例CSS linear-gradient overlay (codepen.io)深入探索linear-gradient。
clip-path
顾名思义,这个属性就好比“沿虚线剪开”。同时它定义了很多“虚线函数”。polygon就是其中的一个折线函数,只要在该函数内定义多个平面坐标,就会得到一个沿着这些坐标裁剪的盒子。
这是裁剪前的盒子:
.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点:
裁剪后即为最终效果:
当然, polygon还有不少的别的玩法,理论上你可以定义无数点。你甚至可以定义一个箭头标识:
Animations
Effect - 1 Moving From A Certain Direction
@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状态下,向下降低,同时阴影效果变深,非常有意思的一个动画。
// 按钮 基础样式
.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
.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时放大的同时消失,于是产生了如上效果。