Dummy CSS - 3d按鈕

888 阅读3分钟

上次小试牛刀后,这次看一个比较难的,纯css做一个有3d效果的按钮:

3d button

codepen示例

先把按钮的外表做出来,添加三个按钮:

<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);
}

效果如下:

firstbutton.png

现在只有一层,还有两层,可以用伪元素来实现第二层,做一个一样大小但背景色不同的按钮,用绝对定位,然后把四个方位设为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;
}

secondbutton.png

别管它遮住第一层的按钮,先把第三层按钮实现。第三层可以看作为第二层的阴影,可以用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则是添加按钮的底层:

thirdbutton.png

codepen示例

差不多把按钮的样式实现了,现在只需要把第二,三层置于第一层背面,偏下位置就可以了。偏下可以用translate来解决,居于背面第一时间想到的是用z-index来解决,但在这场景下是不行的,主要原因是当我们用translate时,我们创造新的层级上下文(stacking context),不再是我们设定z-index时的上下文了,这里不详细谈讨z-indextranslate之间的问题,详情可参考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);
}

效果如下:

staticbutton.png

codepen示例

悬浮效果

接下来把动态效果实现,首先是鼠标悬浮在按钮时的效果。仔细观察,鼠标悬浮在按钮时出现两个变化,一是按钮的颜色改变,二是按钮下沉:

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);
}

hoverbutton.png

codepen示例

激活效果

最后把按下时的效果实现就完成,只需要把第一层调下点,第二和三层收缩就可以了:

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);
}

activebutton.png

codepen示例

总结

其实3d按钮不是很难实现,难点是要灵活运用translate3d来实现3d按钮的样式,实现后后面的动态效果也就自然知道怎样实现了。