CSS Tips:用于按钮上的小技巧

URL:ui-buttons.web.app/

可以说,在 Web 应用或网站上,按钮无处不在。它们是 Web 页面和应用界面中最常见的元素之一,用于触发各种操作和交互。然而,在 CSS 中,我们可以通过各种技巧来改变按钮的外观和行为,使其更加灵活和易用。或许你会说,使用 CSS 给按钮设置样式,从而美化按钮的视觉效果,这是一件非常简单的事情。

真的是这样?如果你的答案不是百分百的肯定,那就对了。你也可以接着往下阅读。我将在接下来的内容中会和大家分享一些关于按钮的技巧(一些不太常见的 CSS),帮助你更好地掌握 CSS,并在设计中展现出更多的创意和可能性。

先从 HTML 开始

如果语义化的角度来说,为 Web 提供按钮,就应该使用 HTML 的 <button> 元素。然而,很多 Web 开发者并不太关注 HTML 语义化这个事情。因此,在 Web 应用或页面上,你可以看到千奇百怪的 HTML 元素用于制作按钮,比如:

HTML 复制代码
<button>我是一个真按钮</button>

<input type="button" value="我也是一个按钮" />

<a href="">我是一个链接,我也被当作按钮使用</a>

<span>其实就只是一个HTML标签,我与按钮没半毛钱关系</span>

当然,上面的示例,仅仅是冰山一角,还有很多其他的 HTML 标签用于制作按钮,比如 divsection 等等。

如果你在开发的过程中,也习惯性的使用非 <button> 元素来构建按钮的话,那么请你考虑 A11Y 相关的细节。例如,给元素添加 roletabindex 以及相关的 ARIA 等属性:

HTML 复制代码
<div id="save" tabindex="0" role="button" aria-pressed="false">save</div>

这样,你可以为更多的人提供平等的服务。

众所周知,按钮是一种小部件,用于执行操作,例如提交表单、打开对话框、取消操作或执行命令,如插入新记录或显示信息。添加添加 role="button" 告诉辅助技术(例如屏幕阅读器)该元素(div)是按钮,但不提供按钮功能(通常会使用 JavaScript 来模拟按钮的功能)。这意味着,如果你希望按钮是真的按钮,请使用原生的按钮标签,即 <button>typebutton<input>

HTML 复制代码
<button>我是一个真按钮</button>
<input type="button" value="我也是一个按钮" />

注意,如果使用 role="button" 而不是语义化的 <button><input type="button"> ,你需要让这个元素可聚焦并定义 clickkeydown 事件的事件处理器。简而言之,你要额外做的事情会很多,个人不建议使用非 <button> 标签元素来构建按钮。

在 Web 上,还有另一个争议,那就是就 Web 上的很多链接,它的 UI 外观看上去很像一个按钮,因此有了个"是按钮,还是链接?"的讨论,要是你想更深入的了解这方面的话题,请移步阅读 @Chris Coyier 的《A Complete Guide to Links and Buttons》一文,这里就不再做相关的阐述!

基于可访问性的原因,我们使用 button 来制作按钮:

HTML 复制代码
<button type="submit" class="button">Submit</button>

重置按钮默认样式

如果使用按钮控件来制作按钮,例如 <button><input type="button"> ,用户代理都会为它们设置一个初始化的样式。以 Chrome 浏览器为例:

CSS 复制代码
/* User Agent Stylesheet */
button {
    appearance: auto;
    font-style: ;
    font-variant-ligatures: ;
    font-variant-caps: ;
    font-variant-numeric: ;
    font-variant-east-asian: ;
    font-variant-alternates: ;
    font-variant-position: ;
    font-weight: ;
    font-stretch: ;
    font-size: ;
    font-family: ;
    font-optical-sizing: ;
    font-size-adjust: ;
    font-kerning: ;
    font-feature-settings: ;
    font-variation-settings: ;
    text-rendering: auto;
    color: buttontext;
    letter-spacing: normal;
    word-spacing: normal;
    line-height: normal;
    text-transform: none;
    text-indent: 0px;
    text-shadow: none;
    display: inline-block;
    text-align: center;
    align-items: flex-start;()
    cursor: default;
    box-sizing: border-box;
    background-color: buttonface;
    margin: 0em;
    padding-block: 1px;
    padding-inline: 6px;
    border-width: 2px;
    border-style: outset;
    border-color: buttonborder;
    border-image: initial;
}

/* User Agent Stylesheet */

input {
    font-style: ;
    font-variant-ligatures: ;
    font-variant-caps: ;
    font-variant-numeric: ;
    font-variant-east-asian: ;
    font-variant-alternates: ;
    font-variant-position: ;
    font-weight: ;
    font-stretch: ;
    font-size: ;
    font-family: ;
    font-optical-sizing: ;
    font-size-adjust: ;
    font-kerning: ;
    font-feature-settings: ;
    font-variation-settings: ;
    text-rendering: auto;
    color: fieldtext;
    letter-spacing: normal;
    word-spacing: normal;
    line-height: normal;
    text-transform: none;
    text-indent: 0px;
    text-shadow: none;
    display: inline-block;
    text-align: start;
    appearance: auto;
    -webkit-rtl-ordering: logical;
    cursor: text;
    background-color: field;
    margin: 0em;
    padding: 1px 0px;
    border-width: 2px;
    border-style: inset;
    border-color: -internal-light-dark(rgb(118, 118, 118), rgb(133, 133, 133));
    border-image: initial;
    padding-block: 1px;
    padding-inline: 2px;
}

input[type="button" i] {
    appearance: auto;
    user-select: none;
    align-items: flex-start;()
    text-align: center;
    cursor: default;
    box-sizing: border-box;
    background-color: buttonface;
    color: buttontext;
    white-space: pre;
    padding-block: 1px;
    padding-inline: 6px;
    border-width: 2px;
    border-style: outset;
    border-color: buttonborder;
    border-image: initial;
}

对应的按钮样式风格如下:

为了便于自定义按钮的 UI 样式,通常会给按钮设置 appearance 属性的值为 none

CSS 复制代码
.button {
    appearance: none;
}

这样做的最大好处是,它可以基于用户操作系统为按钮提供初始化 UI 样式,这个时候,你在不同的操作系统,不同的平台,看到的按钮风格是有所差异的:

上图是基于 OS 系统在不同浏览器下,按钮设置了 apperance:none 的 UI 效果!

如果你希望彻底从头开始给按钮定义样式,又担心自己遗漏覆盖默认样式,那么可以采用一种简单且粗暴的方式,将按钮的 all 属性设置为 unset

CSS 复制代码
.button {
    all: unset;
}

如此一来,按钮将不会带有任何 UI 效果:

CSS 的 unsetinheritinitialrevert 统称为 CSS 显式默认值,它可以很容易让你获得重置和继续属性默认值的方式:

如果你对这方面的知识感兴趣的话,个人建议你移步阅读《现代 CSS》中的《CSS 显式默认值:inhert 、initial 、unset 和 revert 》一文!

触摸操作

你是否曾经反复点击按钮,结果页面意外地放大了?如果你希望避免这种现象出现,可以通过 touch-action 来移除:

CSS 复制代码
.button {
    touch-action: manipulation;
}

manipulation 值禁用了诸如"双击放大"的手势。其他手势,如"平移"和"捏合放大",不受影响。额外的好处是浏览器不再需要等待第二次点击来延迟点击事件。

有人建议将 metaviewport 中的 user-scalable 设置为 none

HTML 复制代码
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

需要注意的是,使用 user-scalable=no 可能会给视力受损(如低视力)的用户带来无法访问的问题。WCAG 要求至少 2 倍的缩放;然而,最佳实践是启用 5 倍缩放。因此应该谨慎使用。

悬停和可视焦点

给按钮提供悬停和焦点样式,对于按钮来说是非常重要的。这里特意要提出来的是,同时给按钮添加悬停和焦点样式时,它们的顺序非常重要。

当悬停样式在焦点样式之前添加时,每种样式都能正常工作。然而,问题出现在当焦点样式在悬停样式之前放置时。当使用鼠标点击元素时,焦点样式将不会出现,只有悬停样式会显示。

以下是正确的顺序:

CSS 复制代码
.button {
    /* Default Style */
    
    &:hover {
        /* Hover Style*/
    }
    
    &:focus {
        /* Focus Style */
    }
}

按钮焦点样式还有一个细节。与按钮交互时,获得焦点环不只是通过鼠标与其交互可获得,还可以通过键盘与其交互也可以获得。因此,请不要遗漏给键盘交互获得的焦点环设置样式。

在 CSS 中,可以通过下面这种方式给 :focus (鼠标交互)和 :focus-visible (键盘交互)设置不一样的样式:

CSS 复制代码
button:focus:not(:focus-visible) { 
    outline: 2px dotted #416dea; 
    outline-offset: 2px; 
    box-shadow: 0px 1px 1px #416dea; 
} 

button:focus-visible { 
    outline: 2px solid #f35; 
    outline-offset: 2px; 
    box-shadow: 0px 1px 1px #416dea; 
} 

CSS 中除了 :focus:focus-visible 之外,还有一个 :focus-within ,它们都可以用于设置焦点环样式,但它们之间有着明显的差异。有关于这方面更详细的介绍,可以称步阅读《CSS 焦点样式: :focus 和 :focus-visible》一文!

按钮的最小宽度

为了确保按钮具有适当的宽度,重要的是提前考虑到按钮内容的长短,并为其设置最小宽度。通过使用 min-width 属性,可以帮助你确定按钮的最小宽度。

考虑下面的示例,其中有一些按钮具有不同长度的内容,包括英文和阿拉伯文。如果文本较短,没有设置最小宽度,按钮的宽度可能会变得太小。通过使用 min-width,可以避免这种情况。

CSS 复制代码
.button {
    min-width: 104px;
}

有关于这方面更多的介绍,可以移步阅读:

按钮的字体

默认情况下,表单元素不会继承 <html><body> 元素的 font-family 。如果你希望按钮的字体继承它们的 font-family ,最简单的解决方案是重置按钮的 font-family 属性的值为 inherit

CSS 复制代码
.button {
    font-family: inherit;
}

按钮禁用状态

为了指示按钮被禁用,我们可以给它添加 disabled 属性,然后用 CSS 样式进行样式化。

HTML 复制代码
<button disabled></button>
CSS 复制代码
button[disabled] {
    color: #d2d5db;
    background: #6c7589;
    cursor: not-allowed;
}

当按钮被禁用时,无法通过键盘聚焦到它,并且它会从可访问性树中移除。

意外选择

很多 Web 应用或网站上会将链接 <a> 的外观设置的看上去像一个按钮。通常会使用一个共享的类,例如 .button.btn

HTML 复制代码
<a class="button" href="/sign-in">Sign in</a>

此时,反复点击它,可能会被选中或高亮显示,为了避免这种现象,可以将 user-select 设置为 none

CSS 复制代码
.button {
    user-select: none;
}

小结

按钮样式的设计对于 Web 的外观和用户体验至关重要。通过一些小技巧,可以使按钮看起来更加吸引人、易于理解和操作。以下是对按钮样式小技巧的简要总结:

首先,悬停和焦点样式是为了增强按钮的交互性。通过使用 :hover:focus:focus-visible 伪类,我们可以为按钮添加悬停和焦点时的样式效果,从而提高用户对按钮的注意力,并且在键盘导航时也能保持可见性。

其次,按钮的最小宽度是确保按钮在不同文本长度下保持一致的外观。通过使用 min-width 属性,我们可以为按钮设定一个最小宽度,这样即使按钮文本内容较短,按钮也不会显得过于拥挤或不规整。

第三,字体系列的设置可以让按钮文本与网页的整体风格保持一致。通过将 font-family 属性设置为inherit,按钮文本将继承网页中定义的字体样式,从而确保按钮在外观上与网页内容一致。

最后,禁用状态样式可以为用户提供视觉提示,告知他们按钮当前处于禁用状态。通过为 [disabled] 属性选择器定义样式,我们可以改变禁用状态按钮的颜色、背景和鼠标指针样式,使用户能够清楚地识别禁用按钮并且避免误操作。

综上所述,通过应用这些按钮样式小技巧,我们可以创建出更具吸引力、易用性和可访问性的按钮,从而提升用户体验并增强网页的整体品质。


如果你觉得该教程对你有所帮助,请给我点个赞。要是你喜欢 CSS ,或者想进一步了解和掌握 CSS 相关的知识,请关注我的专栏,或者移步阅读下面这些系列教程:

相关推荐
Leyla几秒前
【代码重构】好的重构与坏的重构
前端
影子落人间3 分钟前
已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed
前端·npm·node.js
世俗ˊ28 分钟前
CSS入门笔记
前端·css·笔记
子非鱼92128 分钟前
【前端】ES6:Set与Map
前端·javascript·es6
6230_33 分钟前
git使用“保姆级”教程1——简介及配置项设置
前端·git·学习·html·web3·学习方法·改行学it
想退休的搬砖人42 分钟前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
加勒比海涛1 小时前
HTML 揭秘:HTML 编码快速入门
前端·html
啥子花道1 小时前
Vue3.4 中 v-model 双向数据绑定新玩法详解
前端·javascript·vue.js
麒麟而非淇淋1 小时前
AJAX 入门 day3
前端·javascript·ajax
茶茶只知道学习1 小时前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css