使用Sass美化表单控件

表单控件在网页设计中无疑是占有重要地位的。由于表单控件是用户频繁使用到的页面元素,所以有必要使用 Sass 来快速美化项目中的表单控件。

占位符

占位符,可以用来提示用户当前输入框所需要的信息。只有当 type 类型为 textsearchtelurlemail 时,表单控件的占位符属性才会生效,其他类型下会被自动忽略。不足之处在于,使用占位符需要配合恰当的浏览器伪元素前缀,所以,开发者需要手动为主流浏览器添加前缀,包括 IE,Firefox,Safari,Chrome 和 Opear。

占位符混合宏示例

占位符混合宏可以应用到形形色色的上下文环境中,就可以独立使用,也可以配合其他选择器使用。此外,我还声明了一个 Sass map,用来配置所需的样式。

index.html

<label for=“username”>Name</label>
<input type=“text” name=“username” id=“username”  placeholder=“first, last”>

_placeholder-mixin.scss

在下述的混合宏中,@at-root 指令被用来将嵌套的样式声明到选择器链的最外层。

注意:本文发布时,由于解析插值存在的问题(比如 @at-root #{&}#{$pseudo}),node-sass 尚不能编译占位符选择器。

$pseudo-phprefix: “::-webkit-input-placeholder” “::-moz-placeholder” “:-ms-input-placeholder” “::placeholder”;

$ph-styles: (
  font-family: sans-serif,
  font-size: medium,
  font-style: normal,
  font-weight: normal,
  color: inherit,
  letter-spacing : normal,
  line-height: normal,
  text-align: inherit,
  text-decoration: inherit,
  padding: 0
);

@mixin placeholder-theme($styles) {
  @each $pseudo in $pseudo-phprefix {

    @at-root #{&}#{$pseudo} {
      @each $key, $value in $styles {
        #{$key}: #{$value};
      }
    }

  }
}

@mixin placeholder {
  @each $pseudo in $pseudo-phprefix {

    @at-root #{&}#{$pseudo} {
      @content
    }

  }
}

定义完必须的混合宏之后,我们就可以独立地引用这些混合宏,使其根据参数将所有的占位符渲染为统一的风格。上面的第二个混合宏可以按需配置特定的选择器,同时也无需加载全局的统一样式。

_placeholder-mixin.scss

@include placeholder { color: red; }

input {
  @include placeholder-theme($ph-styles);
}

CSS Output

::-webkit-input-placeholder {
  color: red;
}
::-moz-placeholder {
  color: red;
}
:-ms-input-placeholder {
  color: red;
}
::placeholder {
  color: red;
}
input::-webkit-input-placeholder {
  font-family: sans-serif;
  font-size: medium;
  font-style: normal;
  font-weight: normal;
  color: inherit;
  letter-spacing: normal;
  line-height: normal;
  text-align: inherit;
  text-decoration: inherit;
  padding: 0;
}
input::-moz-placeholder {
  font-family: sans-serif;
  font-size: medium;
  font-style: normal;
  font-weight: normal;
  color: inherit;
  letter-spacing: normal;
  line-height: normal;
  text-align: inherit;
  text-decoration: inherit;
  padding: 0;
}
input:-ms-input-placeholder {
  font-family: sans-serif;
  font-size: medium;
  font-style: normal;
  font-weight: normal;
  color: inherit;
  letter-spacing: normal;
  line-height: normal;
  text-align: inherit;
  text-decoration: inherit;
  padding: 0;
}
input::placeholder {
  font-family: sans-serif;
  font-size: medium;
  font-style: normal;
  font-weight: normal;
  color: inherit;
  letter-spacing: normal;
  line-height: normal;
  text-align: inherit;
  text-decoration: inherit;
  padding: 0;
}

提醒:不要使用占位符属性替代标签元素。这两者之前存在明显的差异:标签元素用来描述表单空间的角色定位,提示当前表单控件的信息类型;占位符属性则是用来提示内容的格式。由于各种原因,占位符属性并不一定会展示给用户,所以必须设想没有占位符属性时的用户体验。

占位符跳跃动效

这动效棒极了!稍有不足的是只能在基于 WebKit/Blink 引擎的浏览器下有效果。由于其首次亮相时吸引众人热论的动效表现,也有人称之为 “Floating Label”。

index.html

<label for=“phone”>Cell Phone</label>
<input type=“tel” name=“phone” class=“jpinput” id=“phone” placeholder=“(555) 555-5555”>

这个特效的魔力来源于来源于伪元素选择器 ::-webkit-input-placeholder[style*=hidden]:一旦用户开始填写信息时,该选择器就可以修改占位符元素的状态。我非常期望找到适用于 Mozilla 的等效选择器,但这个愿望最终落空了。在本段的下方,我引用了 David Bushell 所实现的一种方式,该方式充分利用了伪元素选择器,但也存在一些其他的问题。

_js-input.scss

$jpinput-height: 40px;
$jpinput-radius: 4px;
$jpinput-padding: 10px 16px;
$jpinput-bg: #8DAA91;
$jpinput-color: #4F4137;
$jpinput-ph-color: $jpinput-color;
$jpinput-phide-color: $jpinput-bg;

input {
  appearance: none;
  box-sizing: border-box;
  border-radius: $jpinput-radius;
  display: inline-block;
  outline: 0;
  width: 100%;
}

.jpinput {
  height: $jpinput-height;
  padding: $jpinput-padding;
  transition: transform 225ms ease-in-out;
  background: $jpinput-bg;
  color: $jpinput-color;

  @include placeholder {
    position: relative;
    top: 0;
    left: 0;
    transition: all 300ms ease-in-out;
    color: rgba($jpinput-ph-color, .5);
  }
}

.jpinput::-webkit-input-placeholder[style*=hidden] {
  transform: translateY(-$jpinput-height);
  opacity: 1;
  visibility: visible !important;
  color: $jpinput-phide-color;
}

当然也有其他的方法可以实现这种动效,希望你能深入理解其中的优点和不足。即使不说你也会理解,有一种解决方案叫做 “JavaScript 无所不能系列”。更多参考资料:

Label

HTML 中的 Label 为界面中与之相关联的控件提供了一个标题,常用来提示当前空间所需的信息类型。

安全输入模式

当输入框失去焦点时,我们可以将 Label 标签拟化为一个滑动门,遮盖住输入框中的数据。这种动效既华丽又实用,可以隐藏类似信用卡号和安全码等隐私数据。该示例中同样使用了上述的混合宏。随你喜欢,Label 可以放在控件前后左右的任意位置

index.html

<div class=“slabel”>
  <input id=“credit-card” type=“text” pattern=“[0-9]{13,16}” placeholder=“xxxx-xxxx-xxxx-xxxx”>
  <label for=“credit-card”>Credit Card</label>
</div>

_slabel-input.scss

$slabel-theme: (
  border: 0,
  radius: 0,
  padding: 0,
  font: inherit,
  bg: white,
  label-bg: white,
  label-color: inherit,
  error-color: #E82C0C,
  placeholder-color: #B9E0D6,
  success-color: #5C832F
);

更多有关 Label 的特效,点击这里

输入框

输入框可以用来创建表单的交互控件或接收用户输入的表单数据。表单的输入框类型通常包括:文本、邮箱地址、数字、单选按钮、复选按钮,甚至是单纯的按钮类型。

下拉框

这一部分将会介绍一种简洁的方法美化下拉框,而不使用那些冗杂妥协的技巧。在大多数情境下,下拉框都是使用 JavaScript 设置为 display: none,然后制成多个 div 而实现的。用户喜欢这样的表现,但是开发者对此会非常痛恨。在可以使用 CSS 实现相关样式之前,我认为下面的这个方法,无论是对于开发者还是用户,都具有一定的吸引力。它允许开发者为支持相关属性的浏览器做出合理的美化,又不会影响其他浏览器的渲染和体验。

index.html

<select>
  <option>Property Closing*</option>
  <option>open</option>
  <option>closed</option>
</select>

_select-input.scss

$select-arrow: ‘data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDQ4IDQ4IiB3aWR0aD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE0LjgzIDE2LjQybDkuMTcgOS4xNyA5LjE3LTkuMTcgMi44MyAyLjgzLTEyIDEyLTEyLTEyeiIvPjxwYXRoIGQ9Ik0wLS43NWg0OHY0OGgtNDh6IiBmaWxsPSJub25lIi8+PC9zdmc+’;
$select-padding: 0;

select {
  border-radius: 0;
  -webkit-appearance: none; // autoprefixer won’t add this and we still need it
  appearance: none;
  cursor: pointer;
  padding: $select-padding;
  width: 100%;

  @media screen and (-webkit-min-device-pixel-ratio: 0) {
    background-image: url(#{$select-arrow});
    background-position: right 0 top 50%;
    background-repeat: no-repeat;
  }
}

更多细节请阅读 Lea Verou 的文章,也可以查看 Tympanus 创建的下拉框特效集合

单选按钮

单选按钮常用于选择一系列项目中的一个。相比较复选框可以选择多个选项,单选框只允许用户选择单一的选项。

下面的这个自定义单选按钮是基于 Sass 实现的,是对 Mark Otto 在 WTF,forms? 一文中单选按钮的改进版本。该版本中包含了一些使用 CSS 变形实现的定位技巧,并且具有良好的扩展性和定制能力。

index.html

<label for=“radioa” class=“input-control radio”>
  <input type=“radio” id=“radioa” name=“radio” value=http://www.w3cplus.com/preprocessor/“radio-value”>>

_input-radio.scss

$input-radius: 0 !default;
$input-unit: 16px !default; // accepts px, em, rem
$input-spacing: $input-unit * 1.5 !default; // adjust depending on font-family
$input-font: sans-serif !default;

$radio-bg: white !default;
$radio-txt-color: #AACCFF !default;

$radio-checked-custom: (
  background: #0081D0
) !default;
$radio-checked: #222233 !default;
$radio-checked-focus: white !default;

更多特效请查看 Samurai 的单选输入框动效集合

多选按钮

多选按钮的输入框类型为 checkbox,描述了一种可触发的状态。

SVG Checkbox

下面的 SVG 多选按钮是由 Sara Soueidan 创建的,通过 svg 为创建后的按钮增加了 X 形状。该元素使用了 SVG 的 stroke-dasharraystroke-dashoffset 属性,并辅以 CSS 动画属性实现了选择动效。除了根据 Sara Soueidan 的示例之外,我还添加了 :focus 状态和其他一些细节的优化,有助于开发者定义和扩展。

index.html

<input type=“checkbox” id=“optiona” name=“optiona”>
<label for=“optiona”>Click Me
  <svg viewBox=“0 0 100 100” xmlns=“http://www.w3.org/2000/svg”>
    <path d=“M 10 10 L 90 90”></path>
    <path d=“M 90 10 L 10 90”></path>
  </svg>
</label>

_checkbox-input.scss

$font-size: 2em; // adjust accordingly
$ratio: 1; // adjust accordingly
$size: $ratio + em;
$ratio: $ratio;
$gutter: 5px; // adjust accordingly
$stroke-dash: 270;
$stroke: (
  thickness: $gutter/3,
  style: solid,
  color: #fff
);
$mark-ischecked: (
  stroke-dashoffset: 0
); // define css properties
$label-ischecked: (); // define css properties
$svg-ischecked: (); // define css properties

滑动多选按钮

下面这个多选按钮曾被我用到了 Transformicons 项目中,看起来很像一个滑门。虽然它是基于 Sass 实现的,但在可复用的同时还很精简。值得注意的是,该动效还支持键盘操作:可以使用 tab 键选中该按钮,使用空格键来切换状态。

index.html

<div class=“slider-checkbox”>
  <input type=“checkbox” id=“option” aria-checked=“false” role=“checkbox”>
  <label for=“option”>Label Text</label>
</div>

在这个实例中使用 Sass 的全局变量,为开发者提供了两种样式:roundednull。使用 null,可以取消按钮的 border-radius 属性,使其呈现一种方形。

_slider-checkbox.scss

$checkbox-style: rounded; // accepts ‘rounded’ or ‘null’
$checkbox-sizing-unit: 6rem; // adjust this value for sizing
$checkbox-height: $checkbox-sizing-unit / 1/4;
$checkbox-position-unit: $checkbox-sizing-unit * 3/4;
$checkbox-speed: 150ms;
$checkbox-off-bg: #E8DFE7;
$checkbox-on-bg: #4fbe79;
$checkbox-btn-bg: #FFFFFD;

有效性状态

有效性伪类选择器通常被用于交互元素,以验证用户的输入状态,最常用的就是::invalid:valid。下面的 Sass 混合宏就包含了这些状态。值得注意的是,当输入框中内容不存在或不符合要求时,:invalid 选择器都会生效。

@mixin valid {
  &:valid,
  &:empty:valid,
  &:focus:empty:valid {
    @content;
  }
}

@mixin invalid {
  &:invalid,
  &:focus:invalid {
    @content;
  }
}

更多表单控件的伪类资料请参考参考这里

:required
:optional
:enabled
:disabled
:not(:checked)
:in-range
:out-of-range
:user-error
:empty
:blank

总结

如果你想更深入的理解美化本地表单控件的技术,可以参考这个跨浏览器伪类选择器一揽子详细总结。如果你想学习更多有效性状态,那么可以深读 W3C 的官方文档

本文根据@Dennis Gaebel的《Theming Form Elements with Sass》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.sitepoint.com/theming-form-elements-sass/

出处:http://www.w3cplus.com/preprocessor/theming-form-elements-sass.html