新型应用程序

使用适用于 WinJS 应用程序的 CSS 构建响应迅速的现代 UI

Rachel Appel

使用 CSS 会让许多开发者感到沮丧,因为其中充满了各种细微差别。即便是对某个选择器或 HTML 元素进行少量更改,往往也会传播给另一个选择器或 HTML 元素并对其造成影响。由于 CSS 的众多怪异问题(尤其是面向多个浏览器时),试图使其保持简洁而有效可能相当困难。幸运的是,如果您要开发的是 Windows JavaScript 库 (WinJS) 应用程序,可以使用 Visual Studio 项目模板中内置的 CSS,它既灵活又具有一致和易于维护的特点。Visual Studio 项目模板包含的代码构成了响应迅速的现代 UI 设计的基础。

适用于 Windows 应用商店应用的内置 CSS

所有适用于使用 JavaScript 构建的 Windows 应用商店应用的项目模板均包含两个基本样式表或主题 — 深色(默认)和浅色,它们分别位于名为 ui-dark.css 和 ui-light.css 的文件中。这些文件属于 Visual Studio 项目引用节点下 CSS 文件夹中的一组核心项目文件的组成部分。核心 CSS 文件中有近 4,000 行 CSS,因为它们构建的 UI 需要遵循所有 Windows UI 设计原则,包括响应 Windows 对齐视图和媒体类型的更改。您不应试图修改内置样式表(它们是只读的),而是应该覆盖您自己的 CSS 文件中的内置样式。

要使用内置 Windows 应用商店应用 CSS,请将以下引用添加到任意页面的 <head> 部分(请注意,链接中的“2.0”适用于 Windows 8.1,而“1.0”适用于 Windows 8):

 

<link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />

路径开头的两个正斜杠表示对 WinJS 核心库(也称为“共享库”,即与应用程序包中的本地项目文件相对)的引用。 在使用 JavaScript 构建的 Windows 应用商店应用中,以单个正斜杠开头的路径表示该路径开始于项目的根文件夹,单个正斜杠是指本地项目文件。

使用 JavaScript 构建的 Windows 应用商店应用采用了充足的供应商前缀(例如 -ms-grid、-flexbox 等),使技术最先进的 CSS 得以在应用程序中使用。 WinJS 应用程序中的其他高科技 CSS 包括 CSS3 RGBA 颜色、Web 开放字体格式 (WOFF) 字体和媒体查询。

使用 CSS 设置 WinJS 控件样式

WinJS 控件是 HTML 元素的延伸,因此您可以像使用任何 HTML 标记那样,使用 CSS 设置 WinJS 控件的样式。 Visual Studio 项目模板包含对用于为每个 HTML 元素和 WinJS 控件创建现代 UI 样式的 CSS 的引用,分为深色和浅色两种类型。 当然,您并非只能使用这些样式,而是可以根据需要对其进行修改以满足公司或是产品品牌或主题的需要。 但是,要与新的 Windows UI 保持一致以免使用户感到困惑,这一点很重要。

图 1 分别展示了同时使用深色和浅色主题的几个基本的常见 HTML 和 WinJS 控件的代码。 图 2 显示了此代码的输出。

图 1 基本 HTML 和 WinJS 控件的代码

<div id="grid">
  <div style="-ms-grid-column: 1; -ms-grid-row: 1">
    <label for="textbox">Textbox:</label>
    <input id="textbox" type="text" />
  </div>                   
  <div style="-ms-grid-column: 2; -ms-grid-row: 1">
    <label for="button">Button:</label>
    <button id="button" value="Button">Clickety Click</button>
  </div>
  <div style="-ms-grid-column: 1; -ms-grid-row: 2">
    <label for="radio">Radio:</label>
    <input type="radio" id="radio" name="radio" />
      <label for="radio">One</label>
    <input type="radio" id="radio" name="radio" />
      <label for="radio">Two</label>
    <input type="radio" id="radio" name="radio" />
      <label for="radio">Three</label>
  </div>                   
  <div style="-ms-grid-column: 2; -ms-grid-row: 2">
    <label for="select">Select:</label>
    <select id="select">
      <option value="One">One</option>
      <option value="Two">Two</option>
      <option value="Three">Three</option>
     </select>
  </div>                                  
  <div style="-ms-grid-column: 2; -ms-grid-row: 3">
    <label for="rating">Rating:</label>
      <div id="rating" data-win-control="WinJS.UI.Rating"></div>
  </div>
  <div style="-ms-grid-column: 1; -ms-grid-row: 3">
    <label for="toggle">Toggle:</label>
    <div id="toggle" data-win-control="WinJS.UI.ToggleSwitch"></div>
  </div>  
  <div style="-ms-grid-column: 1; -ms-grid-row: 4">
    <label for="datepicker">Date Picker:</label>
    <div id="datepicker" data-win-control="WinJS.UI.DatePicker"></div>
  </div>                     
 <div style="-ms-grid-column: 2; -ms-grid-row: 4">
    <label for="timepicker">Time Picker:</label>
    <div id="timepicker" data-win-control="WinJS.UI.TimePicker"></div>
  </div>
</div>

Common HTML and WinJS Controls in Dark Default Style
Common HTML and WinJS Controls in Light Default Style
图 2 采用深色和浅色默认样式的常见 HTML 和 WinJS 控件

通过查看图 2 可以发现,控件的默认样式反映了新的 Windows UI。 Windows 开发人员中心提供了 HTML 和 WinJS 控件的完整列表,网址为 bit.ly/w1jLM5

有关 WinJS 控件现状的详细信息,请参阅 msdn.microsoft.com/magazine/dn296546 上我的专栏“精通用 JavaScript 构建的 Windows 应用商店应用中的控件和设置”。 同时,我还会介绍以下几个重要控件的样式设置指导原则:AppBar、浮出控件和 ListView。

AppBar AppBar 是所有 Windows 应用商店应用的基本 UI 组件。 CSS 选择器可用于设置 AppBar 各个方面的样式,包括 AppBar 整体、各个按钮标签、图像以及常规和悬停状态下的工具提示。 这意味着您可以全面掌控 AppBar 的外观。 当您通过覆盖 .win-appbar 类完成 AppBar 本身的样式设置后,便可以继续设置各个命令了。 由于 AppBar 按钮是 WinJS 控件,因此 data-win-options 属性包含通过设置 label、icon、section 和 tooltip 属性正确设置命令按钮的所有必要信息:

<div id="appbar" class="win-appbar"
  data-win-control="WinJS.UI.AppBar">
  <button data-win-control="WinJS.UI.AppBarCommand"
    data-win-options="{
      id:'addFriend',
      label:'Add Friend',
      icon:'addfriend',
      section:'global',
      tooltip:'Add a friend'}"
    type="button">
  </button>
</div>

您可以通过调整以下类选择器的样式,使 AppBar 具有与横跨屏幕底部的简单默认条带迥然不同的外观。

  • .win-appbar:设置 AppBar 的整体样式。
  • .win-command:设置单个 AppBar 按钮的样式。
  • .win-commandimage:设置命令按钮图像的样式。
  • .win-commandring:设置 AppBar 按钮周围的圆环的样式。
  • .win-commandimage:hover 和 .win-commandring:hover:设置命令按钮图像和圆环悬停状态的样式。

如您所见,可以设置 AppBar 各个方面的样式。 

浮出控件 浮出控件是交互式弹出窗口。 在 Windows 应用商店应用中,浮出控件常作为应用程序的“设置”超级按钮的组成部分实现,目的通常是收集用户输入。 浮出控件非常适用于实现设置或保存用户不经常访问的某些数据。 例如,您可以使用它们提供应用程序被 Windows 应用商店接受所需的隐私声明。 浮出控件的样式设置非常简单,只需覆盖 .win-flyout 选择器即可。 系统 CSS 包含 .max-width 和 .max-height 的设置,因此如果您需要收集整个数据表单,可能需要调整这些设置。

浮出控件是一个保持隐藏和不可见状态的 <div> 元素,仅当用户通过超级按钮或 AppBar 命令调用它时才会弹出到屏幕上。 尽管浮出控件中存在其他控件,但设置这些控件的样式不会改变这一点,因为它们只是 HTML。

ListView ListView 很可能是最复杂的 WinJS 控件,它提供了在一个网格或列表中显示多个数据项的方式。 ListView 还可响应由用户发起的触摸和鼠标事件,使用户可以选择某个项目或调用某个操作。 自 Windows 8.1 起,ListView 控件允许用户对项目进行拖放和重新排序。

在使用 ListView 控件之前,您必须先了解其工作原理。 ListView 控件主要包括四个可以灵活设置的部件:ListView 本身、视区、表面区域和项目。 项目存在于表面区域内,而后者是 ListView 的可滚动区域。 表面区域在视区内存在和移动,因此视区包含滚动条,如图 3 所示。

The Viewport and Its Surface Area Combine to Make the ListView Control
图 3 视区及其表面区域组成 ListView 控件

视区与其充满项目的表面区域共同组成了 ListView 控件。 由于 ListView 控件包含这些具有不同操作方式的部件,因此对于其样式设置存在许多详细指导原则,Windows 开发人员中心提供了相关概述,网址为 bit.ly/­HopfUg。 现在,我要介绍一下设置 ListView 控件外观需要了解的最重要的内容:

  • .win-listview:设置 ListView 的整体样式。
  • .win-viewport:设置 ListView 视区的样式。
  • .win-surface:设置 ListView 可滚动区域的样式。

这些可以灵活设置的部件使您可以执行多种操作,如应用某个随项目滚动的背景图像。 当表面区域大于视区时,视区将显示滚动条(根据需要显示为垂直或水平)。

设置 ListView 项目的样式非常简单。 可以使用 .win-item 和 .win-container 类。 ListView 中的每个项目都放在一个容器中,容器用于保存该项目的图像和文本字段。 这个容器其实就是一个 HTML 模板,用于定义共同创建 ListView 中的项目的各个元素。 图 4 中的代码展示了如何定义该模板及其对应的 ListView。 它将创建一个 WinJS.Binding.Template 控件,ListView 使用该控件显示数据。

图 4 定义一个模板及其对应的 ListView 的代码

<div id='listviewtemplate' class="itemtemplate" 
  data-win-control="WinJS.Binding.Template">
  <div class="item">
    <img class="item-image" src="#"
      data-win-bind="src: backgroundImage; alt: title" />
    <div class="item-overlay">
      <h4 class="item-title" data-win-bind="textContent: title"></h4>
      <h6 class="item-subtitle win-type-ellipsis"
         data-win-bind="textContent: subtitle"></h6>
    </div>
  </div>
</div>
<div class="groupeditemslist win-selectionstylefilled"
  aria-label="List of groups"
  data-win-control="WinJS.UI.ListView"
   data-win-options="{ selectionMode: 'none' }">
</div>

如您所见,图 4 中有用于组成 ListView 项目模板的 <div> 元素,这些模板内置于“网格”和“拆分”项目模板中。 在运行时,应用程序的执行引擎会将 .win-container 和 .win-item 类插入这些元素中,因此您在开发过程中不会在代码中看到这些选择器,但您可以在 CSS 文件中覆盖它们以应用您自己的样式。 在项目模板的 ListView 代码中,.item、.item-image、.item-title、.item-subtitle 和 .item-overlay 均作为选择器提供,您可对其进行修改以指定网格内每个项目的外观。

如果没有排序、分组和执行其他影响其成员的操作的功能,任何列表或网格都是不完整的。 因此,既有用于分组项目的样式,也有用于单个项目的样式。 通过覆盖 .win-groupheader 类选择器可设置组标题的样式,通过覆盖 .win-progress 可在样式中显示进度。

流畅 CSS 用于实现响应迅速的 UI

Visual Studio 中的“网格”、“拆分”和“导航”项目包含与 HTML5 语义元素配合使用以确保实现流畅的现代布局的 WinJS CSS 选择器。 图 5 显示了通过“网格”模板创建网格布局所需的 CSS 和 HTML。 请注意,.fragment 类使用 -ms-grid-columns 和 -ms-grid-rows 前缀定义网格的行和列。 随后,它将这些前缀和其他选择器应用于图 5 中的 <div> 元素。 <header> 和 <section> 语义元素用于明确定义每个元素中放置何种类型的内容。

图 5 页面段的基础 HTML 和 CSS

.fragment {
  /* Define a grid with rows for a banner and a body */
  display: -ms-grid;
  -ms-grid-columns: 1fr;
  -ms-grid-rows: 128px 1fr;
  height: 100%;
  width: 100%;
}
  .fragment header[role=banner] {
    /* Define a grid with columns for the back button and page title. */
    display: -ms-grid;-ms-grid-columns: 39px 81px 1fr;
    -ms-grid-rows: 1fr;
  }
  .fragment header[role=banner] .win-backbutton {
    -ms-grid-column: 2;
    margin-top: 59px;
  }
  .fragment header[role=banner] .titlearea {
    -ms-grid-column: 3;
    margin-top: 37px;
  }
  .fragment header[role=banner] .titlearea .pagetitle {
    width: calc(100% - 20px);
  }
  .fragment section[role=main] {
    -ms-grid-row: 2;
    height: 100%;
    width: 100%;
  }
<div class="fragment groupeditemspage">
  <header aria-label="Header content" role="banner">
    <button class="win-backbutton" aria-label="Back"
       disabled type="button"></button>
    <h1 class="titlearea win-type-ellipsis">
      <span class="pagetitle">CSS in Windows Store apps</span>
    </h1>
  </header>
  <section aria-label="Main content" role="main">
    <div class="groupeditemslist win-selectionstylefilled"
       aria-label="List of groups"
       data-win-control="WinJS.UI.ListView"
       data-win-options="{ selectionMode: 'none' }">
  </div>
  </section>
</div>

由于此 CSS 是“网格”和“拆分”项目模板的组成部分,因此您不必担心需要完成创建根据数据变化或应用程序状态而变化的流畅网格的繁琐任务,此功能已内置。

Windows 应用商店 JavaScript 应用程序模板使用 CSS 框模型(请参阅我的博客文章“关于使用 CSS 框模型进行元素显示和放置的指南”,网址为 bit.ly/xxATgL)布置页面,并使用 CSS 网格布局(有关详细信息,请参阅万维网联盟 [W3C] 站点,网址为 bit.ly/14yzx2h)创建响应迅速的 UI。 请注意,在对齐视图和完整视图之间变化时,网格会变为垂直列表再变回网格。

Windows 应用商店应用中的大部分默认项目模板都利用 CSS 媒体查询提供可响应设备和浏览器大小、方向和分辨率的变化的复杂 UI。 如果要了解有关媒体查询的更多信息,请参阅我的博客文章“使用 CSS 媒体查询创建移动站点布局”,网址为 bit.ly/1c39mDx

Windows 应用商店应用使用媒体查询的另一个原因是 Windows 8 支持四种不同的应用程序视图状态:完整视图、对齐视图、填充视图和纵向视图。 当用户将应用程序置于对齐视图或填充视图中时,从概念上讲相当于通过不同的设备访问该应用程序,因为浏览器的尺寸和方向都会发生彻底的变化。

查看内置 CSS 时您会发现,有许多适用于这四种应用程序视图状态以及高对比度和可访问的查看状态的 @media 规则。 以下是用于检测对齐视图和全屏幕纵向状态的媒体查询:

@media screen and (-ms-view-state: snapped) {}
@media screen and (-ms-view-state: fullscreen-portrait) {}

通常情况下,适用于完整视图的 CSS 同样适用于填充视图(四分之三屏幕)。 以上查询显示了 Windows 应用商店应用领域最热门的两种媒体功能,但 W3C 站点还提供了许多其他媒体功能,网址为 bit.ly/gnza0F

Windows 应用商店应用使用高效、有条理的 CSS

查看 Visual Studio 模板的内置 CSS 选择器时,您会注意到它们非常简洁而精确。 CSS 的具体性(任何代码都是如此)使其构建的应用程序更易于维护且性能更高。 当您在代码中看到“.fragment header[role=banner]”,便会确切知道它适用于哪些元素 — 在本例中是归类为“fragment.”的元素内具有值为“banner”的 role 属性的 <header> 元素。请记住,浏览器从右向左解析 CSS,因此最具体的选择器应放在右侧,使浏览器可以更快找到匹配的 DOM 元素。

与使用脚本切换可视指标相比,利用某些 CSS 功能(如悬停、活动、禁用、启用和其他可视状态的伪选择器)可确保维护工作更加简单。 WinJS 根据许多控件的需要定义伪选择器。 例如,TextBox 和 CheckBox 可在禁用和启用状态间切换,锚点可在悬停和活动状态间切换。 Windows 8.1 中还有更多 CSS 动画 (bit.ly/KDVSPU),在转而使用 JavaScript 实现相同动画之前,您可以了解一下这些动画。

效率意味着正确的文件组织和高效的代码。 \css 文件夹中有一个名为 default.css 的文件,所有内置 HTML 页面均包含对此文件的引用。 此文件中包含您在图 5 中看到的 CSS,以及常规样式规则和媒体查询。 与 ui-dark.css 和 ui-light.css 文件不同,default.css 可以修改或删除。

Visual Studio 项目模板会将文件整理到包含相关项目的文件夹中,例如 groupedItems.html、grouped­Items.js 和 groupedItems.css 与其他类似结构一起放在 \pages\groupedItems 文件夹中。 您可以继续按这种方式将文件整理到文件夹中,也可以按您自己的方式重新排列文件。 或许您会因为希望尝试使用 Model-View-ViewModel (MVVM) 模式而重新整理项目结构,在这种情况下,CSS 文件可以放入另一个文件夹。 您也可能希望将所有 CSS 丢入一个文件夹。 只要您的文件组织对于项目是合理的并且易于维护,那么如何整理并不重要。

出于可读性考虑,可以将 CSS 分为不同的文件并按其功能进行排列。 例如,您可能有用于实现由许多页面使用的单个控件(如浮出控件)的 CSS。 该文件可以放在通用 CSS 的文件夹中,也可以放在浮出控件所在的文件夹中。 如果一个 CSS 文件充斥着与引用该文件的页面完全无关的 CSS,要研究这样的文件真是再糟糕不过了。 例如,符合下列条件的 CSS 应该有自己的文件:

  • 用于实现某个特定浮出控件或设置页面的 CSS。
  • 仅包含颜色和美学元素(用于创建主题)的 CSS。 这样您可以根据需要换入和换出颜色样本等 CSS 文件。
  • 媒体查询中针对某个特定情形(如对齐视图或填充视图)的 CSS。 此 CSS 可以放在其自己的文件中,而该文件放在引用它的页面所在的目录中。

这样,您可以根据需要使用 CSS 的每个功能单元,而不必针对每个页面(无论其是否使用 CSS)加载所有 CSS。 请记住,这些只是指导原则,每个项目都具有独特性,并且可能有不同的需求。

Windows 应用商店应用项目会执行设备本地的代码而不是先下载 CSS 或脚本,因此您不需要像在 Web 项目中那样捆绑并缩小 CSS 和脚本。 当然,应用程序在执行前必须将代码加载到内存中,因此出于性能和可读性方面的原因,您仍然需要避免臃肿的代码。

关注应用程序构建

许多内置 WinJS 控件的样式设置都非常简单,因为框架提供了先进的 CSS3 和 HTML5 功能。 WinJS 中的核心 CSS 可创建流畅而灵活的现代 UI,当用户在完整视图与对齐视图间切换时,该 UI 能够响应应用程序视图状态的变化。 拥有现成的核心 WinJS CSS 意味着您可以集中关注应用程序的构建,而不必费力操作结构化 CSS 以创建现代风格的 UI。

Rachel Appel是一名顾问、作家、导师和前 Microsoft 员工,在 IT 行业有 20 多年的经验。她常在 Visual Studio Live!、DevConnections、MIX 等顶级行业大会上发言。她的专业是开发侧重于 Microsoft 系列开发技术和开放式 Web 并且符合业务和技术需要的解决方案。有关 Appel 的详细信息,请访问她的网站 rachelappel.com

衷心感谢以下技术专家对本文的审阅:Eric Schmidt (Microsoft)