按钮

2025-05-27

按钮

演示在这里。源代码在这里

使用<button>

请不要将其用作<a>按钮。它们的含义和行为不同。链接响应Enter键(将触发 onClick 操作),<button>响应Space。如果用户将焦点放在 上<a>,其样式为按钮,并使用Space页面滚动而不是操作。<a>用于导航,用户可以Ctrl/Cmd点击它,在新标签页中打开。<a>在 Firefox 中无法获得焦点。我想说的是<a><button>和 的行为和语义有很大差异。

<button type="button">
  <span role="img" aria-label="unicorn">
    🦄
  </span>{" "}
  Button
</button>

你应该可以<button>在任何地方使用,但如果你想要其他东西,你<div role="button" tabindex=0>也可以使用。<input type="button" />如果你想要一些老派的东西,这里有。

如果使用role="button"语义<button><input type="button">元素,则需要使元素可聚焦,并且必须定义 click 和 keydown 事件(包括EnterSpace键)的事件处理程序,以便处理用户的输入。参阅官方 WAI-ARIA 示例代码。——
MDN

重置样式

<button>带有预定义样式,但如果我们想自定义它,我们可以从重置样式开始

/* reset button styles https://css-tricks.com/overriding-default-button-styles/ */
button {
  border: none;
  padding: 0;
  margin: 0;
  /* not needed in modern browsers */
  -webkit-appearance: none;
  -moz-appearance: none;
}

初始样式

让我们的按钮看起来像一个按钮

<button type="button" className="button">
/* inspired by https://codepen.io/liamj/pen/vvdRdR */
.button {
  --color-dark: #333;
  --color-light: #fff;
  display: block;
  position: relative;
  font-size: 2rem;
  padding: 1rem 2rem;
  border-radius: 0.4rem;
  background: var(--color-light);
  color: var(--color-dark);
  border: 0.2rem solid var(--color-dark);
  box-shadow: 0 0.2rem 0 0 var(--color-dark);
}

活动状态

按钮应该提供活动状态,以便用户知道按钮对点击做出响应。

.button:active {
  top: 0.2rem;
  box-shadow: none;
}

禁用状态

该按钮应提供禁用状态,以便用户知道该按钮不可点击。

<button type="button" className="button" disabled>
.button:disabled {
  --color-dark: #999;
  cursor: not-allowed;
}

快到了,但是表情符号没有改变颜色。

.button:disabled {
  --color-dark: #999;
  cursor: not-allowed;
  /* see https://www.bram.us/2016/10/06/emoji-silhouettes-and-emoji-outlines-with-css/ */
  color: transparent;
  text-shadow: 0 0 0 var(--color-dark);
}

与其他浏览器不同,Firefox 默认会在<button>页面加载过程中保持动态禁用状态。将 autocomplete 属性的值设置为 off 即可禁用此功能。请参阅错误654072。——
MDN关于按钮

焦点状态

按钮应该提供焦点状态,以便用户知道焦点在哪里。否则,用户需要猜测或点击 Tab 键来选择最近的焦点元素。浏览器提供了一个开箱即用的焦点状态:

铬合金:

火狐浏览器:

Safari:

在 Safari 中,按钮不可点击🤦

自定义焦点状态

让我们删除默认焦点状态:

/* https://fvsch.com/styling-buttons/ */
.button:focus {
  outline: none;
}
.button::-moz-focus-inner {
  border: none;
}

不要删除轮廓,除非你提供替代方案

让我们添加自定义轮廓:

.button:focus {
  outline: none;
  box-shadow: 0 0.2rem 0 0 var(--color-dark), 0 2px 5px 3px #f0f;
}

焦点状态 + 活动

因为我们box-shadow同时使用它们:active并且:focus它们可能会发生冲突,所以我们需要注意特殊情况:

.button:active:focus {
  top: 0.2rem;
  box-shadow: 0 0px 6px 4px #f0f;
}

仅限键盘用户的焦点状态

鼠标用户无需显示焦点,它仅对键盘用户有用。因此,有人提议添加:focus-visible状态来实现这一点。同时,我们可以使用 polyfill 或自行实现此功能。

import "focus-visible";
.js-focus-visible :focus:not(.focus-visible) {
  box-shadow: 0 0.2rem 0 0 var(--color-dark);
}
.js-focus-visible :active:not(.focus-visible) {
  top: 0.2rem;
  box-shadow: none;
}

触摸屏

触摸屏对按钮也有特殊要求

最小尺寸

根据许多资料(1、2、3 触摸设备上的按钮尺寸应约为 1 厘米。

button {
  min-width: 1cm;
  min-height: 1cm;
}

相邻按钮周围也应留有足够的空间,以防止错误点击按钮。

触摸屏的活动状态

当用户点击触摸设备上的按钮时,手指会遮住按钮,因此无法看到按钮的活动状态。因此,他们需要一个特殊的活动状态,使其在手指移开后仍然可见。例如,Material Design 就使用了波纹效果来实现这一点。

button {
  user-select: none;
  /* we need to remove the built-in effect */
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

让我们创建自己的点击后效果

/* https://css-tricks.com/touch-devices-not-judged-size/ */
@media (hover: none) {
  /* inspired by https://codepen.io/numerical/pen/XJKeop */
  .button ::after {
    content: "";
    display: block;
    height: 100px;
    position: absolute;
    transform: translate3d(-150%, -50px, 0) rotate3d(0, 0, 1, 45deg);
    width: 200px;
  }

  .button.active ::after {
    background-image: linear-gradient(
      to top,
      rgba(255, 0, 255, 0.1),
      rgba(255, 0, 255, 0.9)
    );
    transition: all 2.2s cubic-bezier(0.19, 1, 0.22, 1);
    transform: translate3d(120%, -100px, 0) rotate3d(0, 0, 1, 90deg);
  }
}

用一点 JS 来实现鼠标移开后切换类

const Button = ({ children }) => {
  const [activated, setActivated] = React.useState(false);
  return (
    <button
      className={"button" + (activated ? " active" : "")}
      onMouseDown={() => setActivated(false)}
      onMouseUp={() => setActivated(true)}
    >
      {children}
    </button>
  );
};

聚苯乙烯

我是用 React 做的,但用纯 HTML 和 CSS 也可以实现。希望你主要关注的是按钮的用户体验,而不是代码本身。

文章来源:https://dev.to/stereobooster/the-button-3kme
PREV
TypeScript:类型与接口
NEXT
SSR 服务器端渲染的优缺点是什么?何时使用它,何时选择其他?