BERG 云按钮

Avatar of Chris Coyier
Chris Coyier on

DigitalOcean 为您的旅程每个阶段提供云产品。立即开始使用 $200 免费试用额度!

BERG 云 上的按钮看起来很漂亮。这不是什么大不了的事,但它们创建它们的方式使用了两个单独的图像(而不是精灵图)和两个内部跨度。在本教程中,我们将使用一些现代技巧来重新创建它们。我们不会使用任何图像(更高效),更少的标记(更语义化),并且功能更平滑(没有 JavaScript 控制状态)。

以下是我们要尝试重新创建的原始按钮

orig-buttons

以及我们的最终结果 在 CodePen 上

简单的标记

链接就是链接。

<a href="#" class="button blue">
  Find Out<br>More
</a>

在我们的例子中,除了 “button” 之外,我们还有 “blue” 类。这种简单的事情值得讨论。首先,在 “现实世界” 中,我只需使用 “button” 类就可以完全正常运行。它将是网站上最常见的按钮样式。然后为了处理变化,过去我添加了额外的类,就像上面显示的那样。第二个类将处理覆盖。我可能会像这样写它们

.button.blue {
   /* overrides */
}

但我开始认为这不太好。该按钮的特殊性是原始按钮的两倍,并且使用了没有独立值的类。最近我看到了几个使用单个类名进行变体的代码库,例如 “button-blue” 是唯一的类名,并且让它完成所有工作。在常规 CSS 中完全可行,但在 Sass 中使用 @extend 会更容易。例如

.button {
   /* Styles for basic button */
}

.button-blue {
   @extend .button;
   /* overrides */
}

超级干净的创作,不臃肿的输出,以及与任何其他按钮具有相同 特殊性 的单个类名。我同意这一点。

神圣的 box-shadow!

这里发生的主要事情是在内联块链接上层叠了 box-shadow。如果创建了一个在两个方向上偏移 1px、模糊为零的阴影,则可以本质上在方框的两个边缘创建 1px 边框。如果再次使用相同的偏移方向但偏移 2px,则会开始形成一条斜线并为方框赋予一些伪深度。如果这样做六次,您将获得一个看起来相当厚实的按钮。

现在,如果您将它加倍并交替颜色(左侧偏移获得一种色调,底部偏移获得另一种色调),则可以模拟一些灯光。

.button {
    box-shadow:
      /* Left Side */      /* Right Side */
      -1px 0px 1px #6fadcb, 0px 1px 1px #54809d,
      -2px 1px 1px #6fadcb, -1px 2px 1px #54809d,
      -3px 2px 1px #6fadcb, -2px 3px 1px #54809d;
      /* etc */
}

使用相同的技术,但反转方向并从边缘停止的地方开始,您可以使用非常柔和的透明黑色来创建真实外观的阴影。在上面添加一个带柔和透明白色的内阴影,它会加强光线照射到按钮的错觉。

.button {
  box-shadow:
    
    /* Sides */
    -1px 0px 1px #6fadcb, 0px 1px 1px #54809d,
    -2px 1px 1px #6fadcb, -1px 2px 1px #54809d,
    -3px 2px 1px #6fadcb, -2px 3px 1px #54809d,
    /* etc */

    /* Shadow */
    -6px 7px  0 rgba(0, 0, 0, 0.05),
    -5px 8px  0 rgba(0, 0, 0, 0.05),
    -3px 9px  0 rgba(0, 0, 0, 0.04),
    /* etc */
  
    /* Light & Top Edge */
    inset 0 4px 5px -2px rgba(255, 255, 255, 0.5),
    inset 0 1px 0 0 rgba(0, 0, 0, 0.3);

}

我相信大家都可以想象 Sass 以巧妙的方式帮助完成这项工作。计算色调、循环、颜色变量、更紧凑的语法等等。

更多 CSS!

按钮的正面是一个非常微妙的渐变(再次有助于照明)。没问题。最好将渐变应用于按钮的基本类,然后覆盖它以进行变化。

.button {
  /* ...shadows ... */

 background: linear-gradient(#a2d3e9, #7abedf);
}

按钮内的文本带有一点阴影。用 text-shadow 很容易。只要确保阴影与背景相符。我们制作了两个按钮变体,本质上我们需要覆盖黄色变体上的所有颜色,因为它是在深色背景上的浅色,而不是在浅色背景上的深色。

.button {
  /* ...shadows ... */
  /* ...background ... */

 text-shadow: -2px 2px 0 rgba(0, 0, 0, 0.2);
}

当然,这些按钮上还有很多其他 CSS 属性,就像您所期望的那样。例如,关闭下划线、文本颜色、设置间距以及其他显而易见的事情。

交互

在原始按钮中,当您点击或点击按钮时,JavaScript 会应用 “active” 类,这会触发 “按下” 动画。这有点笨拙,因为按钮可能会卡在这种状态。尝试点击按钮,然后将鼠标移开并松开。按钮保持按下状态。如果它们执行了诸如在鼠标移开时删除 active 类之类的操作,则可以解决这个问题,但是,我们不必担心这个问题,因为我们可以在 :active 上触发按下状态,在 :active 中,我们会自动获得所有交互详细信息。

我们的交互将是相同的按下动画,其中

  1. 删除所有 box-shadow,使按钮看起来平坦
  2. 按钮被移动到看起来像表面的位置

非常简单。

.button {

  /* ... styling stuff ... */

  /* interaction */
  transition: all 0.1s linear;
  transform: translateZ(0);
}
.button:active {
  box-shadow: none;
  transform: translate3d(-6px, 6px, 0);
}

过渡完成了大部分工作。应用后,box-shadow 会慢慢消失,而不是立即消失。在此过程中,我们将移动按钮。我们可以对按钮进行相对定位,并使用 top/left 值将其推动。这样做的问题在于

  1. 它混淆了定位和交互问题。如果按钮被绝对定位,它很快就会变得很奇怪。没有 top: where-its-at-plus-10;
  2. 它的性能不如使用 translate 移动好。

要注意的第二件事是使用 3D 变换。我们正在使用 3D 变换属性,但实际上没有进行任何 3D 变换。我们这样做是因为

  1. 它会启动 GPU 并获得更平滑的性能。
  2. 它会使按钮的 *默认状态* 中的文本变得模糊(变细),因此当过渡开始时不会感到意外。

WebKit 有一个很糟糕的(我认为是 bug)问题,即被转换/过渡的文本看起来很细而且很糟糕。我之前尝试过 不令人满意地 解决这个问题。我的朋友 Koop 曾经很好地总结了这个问题,他说 “你只需要决定哪种更糟糕”。选项 A) 让文本一直模糊,这样就不会出现尴尬的屏幕闪烁和文本重量的变化。选项 B) 忽略它。默认情况下文本看起来很好,但当按钮处于过渡状态或被转换时,会出现闪烁和变细。

在这些按钮上,它相当引人注目。

thick
没有变换(厚实,正常)
thin
有变换(薄)

在这种罕见的情况下,我更喜欢变细的版本,因此两全其美。

箭头

在我第一次尝试创建这些按钮时,我用两个跨度创建了箭头。它运行良好,但与原始版本相比,语义改进并不大。Neil Kinnish 复制了我的 Pen 并使用伪元素创建了箭头,这意味着我们又回到了只使用快乐的锚链接。我后来用他的代码更新了我的 Pen。你会认为我的脑海里会直接想到伪元素,因为我以前专门做过关于它们的演讲,而且我 长期以来一直吹嘘 它们的出色之处。我知道在 WebKit 中你仍然不能转换伪元素,但我认为你也不能转换它们。要么我一直错了,要么这是一个比较新的功能。

诀窍是使用两个免费元素来创建一个小的黑色矩形,并将其绝对定位在按钮的右侧(由于 padding,那里总会有空间)。一个小黑矩形旋转 45 度(通过 transform),另一个旋转 -45 度。当它们嵌套在跨度中时,设置 filter: drop-shadow() 最有意义(只应用于顶部跨度),但现在使用伪元素,box-shadow 在两者上都工作得一样好。

.button:after, .button:before
    position: absolute;
    content: "";
    right: 15px;
    top: 14px;
    width: 6px;
    height: 18px;
    background: white;
    transform: rotate(-45deg);
    display: block;
    z-index: 2;
}
.button:before {
    height: 14px;
    top: 26px;
    right: 16px;
    z-index: 3; /* on top */
    transform: rotate(-137deg); /* hey, it works */
    filter: drop-shadow(0 -2px 0 rgba(0, 0, 0, 0.15)); 
}
.button:After {
   filter: drop-shadow(-2px 0 0 rgba((0, 0, 0, 0.2)); 
} 

同样,您需要调整所有颜色以适应不同的按钮变体。但定位将相同。

完成

以下是最终结果 在 CodePen 上

另外:OMG 微型打印机太可爱了 #想要。