创建垂直表单控件

本指南介绍了如何使用 CSS 的 writing-modedirection 属性来创建和配置垂直表单控件。这包括:

通用技术

在现代浏览器中,writing-mode 属性可以设置为垂直值,以垂直显示文本字符通常为水平的表单控件(例如拉丁语系),文本会以默认方向旋转 90 度显示。通常垂直书写的文本字符(例如中文或日语)在这方面不受影响。

这在创建垂直语言表单时非常有用。

具体而言:

  • writing-mode: vertical-lr 将创建块流向为从左到右的垂直表单控件,这意味着在具有换行或多行文本的控件中,后续行将出现在前一行的右侧。
  • writing-mode: vertical-rl 将创建块流向为从右到左的垂直表单控件,这意味着在具有换行或多行文本的控件中,后续行将出现在前一行的左侧。

你也可以使用 transform 将控件旋转 90 度,但这会将控件放置在其自身的图层中,并可能导致意外的布局副作用,例如覆盖其他内容。使用 writing-mode 提供了一个更可靠的解决方案。

注意:虽然 writing-mode 属性得到了很好的支持,但使用 writing-mode 创建垂直方向的表单控件直到 2024 年才获得完整的浏览器支持。

注意:实验性的 sideways-lrsideways-rl 值分别与 vertical-lrvertical-rl 有类似的效果,不同之处在于,通常垂直书写的文本字符(例如中文或日语)会旋转 90 度侧向显示,而水平书写的文本字符(例如拉丁语系)不受这些值的影响。

此外,direction 属性可用于控制控件内部内容的方向:

  • direction: ltr 将使内容从顶部开始流向底部。
  • direction: rtl 将使内容从底部开始流向顶部。

direction 属性可用于设置内联基本方向——即内容在一行中排列的主要方向,它定义了一行的“开始”和“结束”在哪一侧。对于基于文本的表单控件,区别是显而易见的——文本流从顶部或底部开始。在非基于文本的控件(如范围滑块)中,direction 设置了控件绘制的方向。例如,在垂直滑块上设置 direction: ltr 会将最小值置于滑块顶部,最大值置于滑块底部。

以下各节将展示如何创建不同类型的垂直表单控件,并附有每个类型的示例。请查阅每个链接参考页面上的浏览器兼容性信息,以了解每种类型的确切支持情况。

范围滑块、meter 和进度条

我们来看看如何创建垂直的范围滑块、meter 和进度条。

基本示例

一组典型的可视化 <input type="range"> 滑块、<progress><meter> 控件是这样创建的:

html
<form>
  <input type="range" min="0" max="11" value="9" step="1" />
  <meter id="fuel" min="0" max="100" low="33" high="66" optimum="80" value="20">
    at 50/100
  </meter>
  <progress id="file" max="100" value="70">70%</progress>
</form>

注意:最佳实践是为每个表单控件包含一个 <label> 元素,以便为每个字段关联有意义的文本描述,以实现可访问性(更多信息请参见使用有意义的文本标签)。我们在此没有这样做,因为本文纯粹关注表单控件的视觉渲染方面,但你应该确保在生产代码中这样做。

要垂直显示这些控件,我们可以使用如下的 CSS:

css
input[type="range"],
meter,
progress {
  margin-block-end: 20px;
  writing-mode: vertical-lr;
}

writing-mode: vertical-lr(和 vertical-rl)可在现代浏览器中使控件垂直显示。

结果如下所示:

从下到上绘制控件

默认情况下,控件的 direction 值为 ltr。这会导致你的滑块、meter 和进度条从上到下绘制,如上所示。

你可以通过设置 direction: rtl 来改变这一点——这会使它们从下到上绘制:

css
input[type="range"],
meter,
progress {
  margin-block-end: 20px;
  writing-mode: vertical-lr;
  direction: rtl;
}

结果如下所示:

在旧版浏览器中创建垂直范围滑块

在不支持使用 writing-modedirection 创建垂直表单控件的旧版浏览器中,可用的替代方案有限。以下方法仅适用于 <input type="range">,并使文本从下到上流动——它们对 <meter><progress> 元素没有影响:

  • 非标准的 appearance: slider-vertical 属性可以在旧版 Safari 和 Chrome 中使用。
  • 非标准的 orient="vertical" 属性可以在旧版 Firefox 中添加到 <input type="range"> 元素本身。

此示例的 HTML 仅包含一个 <input type="range"> 滑块,并添加了 orient="vertical" 以使其在旧版 Firefox 中垂直显示:

html
<form>
  <input type="range" min="0" max="11" value="9" step="1" orient="vertical" />
</form>

为了使控件在旧版 Chrome 和 Safari 中也能垂直显示,我们可以使用 appearance: slider-vertical

css
input[type="range"] {
  margin-block-end: 20px;
  appearance: slider-vertical;
}

结果如下所示:

select 元素

本节介绍如何处理垂直的 <select> 元素。

Select 基本示例

下面的 HTML 创建了两个 <select> 元素,一个只能单选,另一个可以多选:

html
<form>
  <select multiple>
    <option>First</option>
    <option>Second</option>
    <option>Third</option>
    <option>Fourth</option>
    <option>Fifth</option>
  </select>
  <select>
    <option>First</option>
    <option>Second</option>
    <option>Third</option>
    <option>Fourth</option>
    <option>Fifth</option>
  </select>
</form>

要垂直显示这些控件,我们可以使用如下的 CSS:

css
select {
  inline-size: 100px;
  margin-block-end: 20px;
  writing-mode: vertical-rl;
}

结果如下所示:

调整文本方向和选项顺序

同样,可以使用 direction 属性值为 rtl 来将文本方向设置为从下到上,而不是默认的从上到下。

还值得注意的是,在上面的示例中,select 选项的内联方向是从右到左,因为我们使用了 writing-mode: vertical-rl。如果我们改用 writing-mode: vertical-lr<option> 文本将从左到右显示。

我们将使用三个列表框(multiple<select> 元素来探讨这两种用例,以便轻松地并排比较效果。

html
<form>
  <div>
    <h2>writing-mode: vertical-lr</h2>
    <select multiple>
      <option>First</option>
      <option>Second</option>
      <option>Third</option>
      <option>Fourth</option>
      <option>Fifth</option>
    </select>
  </div>
  <div class="direction">
    <h2>direction: rtl & writing-mode: vertical-lr</h2>
    <select multiple>
      <option>First</option>
      <option>Second</option>
      <option>Third</option>
      <option>Fourth</option>
      <option>Fifth</option>
    </select>
  </div>
  <div class="reverse-option-order">
    <h2>writing-mode: vertical-rl</h2>
    <select multiple>
      <option>First</option>
      <option>Second</option>
      <option>Third</option>
      <option>Fourth</option>
      <option>Fifth</option>
    </select>
  </div>
</form>

在此示例的 CSS 中,我们为这三个列表框设置了以下属性:

  1. writing-mode: vertical-rl,显示方式与前一个示例相同——文本从上到下流动,选项从右到左显示。
  2. writing-mode: vertical-rldirection: rtl,选项从右到左,但文本流反转为从下到上。
  3. writing-mode: vertical-lr,文本从上到下,但选项顺序反转为从左到右。
css
select {
  inline-size: 100px;
  margin-block-end: 20px;
  writing-mode: vertical-rl;
}

.direction select {
  direction: rtl;
}

.reverse-option-order select {
  writing-mode: vertical-lr;
}

结果如下所示:

按钮

本节介绍如何处理垂直的 <button> 元素。请注意,虽然我们在下面的示例中只使用了 <button> 元素,但对于其他创建按钮的元素,其行为是相同的,例如 <input>buttonresetsubmit 类型。

基本按钮示例

下面的 HTML 创建了两个 <button> 元素,一个带有一行文本,另一个带有三行:

html
<button>Press me</button> <button>Press me<br />Please?<br />Thanks</button>

要垂直显示这些按钮,我们可以使用如下的 CSS:

css
button {
  inline-size: 100px;
  margin-block-end: 20px;
  writing-mode: vertical-rl;
}

结果如下所示:

调整按钮文本行顺序

当你将 writing-mode 的值从 vertical-rl 切换到 vertical-lr 时,后续的文本行将出现在前一行的右侧,而不是左侧。

此示例使用了我们在前一个示例中看到的带有三行文本的按钮的两个副本,这样你就可以轻松看到更改书写模式的效果:

html
<div>
  <h2>writing-mode: vertical-lr</h2>
  <button>Press me<br />Please?<br />Thanks</button>
</div>
<div class="reverse-line-order">
  <h2>writing-mode: vertical-rl</h2>
  <button>Press me<br />Please?<br />Thanks</button>
</div>

在 CSS 中,我们在第一个按钮上设置 writing-mode: vertical-rl,使行顺序从右到左排列。在第二个按钮上,我们设置 writing-mode: vertical-lr 来反转行顺序——从左到右:

css
button {
  inline-size: 100px;
  margin-block-end: 20px;
  writing-mode: vertical-rl;
}

.reverse-line-order button {
  writing-mode: vertical-lr;
}

结果如下所示:

基于文本的表单控件

最后,我们来看看如何处理垂直的 <textarea> 和文本类型的 <input>。请注意,虽然我们在下面的示例中只包含了一个 <input type="text"> 元素,但对于其他文本类型的 <input>,其行为是相同的:passwordnumberurl 等。

基本文本输入和 textarea 示例

下面的 HTML 创建了一个 <textarea> 和一个 <input type="text">

html
<form>
  <textarea>This is my textarea</textarea>
  <input type="text" value="Input text" />
</form>

要垂直显示输入框和文本区域,我们可以使用如下的 CSS:

css
textarea,
input[type="text"] {
  inline-size: 100px;
  margin-block-end: 20px;
  writing-mode: vertical-rl;
}

结果如下所示:

调整文本方向和行布局顺序

你可以使用 direction 属性值为 rtl 来将文本方向从默认的从上到下更改为从下到上。你还可以将 writing-mode 设置为 vertical-lr 而不是 vertical-rl,以使 <textarea> 中的多行文本从左到右显示,而不是默认的从右到左。

此示例使用了我们在前一个示例中看到的相同文本控件的三个副本,这样你就可以轻松看到如上所述更改 directionwriting-mode 的效果:

html
<form>
  <div>
    <h2>writing-mode: vertical-lr</h2>
    <textarea>This is my textarea</textarea>
    <input type="text" value="Input text" />
  </div>
  <div class="direction">
    <h2>direction: rtl & writing-mode: vertical-lr</h2>
    <textarea>This is my textarea</textarea>
    <input type="text" value="Input text" />
  </div>
  <div class="reverse-line-order">
    <h2>writing-mode: vertical-rl</h2>
    <textarea>This is my textarea</textarea>
    <input type="text" value="Input text" />
  </div>
</form>

在 CSS 中,我们为这三组文本控件设置了以下属性:

  1. writing-mode: vertical-rl 使其显示方式与前一个示例相同——文本从上到下流动,行从右到左流动。
  2. writing-mode: vertical-rldirection: rtl 使行从右到左流动,但文本流反转为从下到上。
  3. writing-mode: vertical-lr 使文本从上到下流动,但反转了行的流动方向——从左到右。请注意,这对 <input type="text"> 元素没有影响,因为它们始终是单行。
css
textarea,
input[type="text"] {
  inline-size: 100px;
  margin-block-end: 20px;
  writing-mode: vertical-rl;
}

.direction textarea,
.direction input[type="text"] {
  writing-mode: vertical-rl;
  direction: rtl;
}

.reverse-line-order textarea,
.reverse-line-order input[type="text"] {
  writing-mode: vertical-lr;
}

结果如下所示:

另见