通过选中单选按钮显示其他表单字段

Avatar of Chris Coyier
Chris Coyier

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

CSS 中有一个 :checked 伪类。我经常将其与 “复选框技巧” 联系起来,在这种技巧中,您将其用于带有 ~ 通用同级组合器的隐藏复选框,以模拟切换行为,而无需任何 JavaScript。这是一种技巧,因为现在您在页面上有了这些无关的表单元素,这些元素实际上并不属于表单。这不是什么大问题,我相信您可以通过辅助功能解决它,但有一种方法可以在实际表单上以完全非技巧的方式使用相同的概念!

我在 CodePen 招聘表单 上使用了这种技术,仅在需要时显示其他表单字段。

让我们用一个演示来切入正题

查看 Chris Coyier 在 CodePen 上创作的笔 LEGXOK。(@chriscoyier

HTML

假设我们在这里使用单选按钮。复选框或单选按钮都可以被“选中”(:checked)。我们要显示的 div 必须在它之后,并且是同级元素(在同一个父元素内)。

<input type="radio" name="choice-animals" id="choice-animals-dogs">
<label for="choice-animals-dogs">I like dogs more</label>
    
<div class="reveal-if-active">
  Anything you want in here.
</div>

CSS

默认情况下,“reveal-if-active” div 将被隐藏。我们将通过多种不同的方式来实现这一点。它们并非全部都是隐藏它的必要条件,但它们将影响它如何显示自身。

.reveal-if-active {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
}

现在,当与其处于同一级别的单选按钮或复选框被选中时,它就会显示出来

input[type="radio"]:checked ~ .reveal-if-active,
input[type="checkbox"]:checked ~ .reveal-if-active {
  opacity: 1;
  max-height: 100px; /* little bit of a magic number :( */
  overflow: visible;
}

这可以工作,但让我们以一种花哨的风格过渡一切,并使用 Sass 来增强它

.reveal-if-active {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transform: scale(0.8);
  transition: 0.5s;
  input[type="radio"]:checked ~ &,
  input[type="checkbox"]:checked ~ & {
    opacity: 1;
    max-height: 100px;
    overflow: visible;
    padding: 10px 20px;
    transform: scale(1);
  }
}

这就可以了。

必填字段怎么办?

这有点棘手。假设在“reveal-if-active” div 中,您放置了更多表单字段(这确实是重点)。如果字段显示,您可能希望将其设为必填,但如果未显示,则无需必填。隐藏的必填字段仍然是必填的,因此您不能只是在这些隐藏字段上添加 required 属性并忽略它,以免陷入糟糕的用户体验境地。

我通过在输入上添加“require-if-active” 类和一个 data-* 属性来处理此问题,该属性引用与其配对的 ID。

... 

<div class="reveal-if-active">
  <label for="which-dog">Good call. What's the name of your favorite dog?</label>
  <input class="require-if-active" type="text" id="which-dog" name="which-dog" data-require-pair="#choice-animals-dogs">
</div>

然后,在页面加载时以及每次复选框或单选按钮的值发生变化时,您都会运行一些 JavaScript 来确定该输入是否应该为必填。

var FormStuff = {
  
  init: function() {
    // kick it off once, in case the radio is already checked when the page loads
    this.applyConditionalRequired();
    this.bindUIActions();
  },
  
  bindUIActions: function() {
    // when a radio or checkbox changes value, click or otherwise
    $("input[type='radio'], input[type='checkbox']").on("change", this.applyConditionalRequired);
  },
  
  applyConditionalRequired: function() {
    // find each input that may be hidden or not
    $(".require-if-active").each(function() {
      var el = $(this);
      // find the pairing radio or checkbox
      if ($(el.data("require-pair")).is(":checked")) {
        // if its checked, the field should be required
        el.prop("required", true);
      } else {
        // otherwise it should not
        el.prop("required", false);
      }
    });
  }

};

FormStuff.init();

是的,需要一点 JavaScript。我们也可以通过 JavaScript 来实现隐藏/显示,但 CSS 非常适合它。您甚至可以说这是一个设计问题,因此它属于 CSS。#辩论

这里再次提供演示

奇怪的问题

Becca Rice 写信告诉我,显示其他字段的 CSS 东西存在一个错误,**尤其是在 iOS 9 及更早版本上的 UI WebView 中。**不是 Safari 本身,而是使用内置 WebView 在其自己的应用中显示网页的应用。即使在撰写本文时,iOS 上的整个 Chrome 应用也使用 UI WebView。

错误是:您可以点击一个单选按钮来展开其他字段。甚至可以点击另一个关闭原始字段并打开一组新的其他字段,但随后它停止工作了。您可以继续切换单选按钮,但不再有任何变化。目前尚不清楚单选按钮是否只是视觉上改变了状态,但实际上没有改变值,或者 CSS 是否没有对新的 :checked 值做出反应。

我们都确认了这一点。有一个 应用 专门用于测试 UI WebView 与 WK WebView。