上次小试牛刀后,这次看一个比较难的,纯css做一个有3d效果的按钮:
先把按钮的外表做出来,添加三个按钮:
<button class="big-button">don't</button>
<button class="big-button">push</button>
<button class="big-button">me</button>
添加颜色变量,把按钮居中,然后去掉默认样式:
:root {
--backgroundColor: rgba(246, 241, 209);
--colorShadeA: rgb(106, 163, 137);
--colorShadeB: rgb(121, 186, 156);
--colorShadeC: rgb(150, 232, 195);
--colorShadeD: rgb(187, 232, 211);
--colorShadeE: rgb(205, 255, 232);
}
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700");
* {
box-sizing: border-box;
}
*::before, *::after {
box-sizing: border-box;
}
body {
font-family: 'OpenSans', sans-serif;
font-size: 1rem;
line-height: 2;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
min-height: 100vh;
background: var(--backgroundColor);
}
button {
position: relative;
display: inline-block;
cursor: pointer;
outline: none; /*border 外面的边*/
border: 0;
vertical-align: middle;
text-decoration: none;
font-size: 1.5rem;
color:var(--colorShadeA);
font-weight: 700;
text-transform: uppercase;
font-family: inherit;
}
button.big-button {
padding: 1em 2em;
border: 2px solid var(--colorShadeA);
border-radius: 1em;
background: var(--colorShadeE);
}
效果如下:
现在只有一层,还有两层,可以用伪元素来实现第二层,做一个一样大小但背景色不同的按钮,用绝对定位,然后把四个方位设为0就可以了:
button.big-button::before { /*按钮第二层*/
position: absolute;
content: '';
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--colorShadeC);
border-radius: inherit;
}
别管它遮住第一层的按钮,先把第三层按钮实现。第三层可以看作为第二层的阴影,可以用box-shadow来实现,当然也可以用另外的伪元素after
来实现,但要写好多行css。
button.big-button::before { /*按钮第二层*/
...
box-shadow: 0 0 0 2px var(--colorShadeB), 0 0.75em 0 0 var(--colorShadeA);
/*第一个shadow是用来为第二层加阴影,增加立体感,第二个shadow是按钮第三层*/
}
box-shadow是实现立体按钮的关键,它可以为元素添加多个阴影,是不少炫酷特效的关键属性。第一个box-shadow
给第二层边框性质的阴影,第二个box-shadow
则是添加按钮的底层:
差不多把按钮的样式实现了,现在只需要把第二,三层置于第一层背面,偏下位置就可以了。偏下可以用translate
来解决,居于背面第一时间想到的是用z-index
来解决,但在这场景下是不行的,主要原因是当我们用translate
时,我们创造新的层级上下文(stacking context),不再是我们设定z-index时的上下文了,这里不详细谈讨z-index
和translate
之间的问题,详情可参考z-index和transform,你真的了解吗?,那如果要控制z-index
怎么办?可以用translate3d
,通过控制它的第三个参数,就可以控制z轴的变化。控制z轴的变化,还要在相关元素添加transform-style: preserve-3d;
,这样元素及其子元素才有3d效果。
button.big-button {
...
transform-style: preserve-3d;
}
button.big-button::before {
...
transform: translate3d(0, 0.75em, -1em);
}
效果如下:
悬浮效果
接下来把动态效果实现,首先是鼠标悬浮在按钮时的效果。仔细观察,鼠标悬浮在按钮时出现两个变化,一是按钮的颜色改变,二是按钮下沉:
button.big-button {
...
transition: all 175ms linear;
}
button.big-button:hover {
background: var(--colorShadeD);
transform: translate(0, 0.375em);
}
button.big-button:hover::before {
transform: translate3d(0, 0.75em, -1em);
}
激活效果
最后把按下时的效果实现就完成,只需要把第一层调下点,第二和三层收缩就可以了:
button.big-button:active {
transform: translate(0em, 0.75em);
}
button.big-button:active::before {
transform: translate3d(0, 0, -1em);
box-shadow: 0 0 0 2px var(--colorShadeB), 0 0.25em 0 0 var(--colorShadeB);
}
总结
其实3d按钮不是很难实现,难点是要灵活运用translate3d
来实现3d按钮的样式,实现后后面的动态效果也就自然知道怎样实现了。