首页 > 解决方案 > 如何在保留默认样式行为的同时覆盖 HTML5 输入验证的默认浏览器样式?

问题描述

我正在为我的 Web 应用程序创建一个地址表单,并且无法确定使用该required属性进行 HTML5 表单验证的样式规则。下面描述的示例和行为使用的是 Firefox。

表单的第一个输入字段的 HTML 如下所示:

<label for="addressLine1" class="form__label">
        Address Line 1
</label>
<input type="text" required aria-required="true" class="form__input-text" id="addressLine1"/>

如果没有任何自定义样式,输入的行为如下:

  1. 页面加载时,输入字段显示文本输入的默认样式

在此处输入图像描述

  1. 如果我尝试在所需输入为空白的情况下提交表单,浏览器会在输入中添加红色边框(或阴影?)

在此处输入图像描述

我想保留这种行为,其中输入在加载时显示一些默认样式,并且仅在用户尝试提交任何必填字段为空白(或无效)的表单时才显示“无效”样式。但是我无法找到一个直接的答案,即我需要修改哪些属性/伪类来更改样式,同时保留这种行为。如果我使用:invalid伪类,我会得到这种行为:

  1. 加载时,输入已经具有我的“无效”样式,因为该字段为空白

在此处输入图像描述

  1. 如果我尝试在字段空白的情况下提交表单,浏览器会在我的“无效”样式顶部添加红色边框/阴影

在此处输入图像描述

  1. 我只能通过在输入中输入有效数据来显示我的默认/有效样式

在此处输入图像描述

您如何使用自定义样式保留默认行为(加载时的默认样式,无效提交时的无效样式),可以仅使用 CSS 完成还是必须添加一些 JS 功能?

标签: htmlcssvalidation

解决方案


好吧,在阅读了 MDN 上的 CSS 伪类文档之后,看起来没有任何伪类组合可以串在一起来模拟使这种行为正常工作的各种状态。因此,在玩了一会儿并查看了 Alex Schaeffer 建议的 Bootstrap 验证链接,但决定我不想添加我并不真正需要的额外依赖项/样式表之后,这是我想出的解决方案,它添加了最少的额外 CSS和 JavaScript。

首先,红色边框确实是一个盒子阴影,所以我可以通过将它添加到我的 (S)CSS 中来覆盖它:

.form__input-text {
    /* default input styling goes here */
    box-shadow: none;
}

接下来,我向我的组件添加了一些状态,以跟踪表单是否已经过验证。我正在使用 Svelte,所以这就像在组件的<script>标签内添加一个布尔变量一样简单,如下所示:

let wasValidated = false;

然后我在我的 HTML/JSX 中添加了一个条件类。如果您使用的是另一个框架或 jQuery/vanilla JS,您可能需要使用连接到事件处理程序的函数显式执行此操作,但在 Svelte 中,我只需将我的标记更改为:

<label for="addressLine1" class="form__label">
        Address Line 1
</label>
<input 
    type="text" 
    required aria-required="true" 
    class="form__input-text"
    class:wasValidated="{wasValidated}"
    id="addressLine1"
/>

如果/当变量为真时,所有这些class:wasValidated="{wasValidated}"都是有条件.wasValidated地向该输入元素添加一个类。wasValidated

然后,回到我的 (S)CSS 中,我添加了以下内容以应用我的“无效”样式(此时它只是将边框颜色更改为红色阴影),仅当表单至少经过一次验证时,并且仅适用于无效元素:

input.wasValidated:invalid {
    border-color: $red;        
}

然后我将一个简单的onClick函数连接到提交按钮,该按钮将wasValidated变量更改true为单击按钮时:

HTML/JSX

<button on:click|preventDefault={onClick} class="form__submit-button" type="submit">
    Search
</button>

JS

const onClick = e => {
    wasValidated = true;
};

该函数需要连接到单击事件而不是提交事件,因为如果表单验证失败,则永远不会触发提交事件。

所以现在,当页面首次加载时,所有表单输入都显示默认样式,无论有效性如何,因为wasValidated设置为false. 然后,当单击提交按钮wasValidated切换到true时,.wasValidated该类将应用于任何必需的元素,如果它们无效,则显示“无效”样式。否则,如果表单提交成功,onSubmit连接到表单的函数会从那里处理事情。

编辑:事实证明,在 Svelte 中,您可以在事件第一次触发后取消绑定事件处理程序。所以我对提交按钮的标记现在看起来像这样:

<button on:click|preventDefault|once={onClick} class="form__submit-button" type="submit">
    Search
</button>

添加|once修饰符以在第一次单击按钮时on:click取消绑定该onClick功能,因此如果用户尝试多次提交无效数据,该功能不会不必要地继续触发。


推荐阅读