【问题标题】:How do you override default browser styling for HTML5 input validation while retaining the default styling behavior?如何在保留默认样式行为的同时覆盖 HTML5 输入验证的默认浏览器样式?
【发布时间】:2023-04-07 02:52:01
【问题描述】:

我正在为我的 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 功能?

【问题讨论】:

  • CSS 中可能有 :dirty:changed 之类的东西(我去查一下文档,brb)

标签: html css validation


【解决方案1】:

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

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

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

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

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"
/>

如果/当wasValidated 变量为真时,class: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 函数,因此如果用户尝试多次提交无效数据,该函数不会不必要地继续触发。

【讨论】:

    【解决方案2】:

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

    用很少量的javascript(四行)就可以实现这个效果。

    您的输入显示为invalid 的原因是因为它同时是emptyrequired

    所以一个三步法如下所示:

    第 1 步:使用属性 required 在 HTML 中声明元素

    <input type="text" required>
    

    第 2 步: 然后通过 javascript立即删除该属性

    const addressLine1Input = document.getElementById('addressLine1');
    addressLine1Input.removeAttribute('required');
    

    第 3 步:然后,在 &lt;input&gt; 中输入单个字符后,再次使用 javascript 重新添加 required 属性。

    const setRequired = (e) => e.target.required = 'required';
    addressLine1Input.addEventListener('keyup', setRequired, false);
    

    您可以通过在&lt;input&gt; 中添加一个或多个字符然后将其全部删除来测试所有这些是否正常工作。

    您会看到&lt;input&gt; 最初为空但不显示为invalid,然后包含字符且不显示为invalid,最后又为空,现在确实 显示为invalid

    工作示例:

    const addressLine1Input = document.getElementById('addressLine1');
    addressLine1Input.removeAttribute('required');
    
    const setRequired = (e) => e.target.required = 'required';
    addressLine1Input.addEventListener('keyup', setRequired, false);
    input:invalid {
      background-color: rgba(255, 0, 0, 0.3);
      border: 2px solid rgba(255, 0, 0, 0.5);
    }
    <form>
    <label for="addressLine1" class="form__label">Address Line 1</label>
    <input type="text" name="addressLine1" id="addressLine1" class="form__input-text" placeholder="Enter address here..." aria-required="true" required>
    </form>

    【讨论】:

    • 感谢您的回复。我最终找到了类似的东西(上面发布),我没有删除和读取“required”属性,而是在单击提交按钮时向所需的表单元素添加了一个“.wasValidated”类,并将我所有的“在我的 CSS 中将“无效”样式转换为“.wasValidated:invalid”。
    【解决方案3】:

    我认为纯 CSS 无法做到这一点,你还需要一些 JavaScript

    CSS

    #addressLine1{
        border: none;
        background: none;
        outline: none;
        border-bottom: 1px solid black;
    }
    

    JS

    document.getElementById('form_id').addEventListener('submit',function(e){
        let address = document.getElementById('addressLine1').value
        if(address == ""){
            e.preventDefault()
            address.style.borderBottomColor = "red";
        }else{
            address.style.borderBottomColor = "black";
        }
    })
    

    【讨论】:

      【解决方案4】:

      在所有浏览器中实现统一样式的最简单方法是使用 Bootstrap Validation https://getbootstrap.com/docs/4.0/components/forms/?#validation

      【讨论】:

      • 这个任务可以用纯CSS来完成,不需要把整个库都带进图片
      • 这个建议非常接近“完成它的最简单方法是付钱给别人为你做”:D
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-07
      • 2017-09-06
      • 2010-09-19
      • 1970-01-01
      相关资源
      最近更新 更多