原文:CSS for Windows 8 app development
协议:CC BY-NC-SA 4.0
四、文本属性
注意伟大的排版有一些非常引人注目的地方,会让用户喜欢你的应用。
如果你已经阅读了第一章,那么你知道如何选择元素,你知道如何为这些元素定义样式规则,现在,你已经准备好把单纯的结构变成既美观又实用的东西了。
我们将详细了解许多样式属性中的一些。在这一章中,我们将介绍与排版相关的属性——与应用程序中的文本相关的属性。我们将查看文本颜色和字体属性,以决定文本呈现的字体、大小和粗细。我们将探索在 Windows 8 应用中比在传统网页设计中更受欢迎的多栏布局,我们将学习如何控制文本栏中的断字。
让我花点时间让你相信在你的 Windows 8 应用中高质量排版的重要性。排版不仅仅是让文本看起来很花哨——至少在 Windows 8 应用中是这样。在 Windows 8 中,排版用于传达风格,但也用于传达结构和层次。它帮助用户的眼睛和大脑快速判断屏幕上内容的意义。它用于帮助他们区分应用程序的标题、部分的类别以及组成应用程序内容的文本正文。
因此,花时间学习如何更好地控制应用程序中的文本显示,然后考虑微软设计风格原则的第一条——对工艺表现出自豪。这意味着你应该花时间来确保你的应用程序是完美的,有意识地让你的字体美观是一种完美应用程序的重要方式。
文本
页面上的文本有一个传递信息的基本功能,但小心选择字体和文本布局可以区分一个看起来像字典的应用程序和一个真正吸引用户的应用程序。
在这一部分,我们将会看到一些基本的文本属性,这些属性可以让我们控制文本的颜色、不透明度、粗细、大小和字体。先说颜色和不透明度。
颜色和不透明度
颜色属性 决定了选中元素的前景色。它主要影响元素包含的文本。
定义颜色有三个常见的地方:color
属性、background-color
属性(参见第三章)和border-color
属性(同样,参见第三章),颜色总是以相同的方式定义——实际上是以方式定义——有四种常见的方式来定义颜色:
- 按颜色名称
- 按十六进制值
- 通过 rgb()或 rgba()函数
- 通过 hsl()或 hsla()函数
命名颜色
对大多数人来说,用颜色的名字来定义颜色可能是最直观的,所以如果有一种已命名的颜色符合你的要求,那就一定要使用它。您可以通过名称定义颜色,只需将颜色名称作为值提供给color
属性。在 HTML/CSS 标准中有 147 种命名颜色,你可以在http://www.w3.org/TR/css3-color/#svg-color
看到它们的列表。其中一些是基本的像:Red
、Green
、Blue
。其中一些是像DarkRed
、LightGreen
和DarkSlateBlue
这样的基础的派生。其中一些完全是深奥的,如DarkGoldenRod
、LemonChiffon
和PapayaWhip
。命名的颜色不区分大小写,所以papayawhip
和PapayaWhip
一样有效。
十六进制颜色
使用十六进制值来定义颜色,你可以拥有远不止 147 种颜色——实际上更像是 1680 万种颜色。也许您还记得早期 web 开发中的建议,即您应该坚持使用窄范围的“web 安全色”,但是在当今时代,浏览器只能使用窄范围的调色板的情况少之又少,这个建议几乎没有意义。如果您正在创建一个 Windows 8 应用程序,那么您知道您正在使用 Internet Explorer 浏览器引擎的最新 web 标准,您当然不需要担心像这样的遗留兼容性问题。
十六进制颜色值是一个六位数的十六进制值,前面有一个哈希(#
)。例如,#FFEFD5
将给出等同于PapayaWhip
的值,十六进制值也不区分大小写,所以#ffefd5
也能很好地工作。第一对十六进制数字代表红色级别,第二对代表绿色级别,第三对代表蓝色级别。
表 4-1。一些十六进制值和它们的颜色等价物
十六进制值 | 颜色 |
---|---|
#000000 | 黑色 |
#ffffff | 白色 |
#ff0000 | 红色 |
#00ff00 | 绿色的 |
#0000ff | 蓝色 |
#ffff00 | 黄色 |
#00ffff | 蓝绿色 |
#ff00ff | 品红 |
即使是我们当中更狂热的数字骑师也需要一些时间来转换十进制和十六进制,因此任何现代图形软件包都应该提供您选择的任何颜色的十六进制等价物,这很方便。用十六进制值来指定颜色并不能提供不透明度,所以如果你需要某种程度的透明度,那就继续读下去。
对于带有重复对的十六进制值,如#000000
、#ffffff
,甚至是#aa33dd
,有一种指定十六进制值的简写方法。如果您指定一个只有三个字符的十六进制值,那么它将成对重复这三个值。用这个速记技巧,用#000
代替#000000
( black
),#fff
代替#ffffff
( white
),或者#ff0
代替#ffff00
( yellow
)。
颜色
用rgb()
和rgba()
函数定义颜色非常简单。rgb()
函数的工作方式与十六进制值类似,只是三个颜色分量作为十进制参数传递给函数,而不是三个十六进制对。颜色值rgb(0,0,0)
将产生黑色,就像十六进制值#000000
一样。rgba()函数在接受 alpha 值方面更进了一步。alpha 值定义颜色的不透明度;也就是说,它决定了颜色出现的程度,而不是让它的背景透过。这是透明的反面。完全不透明(零透明度)的蓝色是蓝色,并完全覆盖其背景,而一半不透明(半透明度)的蓝色让一些背景通过,就好像它是蓝色的玻璃。作为一个例子,rgb(0,0,255)
将完全是蓝色的,而rgba(0,0,255,0.5)
将产生类似蓝色玻璃的东西。
红色、绿色和蓝色的值可以是从 0 到 255 的整数值,也可以是百分比值(后跟一个%符号)。alpha 值应该始终是从 0.0(完全透明)到 1.0(完全不透明)的十进制值。
HSL 颜色
与rgb()
和rgba()
类似,您可以使用hsl()
和hsla()
功能根据色调、饱和度和亮度值指定颜色。HSL 是表示独特颜色的另一种方法。色调代表颜色在彩虹中的位置,饱和度大致对应于颜色的丰富程度,明度代表颜色的明暗程度。使用 HSL 值代替 RGB 值的好处是它们相对直观。一旦你有了正确的色调,你就可以调整它的饱和度和明度值来对颜色进行明智的调整,这对于 RGB 来说就不可说了。任何 RGB 值的微小变化都会产生完全不同色调的颜色。这在创建色带时特别有用,在色带中,选择一种色调作为主题颜色,并使用不同的饱和度或亮度值来创建应用程序的视觉资产。
这些函数将它们的第一个参数(色调)作为一个从 0 到 255 的整数,将它们的第二个和第三个参数(饱和度和亮度)作为一个百分比,hsla()
将第四个参数(alpha)作为一个从0.0
(完全透明)到1.0
(完全不透明)的小数。
不透明
opacity
属性是相关的。文本的不透明度决定了允许透过文本显示多少背景。显式设置文本的不透明度与在rgba()
或hsla()
函数中使用 alpha 值是一样的(并且可以结合使用)。不透明度实际上与透明度相反,因此最大值1.0
将导致文本不允许任何背景通过(100%不透明度或完全不透明),最小值0.0
将允许背景完全通过(0%不透明度或完全透明)。
当我们开始制作动画时,不透明度变成了一个更加有用和相关的话题。通常,不透明度从 0 到 1 的动画会使其淡入,从 1 到 0 的动画会使其淡出。
字体和文本样式
大多数与版式相关的属性(前面的例子除外)都以text-
或font-
开头,现在你会看到其中的许多属性。字体属性非常多,所以有一个速记属性,非常有用。在谈论速记语法之前,我将介绍一下各个属性。在接下来的章节中,我们将对字体的可能性进行更深入的探讨。
字体风格〔??〕
属性主要用于斜体显示你的文本。这些值(除了所有属性共享的继承值之外)实际上是normal
、italic
和oblique
。使用italic
将选择正在使用的斜体版本。然而,使用oblique
非常相似,你可能会挠头想知道它们之间的区别。不同的是,italic
选择斜体版本的字体,oblique
只倾斜普通版本的字体。通常它们看起来非常相似,但有时它们实际上非常不同。
大多数印刷工人不喜欢使用oblique
而不是利用合适的斜体,但它在紧要关头肯定会起作用。如果你不太在乎完美的排版,那么这将省去你嵌入额外的斜体子集字体的麻烦。清单 4-1 中的代码定义了字体样式的三个值,图 4-1 描绘了结果。
图 4-1 。在大多数情况下,斜体字看起来和斜体一样,但是用斜体字代替真正的斜体字体可能会被严肃的印刷者所反对
清单 4-1 。使用 font-style 属性使文本倾斜
<!-- HTML snippet -->
<div class="normal">Lorem ipsum dolor sit amet</div>
<div class="italic">Aenean cursus vehicula purus id sagittis</div>
<div class="oblique">Morbi tincidunt suscipit dignissim</div>
/* CSS snippet */
.normal { font-style: normal; }
.italic { font-style: italic; }
.oblique { font-style: oblique; }
字体变体
font-variant
非常简单,只有normal
和smallcaps
表示值。小型股可能是标准资本化的一个有趣而有效的变体。在小型大写字母文本中,所有字母都是大写的,但只比小写字母稍微高一点。你可以在清单 4-2 和图 4-2 中看到小型大写字母变体的例子。
图 4-2 。请注意,第二行中的所有字母都是大写的,但是实际的大写字母只比小写字母高一点点
清单 4-2 。使用 font-variant 属性将文本转换为小型大写字母
<!-- HTML snippet -->
<div class="normal">Lorem ipsum dolor sit amet</div>
<div class="smallCaps">Aenean Cursus Vehicula Purus ID Sagittis</div>
/* CSS snippet */
.normal { font-variant: normal; }
.smallCaps { font-variant: small-caps; }
字体粗细
您可能会经常使用font-weight
属性来决定您的文本是否应该加粗。一个normal
值将是正常的,一个bold
值将是粗体的。字体的粗细可以通过指定从100
-900
到100
的任意增量进行数值设置。400
的值与normal
相同,而700
的值与bold
相同。您也可以使用bolder
或lighter
使文本比它所继承的值逐渐变粗或变亮。清单 4-3 和图 4-3 提供了一个例子。
图 4-3 。第二行(粗体)明显比第一行(正常)要粗,第三行(100)明显要浅,最后一行虽然是最大的字体粗细,但几乎看不出来
清单 4-3 。使用 font-weight 属性使文本加粗或不加粗
<!-- HTML snippet -->
<div class="normal">Lorem ipsum dolor sit amet</div>
<div class="bold">Lorem ipsum dolor sit amet</div>
<div class="_100">Lorem ipsum dolor sit amet</div>
<div class="_900">Lorem ipsum dolor sit amet</div>
/* CSS snippet */
.normal { font-weight: normal; }
.bold { font-weight: bold; }
._100 { font-weight: 100; }
._900 { font-weight: 900; }
字体大小
您可以选择指定字体大小。
- **
absolute sizes
。**可以使用绝对尺寸:xx-small
、x-small
、small
、medium
、large
、x-large
和xx-large
。指定绝对大小让用户代理决定实际大小。 - **
relative sizes
。**您可以指定larger
或smaller
的字体大小,这将使字体大小比其继承的值大或小一个增量。 length.
你可以使用一个长度值作为字体大小,这将设置字体大小绝对不考虑用户代理。- **
percentage
。**如果你使用一个字体大小的百分比,它将设置相对于其父字体大小的字体大小。
我们将主要关注 Windows 8 应用程序的像素——至少是要出现在屏幕上的元素。请记住,Windows 8 会自动放大以获得更高分辨率的显示器,因此开发人员不需要动态修改字体大小。清单 4-4 和图 4-4 显示了使用中的各种字体大小。
图 4-4 。字体大小的差异不言自明
清单 4-4 。使用 font-size 属性放大或缩小文本
<!-- HTML snippet -->
<div class="pt">Lorem ipsum dolor sit amet</div>
<div class="in">.Lorem ipsum dolor sit amet</div>
<div class="px1">Lorem ipsum dolor sit amet</div>
<div class="px2">Lorem ipsum dolor sit amet</div>
/* CSS snippet */
.pt { font-size: 12pt; }
.in { font-size: .5in; }
.px1 { font-size: 10px; }
.px2 { font-size: 30px; }
行高
与font-size
相似和相关的是line-height
(也称为前导),它控制每行文本上下的空白。line-height
的值也是长度值,两倍于font-size
的line-height
将有效地产生双倍行距文本。您也可以使用百分比值。清单 4-5 和图 4-5 显示了行高示例。
图 4-5 。通过将行高指定为 200%,第二段被赋予双倍行距
清单 4-5 。使用 line-height 属性设置一行文本的垂直间距
<!-- HTML snippet -->
<div>Lorem ipsum dolor sit amet...</div>
<div class="doubleHeight">Lorem ipsum dolor sit amet...</div>
/* CSS snippet */
.doubleHeight { line-height:200%; }
字体系列
font-family
的值决定了使用哪种字体来呈现目标元素的文本。这是一个逗号分隔的系统字体列表,通常被称为字体堆栈。用户代理将继续尝试应用字体堆栈中的字体,直到成功找到用户系统上实际安装的字体。
除了实际的字体名称,您还可以指定五个通用字体关键字中的任意一个:serif
、sans-serif
、monospace
、cursive
、fantasy
。如果用户代理找到了字体堆栈中的通用字体,它将从安装在设备上的通用类型中选择一种字体。一些样本字体系列值在列表 4-6 和图 4-6 中说明。
图 4-6 。呈现系统上可用的第一种字体。请注意 serif 和 sans-serif 后退,并注意最后一种字体“垃圾”在系统中找不到,因此使用默认字体
清单 4-6 。使用 font-family 属性选择字体
<!-- HTML snippet -->
<div class="f1">Lorem ipsum dolor sit amet</div>
<div class="f2">Consectetur adipiscing elit</div>
<div class="f3">Maecenas scelerisque tempor tincidunt</div>
<div class="f4">Aliquam fringilla</div>
<div class="f5">Aliquet tincidunt donec lacinia</div>
/* CSS snippet */
.f1 { font-family: arial, sans-serif; }
.f2 { font-family: 'times new roman', serif; }
.f3 { font-family: trebuchet, helvetica, sans-serif; }
.f4 { font-family: wingdings; }
.f5 { font-family: garbage; }
字体速记属性
所有上述字体相关属性都可以封装在字体速记属性中。font 属性需要很多值,所以语法正确很重要。最重要的是它们以正确的顺序提供。
提供属性的顺序是:font-style
、font-variant
、font-weight
、font-size
、line-height
,然后是font-family
。不过也有一些警告。
font-style
、font-variant
和font-weight
是可选的,如果它们顺序不对也可以工作,但是它们必须在font-size
和font-family
之前。font-size
和line-height
应该用斜线(/)而不是空格分隔。line-height
是可选的,显然,如果你不包含斜线,就不应该包含它。font-size
和font-family
是强制性的。没有任何一项,整行都将被忽略。
清单 4-7 展示了几个字体速记属性值,图 4-7 展示了结果。
图 4-7 。如果属性值的顺序正确,它们都将生效
清单 4-7 。使用字体速记属性一次设置多个字体属性
<!-- HTML snippet -->
<div class="f1">Lorem ipsum dolor sit amet</div>
<div class="f2">Consectetur adipiscing elit</div>
/* CSS snippet */
.f1 { font: bold 36pt trebuchet; }
.f2 { font: italic small-caps bold 24pt/48pt 'times new roman'; }
文本转换
属性用来控制文本的大小写。capitalize
值将每个单词的第一个字母大写,uppercase
值将整个单词大写,lowercase
值将所有字符转换成小写。文本转换属性在清单 4-8 和图 4-8 中进行了说明。
图 4-8 。第一行被转换为小写,第二行被转换为大写,第三行被转换为大写,每个单词的第一个字母大写
清单 4-8 。使用 text-transform 属性更改文本的大小写
<!-- HTML snippet -->
<div class="lowerCase">LOREM IPSUM DOLOR SIT AMET</div>
<div class="upperCase">lorem ipsum dolor sit amet</div>
<div class="capitalize">lorem ipsum dolor sit amet</div>
/* CSS snippet */
.lowerCase { text-transform: lowercase; }
.upperCase { text-transform: uppercase; }
.capitalize { text-transform: capitalize; }
**全部大写!**你会注意到微软在 Windows 8 的很多地方都选择了全大写——菜单就是其中之一。与人们的设想相反,使用全部大写是降低文本相对重要性的有效方法。人类的大脑被训练来阅读小写或标题大小写的文本,但是大写的文本在视觉上更像是一种补充元素,更倾向于被引用而不是被阅读。请记住,这并不适用于全大写的段落文本。大写的段落文字会吸引读者的注意力,但方式不恰当。微软风格手册上说“不要全部用大写来强调”。用句子结构来强调。最好避免为了强调而格式化,但是如果一定要为了强调而使用格式化,那就用斜体格式,不要全大写。”(微软出版社,2012 年)
文本装饰
您可以使用text-decoration
属性更改出现在文本上方、下方和中间的线条。实际上,CSS3 调用了对text-decoration
属性的扩展,以允许伴随文本的线条的颜色和样式。新标准将text-decoration
属性本身变成了text-decoration-line
、-color
和-style
的简写属性。不幸的是,在撰写本文时,这个新标准还没有被任何现代浏览器实现。这包括支持 Internet Explorer 10 和 Windows 8 应用程序的 Trident 引擎。
在标准实现之前,只需使用值为overline
、line-through
或underline
的text-decoration
属性,在文本之上、之中或之下添加分数,如清单 4-9 和图 4-9 所示。
图 4-9 。导致文本上方、中间和下方出现线条
清单 4-9 。设置为上划线、划线和下划线的文本装饰值
<!-- HTML snippet -->
<div id="style1">Lorem ipsum dolor sit amet</div>
<div id="style2">Consectetur adipiscing elit</div>
<div id="style3">Maecenas scelerisque tempor tincidunt</div>
/* CSS snippet */
#style1 { text-decoration: overline; }
#style2 { text-decoration: line-through; }
#style3 { text-decoration: underline; }
字体-面
我们已经讨论了如何指定颜色、大小,甚至字体系列,但是有一个相当明显的警告。如果你指定了font-family: pickle;
,那么用户必须在他的机器上安装 pickle 字体才能正确看到它。
无论你的目标是网络还是 Windows 8,这都是一个重大问题。有几个字体,你可以很好地打赌,将在您的用户系统,但没有一个可以保证。你可以使用通用的字体类型,但是这并不能保证你的排版看起来和你设计的一样。你需要的是确定用户能够通过提供字体来查看你的页面。这就是@font-face
的用武之地。@font-face
是自定义字体定义。@
语法表明它不是一个属性或值,而是一个特殊的 CSS 实体,很像@media
关键字。
@font-face
关键字允许我们定义自定义字体名称和字体源的 URL。很可能你的字体会出现在你的项目中,我建议你按照惯例把你的字体放到一个名为type
的文件夹中。在这种情况下,您可以简单地提供一个根级别的 URL,如/type/myfont.ttf
。
清单 4-10 展示了一个简单的@font-face
定义以及该字体在 HTML 中的实现。注意,font-family
值在@font-face
块中定义,然后在.nifty
样式规则中引用。这个名称是您自己选择的,但是引用必须与定义相匹配。
清单 4-10 。引用存储在项目类型文件夹中的字体文件的字体定义
<!-- HTML snippet -->
<span class="nifty">This is my nifty font!</span>
/* CSS snippet */
@font-face {
font-family: "niftyfont";
src: url("/type/nifty_n.woff") format(woff)
}
.nifty {
font-family: niftyfont;
}
你可以在src
属性中指定多个值来创建一个兼容性堆栈,但是当你在 Windows 8 应用上工作时,你的优势是不必担心其他浏览器作为目标。示例中的格式是 WOFF,但是您可能没有使用过这种字体格式。
WOFF (Web 开放字体格式)是由 Opera、微软和 Mozilla 共同提出的开放格式标准。WOFF 格式实际上不是一种新的字体格式,而只是现有的 EOT,TTF,OTF 字体的包装。包装 WOFF 的现有字体以用于您的应用程序有几个强大的优势:
- WOFF 被压缩,因此换行字体比其相关的原始字体小。
- 元数据可以包含在字体包中,以传递关于字体来源的信息,甚至是它的许可信息。
不过,无论你使用传统字体还是 WOFF 字体,如果你希望你的应用程序具有可访问性、适应性和可搜索性,添加良好的排版是一个好主意,定义字体(而不是仅仅在位图中嵌入你的自定义类型)是一个好主意。
Microsoft 供应商特定的文本属性
微软提供了一些供应商特定的、文本相关的 CSS 属性,即:-ms-text-autospace
、-ms-text-align-last
、-ms-text-justify
、-ms-text-kashida-space
、-ms-text-overflow
和-ms-text-underline-position
。这些属性不会被广泛使用,但在某些情况下,它们实际上是至关重要的。
属性允许处理表意文字——传达思想的亚洲字符——周围的间距。
属性决定了如何处理一个段落的最后一行的间距。
属性控制 kashida 间距,这是阿拉伯书写系统中某些字符的扩展。
最后,-ms-text-underline-position
属性可以决定文本的下划线(如果应用的话)是显示在字符的下面还是上面。值为above
和below
,默认为auto
。
对齐和对齐
对齐是文本布局的一个重要部分。对齐方式控制渲染引擎处理文本前后左右空间的方式。很可能,每个人都有在文字处理器中左对齐、居中、右对齐和对齐文本的经验。这正是text-align
属性的工作。
您可以将text-align
属性设置为left
、right
、center
或justify
的值。
除了设置文本的水平对齐,你还可以做很多事情来控制它的垂直布局。vertical-align
属性取值如下:auto
、baseline
、sub
、super
、top
、middle
、bottom
、text-top
、text-bottom
。默认值baseline
将文本行的底部(不包括下行)与其父行的基线对齐。vertical-align
属性也将接受一个长度或百分比值作为偏移量。
vertical-align
属性并不总是如您所料。事实上,根据它所应用到的元素的类型,它的行为略有不同。
当您在图像标签上使用vertical-align
时,它的行为类似于旧的valign
属性,并确定图像相对于包含它的文本的位置。
当您在表格的单元格中使用vertical-align
属性时,它会影响单元格中文本(或其他元素)的垂直对齐,如清单 4-11 中的所示。
图 4-10 。单元格文本按照定义正确垂直对齐
清单 4-11 。简单表格中的垂直对齐
<!-- HTML snippet -->
<table>
<tr>
<td colspan="3">I'm a table</td>
</tr>
<tr>
<td>top</td>
<td>middle</td>
<td>bottom</td>
</tr>
</table>
/* CSS snippet */
table { width: 300px; border-collapse:collapse; }
table tr:nth-of-type(2) { height: 80px; }
table td { border: 1px solid; }
table tr:nth-of-type(2) td:nth-of-type(1) { vertical-align: top; }
table tr:nth-of-type(2) td:nth-of-type(2) { vertical-align: middle; }
table tr:nth-of-type(2) td:nth-of-type(3) { vertical-align: bottom; }
关于清单 4-11,我想指出一些与主题无关的事情:
- 边界-崩溃:崩溃;属性用于移除表中单元格之间固有的间距
- n-of-type()选择器用于根据位置选择表格行和单元格
在图 4-10 的表格单元格中,可以看到文本已经垂直居中。
然而,当你试图在div
中使用vertical-align
时,你可能会大吃一惊。注意在清单 4-12 中,我们是如何试图指示被称为va
的div
将其文本水平居中和垂直居中对齐的。
图 4-11。我们提供的文本没有垂直居中
清单 4-12 。关于使用垂直对齐的一个常见错误
<!-- HTML snippet -->
<div id="va">
middle?
</div>
/* CSS snippet */
div#va {
height: 100px;
width: 200px;
vertical-align: middle;
text-align: center;
border: 1px solid black;
}
它在水平方向上到达了中间,但在垂直方向上显然不在中间。为什么这个属性被忽略了?属性不只是在 CSS 中奇怪地实现。对于表格单元格,它实际上是垂直对齐的,但是如果我们的 div 包含行内元素(行内元素像文本一样流动并换行),那么vertical-align
会做一些完全不同的事情。它相当于旧的valign
HTML 属性,调整元素相对于基线的垂直位置。这丝毫不会影响它们在父容器中的位置。
这个问题似乎已经困扰网页设计师几十年了,我知道这也是我自己一些不眠之夜的原因。网页从来没有真正被设计来指定垂直行为。HTML 的本质是水平伸缩,内容从上到下垂直流动。这些标准已经发展并取得了进步,但是仍然存在过去的残余。
有一些变通方法可以帮助解决这个问题,但是没有一个是好的,这就是为什么微软 CSS3 实现中的新网格非常受欢迎。第六章将带您深入了解网格的实现,以解决这个重大问题。
vertical-align
的另一个重要用途是将文本设置为上标或下标。sub
和super
值将为您执行此校准。您经常会在span
元素中找到这个。例如,下面可以用来构造等式y = x
2
。
<div>y = x<span style="vertical-align:super;">2</span></div>
列
许多现代 HTML 应用和网站严重依赖大量文本,CSS3 通过引入多栏文本管理将这些应用带入了可行性领域。对多列的支持也不仅仅是微弱的支持。它功能强大,功能齐全。
在引入多栏之前,开发人员被迫手动或以编程方式布置栏。新的多列 CSS 属性真的让任何类型的阅读器应用程序不仅成为可能,而且富有表现力和趣味性。
多列支持对 Windows 8 来说尤其重要,因为设计语言是水平布局而不是垂直布局。经常听到有人质疑这是为什么,那么下面是几个原因。。。
- 首先,水平平移是独特的,是差异化的。这是 Windows 8 重塑用户体验的另一种方式,也是它在竞争中脱颖而出的另一种方式。
- 世界上大多数语言都是从左向右阅读的,因此从左向右平移对人类来说是很自然的。
- 大量文本水平排列的应用程序读起来就像一本杂志,新内容从右边显示出来。这再次使它成为一个熟悉的范例。
- 人体手臂和手的解剖结构水平移动比垂直移动更容易。试着左右滑动,然后上下滑动,你就会看到了。
- 最后,屏幕传统上是横向的,随着屏幕纵横比从 4:3 变为 16:9,屏幕变得更加夸张。
对于垂直布局,完全有可能有一个与屏幕宽度相同的列,但对于从右侧显示新内容的水平布局,列就成了必需的。
请注意,从垂直滚动改为水平滚动的一个含义是,文本将不再逐行显示,而是逐列显示(图 4-12 )。在第六章中,我们将学习捕捉点。对齐点有助于让用户停留在文本的每一列。其结果很像翻页——电子书阅读器已经使用了多年,纸质书已经使用了几个世纪。
图 4-12 。垂直文本布局与水平文本布局
垂直滚动和水平滚动之间的差异相当于布局的巨大变化。查看图 4-13 和图 4-14 以查看每个版面中相同内容的示例——一篇关于巴黎的文章。
图 4-13 。使用垂直滚动文本在屏幕底部运行的网络文章
图 4-14 。同一篇文章在一个 Windows 8 应用中水平放置,邀请用户向右平移
列宽和列数
您可以通过选择列计数或列宽将您的文本块转换成多列文本块——只需要设置一个,另一个将被计算出来。如果在 1366 像素宽的设备上设置列数2
,那么列数将按 683 像素计算(减去页边距和装订线的宽度)。当您确切知道要在给定容器中呈现多少列时,请使用列计数。想象一下你的用户将你的文本移动到大屏幕格式。如果你的用户在他们的小屏幕上有两列文本,然后把你的应用程序移到大屏幕上,你还想要两列(现在很宽)的文本吗?可能不会。更有可能的是,您想要设置列宽和,并让屏幕上生成尽可能多的列。看看图 4-15 就明白我的意思了。更大的屏幕需要更多的文本栏。
图 4-15 。设置列宽允许在更大的屏幕上显示更多的列
属性本身是column-width
和column-count
,还有一个简写属性columns
。有趣的是,你很少需要同时使用column-width
和column-count
,所以你可能会在大部分时间或所有时间里只使用一种速记方法。
速记属性叫做columns
。它需要宽度和/或计数。正如我所说的,你可能会选择其中之一,所以通常你的列属性看起来就像清单 4-13 中的那些。
清单 4-13 。确定多列的典型属性
/* CSS snippet */
.columns {
columns: 4;
}
.columns {
columns: 200px;
}
.columns {
columns: 400px;
}
列间距和列规则
column-gap
和column-rule
属性让您可以控制列之间的空间发生了什么。
column-gap
接受一个长度值,并确定列之间的间距。Windows 8 设计指南没有对多列文本之间的间距宽度给出建议,但它建议列表中的列之间的间距为 40 像素,这也是我对文本列的建议。
column-rule
实际上是一个简写的属性,它一次轻松地封装了column-rule-width
、column-rule-style
和column-rule-color
。规则只是分隔文本列的一行。它在美学上是有帮助的,但也可能有点花哨,所以要谨慎使用列规则。当两列文本彼此不相关时,为了清楚起见,在它们之间添加一条规则可能会有所帮助。
列填充
对于列中的文本流动,呈现引擎可以选择两种可能的行为。如果您有三列,但没有足够的文本填满所有三列,引擎可以填充第一和第二列,让第三列变短,或者它可以平衡所有三列中的内容量(垂直)。
属性是你如何控制这些行为中的哪一个被使用。auto
和balance
值的结果行为显示在图 4-16 中。
图 4-16 。自动和平衡列填充的区别
多列样品
我们将会看到许多不同的多栏配置,对于每一个,我们将会使用你在清单 4-14 中看到的相同的 HTML。
清单 4-14 。一个包含五段大小合适的文本的 div
<!-- HTML snippet -->
<div id="columns">
<p>Lorem ipsum dolor sit amet ... </p>
<p>Sed rhoncus, erat in eleifend ... </p>
<p>Nam mollis iaculis neque ut ... </p>
<p>In eleifend purus et leo ... </p>
<p>Sed quis sapien vitae elit ... </p>
</div>
ID 为 columns 的div
包含五段文本。为了简洁起见,我对实际的段落文本进行了裁剪,但实际上每个段落都是典型的段落大小。让我们看看一些可能的 CSS 样式规则,以各种方式将这五个段落格式化成列。
列表 4-15 和图 4-17 显示了自动列填充的结果。另一方面,清单 4-16 和图 4-18 展示了平衡的列填充。
图 4-17 。两个 400 像素的列适合,列填充的自动值导致每个列在溢出到下一列之前被填充到底部
图 4-18 。三列适合空间,文本溢出,以便所有具有相同数量的文本
清单 4-15 。列宽度为 400 像素,自动填充列
/* CSS snippet */
#columns {
columns: 400px;
column-fill: auto;
height: 600px;
}
让我们看看,当我们有多列时,我们可以做些什么来垂直平衡文本。
清单 4-16 。三列,列填充值为 balance
/* CSS snippet */
#columns {
columns: 3;
column-fill: balance;
height: 600px;
}
某些类型的内容适合窄栏。我可以想象一个类似字典的东西,它主要是一系列简短的内容。当您考虑您的设计时,您可能会发现一些列间距和列之间的一些规则会有所帮助。清单 4-17 展示了一些窄列,列之间有一点间隙和浅灰色的标尺。
图 4-19。有规则的窄栏看起来很优雅
清单 4-17 。尽可能多的 80 像素列,以适合 40 像素的间隙和其间的浅灰色嵌线
/* columns.css */
#columns {
columns: 80px;
column-gap: 40px;
column-rule: 1px solid #ddd;
}
孤儿寡母当个别单词或行滞留在一列的开头或结尾时,它们往往会显得格格不入,而且是无意的。我们称这些人为寡妇和孤儿。避免寡妇和孤儿使用 CSS3 的唯一方法是在段落元素中添加break-inside:avoid
。这将导致一个段落试图保持在一起,而不是分裂自己的列。这不是一个理想的解决方案,因为它要么全有,要么全无。如果一个段落连一行都放不下,那么整个段落就会跳到下一列,可能会留下一个大洞,看起来比小寡妇还要无意。
列表样式
有两种列表:有序列表和无序列表。有序列表通常用数字或字母标记,无序列表通常用项目符号标记。您可以使用list-style
属性:list-style-type
、list-style-position
、list-style-image
和速记属性list-style
来控制它们。
list-style-type
属性很有趣,因为不管标记是什么,它的值都可以将列表转换成有序列表或无序列表。因此,如果 HTML 指定了一个ul
(无序列表)标签,您可以简单地应用一个list-style-type
,它将呈现为一个有序列表,就像您使用了ol
标签一样。
list-style-type
属性的有效值为:none
、circle
、disc
、square
、Armenian
、decimal
、decimal-leading-zero
、Georgian
、lower-alpha
、lower-greek
、lower-latin
、lower-roman
、upper-alpha
、upper-latin
和upper-roman
。
当您试图让列表正确对齐时,list-style-position
属性会非常方便。值outside
确定项目符号在文本之外,并且换行文本缩进,因此项目符号保持悬挂在左侧。另一方面,inside
的值确定项目符号在文本内,并且换行文本与项目符号对齐。
属性允许你指定一个自定义的图片用于你的列表的项目符号。该值应该采用url('folder/image.png')
的形式。
清单 4-18 和图 4-20 展示了一个没有应用 CSS 修改的标准无序水果列表。
图 4-20 。创建简单的项目符号列表并不令人惊讶
清单 4-18 。没有应用样式的标准无序列表
<!-- HTML snippet -->
<ul>
<li>lorem</li>
<li>ipsum</li>
<li>dolor</li>
<li>sit amet</li>
<li>tempor</li>
</ul>
清单 4-19 向列表中添加了一些样式,将无序列表(通常使用项目符号)转换成有序列表(使用十进制数字),并确保数字在列表中。我将列表宽度限制为 200 像素,并重复了单词 mangoes,只是为了说明这个list-style-position
属性。你可以在图 4-21 中看到结果。
图 4-21 。即使标记将其定义为无序列表,也会创建有序列表(编号值为 1–5)。此外,请注意第 5 项一直换行到数字级别的方式
清单 4-19 。标准无序列表现在应用了样式
<!-- HTML snippet -->
<ul>
<li>lorem</li>
<li>ipsum</li>
<li>dolor</li>
<li>sit amet</li>
<li>Maecenas scelerisque tempor tincidunt</li>
</ul>
/* CSS snippet */
ul {
list-style-type: decimal;
list-style-position: inside;
width: 200px;
}
使用 CSS 来设计列表的样式是非常容易的,所以列表是一种很好的、语义化的方式来指示 UI 中任何重复的项目或实体列表。例如,您可以将一个项目列表转换成一个列表、一个菜单或一堆小块。
用连字符号连接
断字是在文本块换行时断开单词,以提高对齐效果。如果渲染引擎被迫将整个单词放在一起,它可能会在文本列中造成一些令人尴尬的大范围空白。但是,如果允许引擎在中间断开一个单词,并在下一行继续,并用连字符表示这一点,那么它可以对文本的换行进行更多的控制。
直到最近,网页中还没有断字。CSS3 已经定义了连字符属性,但是还没有被很多浏览器实现。IE10 和 Windows 8 实际上不识别标准的hyphens
属性,但是它们也支持同一属性的供应商特定版本。除了特定于供应商的前缀之外,语法也是一样的。然后,属性是-ms-hyphens.
。像所有其他供应商特定的属性和属性值一样,微软致力于 CSS 标准,并且微软将通过去掉供应商前缀尽快切换到标准属性。今天你使用-ms-hyphens
,但最终,你只会使用hyphens
。
-连字符
指示一个文本块进行断字非常简单。清单 4-20 用值为auto
的单个-ms-hyphens
属性实现了这一点。-ms-hyphens
属性可以有三个有效值之一(除了inherit
): none
、auto
和manual
。一个none
值显然不允许任何断字操作。manual
值将只允许在内容中明确建议了断点的地方使用断字符-通过出现硬连字符()或软连字符(­
)来指示。软连字符表示单词可以在给定点断开,但是除非必须断开,否则连字符不会出现。另一方面,一个auto
值将允许渲染引擎在那些建议的点以及没有建议的单词中间中断。
图 4-22。连字符用于减少文本右边距的锯齿
清单 4-20 。使用-ms-hyphens: auto 打开断字功能
<!-- HTML snippet -->
<p>Lorem ipsum dolor sit amet...</p>
/* CSS snippet */
p {
width: 500px;
-ms-hyphens: auto;
}
在大多数情况下,这就是你所需要做的,但是如果你需要对断字的呈现方式有更多的控制,那么你需要查看其他属性。
-ms-连字符-限制-区域
属性决定了行尾可以保留的最小空白量。如果你指定了一个区域50px
,并且在对齐发生之前,在一行中将会有超过 50 个像素的空白,那么下一行的单词将会被连字符连接并向上拉以填充其中的一些空间。数字越小,允许的空白就越少,因此需要更多的连字符。如果区域太大,则根本不会出现断字。
如果清单 4-21 和图 4-23 中的 CSS 被应用于清单 4-20 中的同一个 HTML,那么我们将以一个连字符行结束——以 adipis 结尾的那一行。如果单词ADI pissing的那一部分没有被提取出来并使用连字符连接,那么单词 dignissim 后面的空格将会超过 50 个像素。
图 4-23 。如果将此图与图 4-22 进行比较,可以看出连字符的行为受到了影响
清单 4-21 。用-ms-hyphenate-limit-zone 设置断字区
/* CSS snippet */
p {
width: 500px;
-ms-hyphens: auto;
-ms-hyphenate-limit-zone: 50px;
}
-ms-连字符-限制-字符
下一个-ms-hyphenate
属性是-ms-hyphenate-limit-chars
。该属性设置可以断字的单词的最小大小。您可以为所讨论的整个单词指定一个最小大小,为连字符之前的部分指定一个最小大小,为连字符之后的部分指定一个最小大小。这三个值由空格分隔。值5 2 2
将指示带连字符的单词必须至少有 5 个字符,并且在带连字符后,连字符前至少有 2 个字符,连字符后至少有 2 个字符。
您可以使用关键字auto
来代替这三个值中的任何一个。auto 的默认值是5 2 2
,所以如果auto
替换了第一个值,那么它将再次代表一个5
,第二个2
,第三个2
。值8 4 4
将非常保守,仅允许大的单词断开,并且将要求至少 4 个字符保留在一行中,并且至少 4 个字符向下移动到下一行。
清单 4-22 中的 CSS 使用了一个值7 3 3
作为例子,注意在图 4-24 中,单词 sollicitudin 被允许断开,因为它超过了 7 个字符(其中至少有 3 个字符可以保留在连字符之前),但是 Curae 不允许断开,因为它只包含 5 个字符。
图 4-24 。同样,断字行为与前面的示例有所不同
清单 4-22 。设置一个单词必须有多大才能断字和断字
/* CSS snippet */
p {
width: 500px;
-ms-hyphens: auto;
-ms-hyphenate-limit-chars: 7 3 3;
}
-ms-连字符-限制-行
-ms-hyphenate
家族的最后一名成员是-ms-hyphenate-limit-lines
。该属性将确保连续的连字符行不超过指定的数量。在清单 4-23 中,-ms-hyphenate-limit-zone
被设置为3px
,这将导致大量的断字,但是-ms-hyphenate-limit-lines
被设置为2
,这意味着一行中不超过 2 行可以被断字。如果你查看图 4-25 中的结果,你会注意到以 Donec 结尾的行是一个在行尾之前至少有 3 个像素空白的断字候选行,但是前面两行(以 Vestibu- 和 Pel- 结尾)已经被断字,所以它不能被断字。
图 4-25 。-ms-hyphenate-limit-lines 限制了连续连字符的行数,可以防止您的文本看起来过于支离破碎
清单 4-23 。使用-ms-hyphenate-limit-lines 设置允许多少个连续的连字符行
/* CSS snippet */
p {
width: 500px;
-ms-hyphens: auto;
-ms-hyphenate-limit-zone: 3px;
-ms-hyphenate-limit-lines: 2;
}
摘要
在这一章中,我们已经讨论了很多与文本样式相关的内容。我们已经介绍了可以用来定制文本颜色和不透明度的 CSS 属性,影响字体的各种方法,我们还介绍了一些强大的文本布局控件的多列和断字,这对 CSS 世界来说是相当新的。
在你的应用中,清晰、干净、有目的的字体设计的重要性怎么强调都不为过。它是一个重要的工具,可以让 Windows 8 应用程序的设计足够引人注目,让用户喜欢它,与朋友谈论它,并给你的应用程序带来高评分。
五、盒子属性
注意HTML 中的一切都适合一个盒子,知道如何控制这些盒子的格式和布局对于扎实理解 CSS 至关重要。
框属性是 HTML 元素的属性,描述了它的大小、填充、边框和间距等内容。
`我们将研究元素大小和间距,以及使这些元素看起来更好的所有填充和边框颜色,并使它们在视图状态改变时发挥应有的作用。让单一视图工作正常是一回事,但是当用户将设备旋转到纵向时会发生什么呢?如果一个元素的框属性设置不正确,那么整个布局会受到不利影响。我们将在本章中探讨的属性对于让您的 Windows 8 应用达到应有的效果至关重要。图 5-1 展示了一些按照微软设计原则设计的 Windows 8 应用。
图 5-1 。一些根据微软设计原则设计的 Windows 8 应用程序
指导 Windows 8 外观和感觉的设计语言融入了大量的设计、思考和测试。从触摸目标的大小到它们之间的间距,一切都在设计原则中占有一席之地。在图 5-1 中,注意内容上方、下方和左侧的一致空间。请注意,内容没有被压缩在屏幕上,而是被给予了一点喘息的空间。请注意,除了内容本身之外,用于交互或导航的视觉元素非常少。所有这些都是设计语言的一部分,甚至更多。
要实现这些原则,你必须非常依赖于盒子模型和各种布局技术。本章介绍盒子模型,第七章将介绍布局。为了彻底理解盒子模型,你必须理解大小、边距、边框和填充。我们将花更多的时间来覆盖渐变和阴影,因为它们有时可以补充你的核心图形,为你的设计增加价值。
盒子模型
如果您想单独理解边距、边框、填充和背景属性,您必须理解框模型。确保图 5-2 中显示的术语已被记忆。
图 5-2 。HTML/CSS 盒子模型
标记为边距 的空间是该元素与其周围所有东西之间的空间。边框 在这里显示为灰色线条,但它实际上可以是多种样式、颜色和粗细中的任何一种。边框和框内实际内容之间的空间称为填充 。
这里的内容表示为文本,但是请记住,您的内容可能是文本,也可能是更多嵌套为子元素的元素。
我需要定义更多基于这个盒子模型的术语。边框是图表中包括边框区域、填充区域和内容,但不包括边距的区域。填充框是包括填充区域和内容区域(不包括边距和边框)的矩形区域。而内容框就是内容区。一会儿你就会明白为什么这些术语很重要。
尺寸
HTML 容器元素可以在没有指定大小信息的情况下定义,并根据其父元素的大小或其内容的大小做出反应,但您也可以显式声明它们应该是什么大小。在 Windows 8 应用程序中指定大小特别有帮助,因为视觉伪像会出现在各种设备上,一些设备实际上会应用系统级缩放,以保持一致和可触摸的用户体验。换句话说,与现有的 Windows 设计环境不同,像按钮这样的东西不会随着用户分辨率的提高而变小。
大多数 HTML 元素可以指定宽度和高度属性来确定它们的显式大小。除了这个绝对值之外,还可以为每个值指定最小值和最大值。以下是可用属性的列表:width
、min-width
、max-width
、height
、min-height
、max-height
。
最小值和最大值属性对于创建良好的自适应布局非常有帮助。80px
的min-width
值将允许目标元素的宽度增长到大于 80 像素(例如,如果用户正在向元素中键入内容),但不会变窄。
在设置一个元素的宽度和高度之前,一定要问自己是应该使用最小值还是最大值属性。你的元素应该是一个绝对的大小,还是应该能够适应,在某些情况下变得更小或更大?正如我们已经讨论过的,这两个属性的值应该是标准的长度单位。清单 5-1 展示了如何用各种单位来指定元素的大小。
清单 5-1。 一个 div,包含五个宽度不同的子元素
<!-- HTML snippet -->
<div id="parent">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
/* CSS snippet */
#parent { width:200px; border: 1px solid black;}
#parent > div { background:green; height: 20px; margin:2px; color:white; }
#parent div:nth-of-type(1) { width: 10px; }
#parent div:nth-of-type(2) { width: 50%; }
#parent div:nth-of-type(3) { width: 100px; }
#parent div:nth-of-type(4) { width: calc(100% - 10px); }
#parent div:nth-of-type(5) { width: 1in; }
关于清单 5-1 中的,你应该注意一些事情。
- 请注意除了第一行之外的所有行都缩进了。这是前面提到的表示层次结构的约定的一个例子。
- 注意第四个子元素的宽度使用了
calc()
函数来表示宽度应该是“100%差 10 个像素”。 - 注意
:nth-of-type()
伪类的使用。这是按顺序为一系列相似元素定义样式规则的好方法。因为使用了:nth-of-type()
而不是:n-child,所以我们可以稍后在div
元素的序列上方添加一个标题,并且不会对它们的样式产生任何影响。
清单 5-1 产生的 HTML 看起来像图 5-3 。你可以看到彼此之间不同的宽度。
图 5-3 。各种大小的矩形说明了宽度属性
在 CSS3 之前,当设置了对象的宽度和高度时,指定的值会影响内容区域的宽度和高度(参见框模型)。在某些情况下,这可能是一种直观的方法,但也会引起一些恐慌。举个例子,将div
的宽度设置为100%
会导致它采用其父项的宽度,但是添加一些填充和边框会导致它看起来比其父项更宽。所以即使这种测量盒子的方法经常令人沮丧,它仍然是 W3C 标准。
CSS3 还引入了两个增强功能,极大地改善了我们的规模场景。第一个我们已经讨论过了,它是用于指定宽度的calc()
方法 ,比如calc(100% - 20px)
。第二个是box-sizing
房产 。box-sizing
属性取值为border-box
或content-box
(默认)。指定border-box
表示width
和height
应该被转换为整个框的宽度和高度(包括填充和边框),而不仅仅是内容。
让我们看看清单 5-2 中的例子,以确保我们清楚这种行为。
图 5-4。一个具有 50 像素边框的 div,其整体宽度明显超过 200 像素
清单 5-2 。使用默认内容框大小调整方法 的 200 像素框
<!-- HTML snipppet -->
<div id="box"></div>
/* CSS snippet */
#box {
margin: 50px;
padding: 50px;
border: 50px solid gray;
width: 200px;
height: 200px;
}
现在,如果我告诉你,结果框中的边框是 50 像素厚,你会相信整个框是 200 像素宽 200 像素高吗?这似乎意味着更多。使用标准的大小调整方法,内容为 200 像素宽,填充和边框各为 50 像素,将整个框的外观宽度增加到 400 像素!
清单 5-3 重复了相同的 CSS,但是引入了一个新的属性,看看这显著不同的结果。
清单 5-3。 一个 200 像素的盒子使用了边框大小调整方法
<!-- HTML snipppet -->
<div id="box"></div>
/* CSS snippet */
#box {
margin: 50px;
padding: 50px;
border: 50px solid gray;
width: 100px;
height: 100px;
box-sizing: border-box;
}
图 5-5。一个 div 已经通过框大小调整设置了它的大小调整方法,现在看起来真正的整体宽度是 200 像素
溢出
盒子模型及其大小、边距和填充让您可以很好地控制页面上所有容器的形状。页面上这些容器的全部意义在于包含你的应用程序的内容,通常这些内容会太大或太长而不适合。在这种情况下,容器的行为就是我们所说的溢出。
例如,如果一个div
元素的高度足以显示 10 行文本,并且其中有超过 10 行的文本,那么我们就有一些溢出。
您可以使用overflow
属性来控制这种行为。有效值为visible
(该值为默认值)、hidden
、scroll
和auto
。
visible
决定了溢出的内容应该可见。即使它是可见的,也不会影响它可能碰撞到的任何元素的布局。hidden
使任何溢出的内容不可见。scroll
给元素添加滚动条,这样用户可以选择滚动到溢出的内容。- 只有在有理由的情况下才添加滚动条。
overflow
属性实际上是overflow-x
和overflow-y
的简写属性,因此您可以独立地控制容器在两个轴上的行为方式。
清单 5-4 展示了我提到的例子,一个div
的大小可以显示 10 行文本,但包含更多。还没有设置overflow
属性,所以使用默认值visible
,事实上,额外的文本在结果中清晰可见。这种溢出的文本的一个有趣的行为是,它不会将其他内容推来推去,这种行为对您来说可能直观,也可能不直观。包含的div
作为一个块级元素,将后续内容向下推,但是它溢出的文本对页面上其他任何内容的位置没有进一步的影响。
清单 5-4。 一个内容溢出的 div 不指定其溢出
<!-- HTML snippet -->
<div id="container">
<p>Lorem ipsum dolor sit amet ... </p>
</div>
/* CSS snippet */
#container {
height: 220px;
width: 300px;
border: 1px solid gray;
margin: 10px;
padding: 10px;
}
图 5-6。如你所见,默认溢出是可见的
让我们来看看应用了不同的overflow
值的同一个 HTML。在清单 5-5 的中,你可以看到我们可以通过将overflow
属性设置为hidden
来消除这个可见的溢出。
清单 5-5 。溢出值“隐藏”应该会改变行为
<!-- HTML snippet -->
<div id="container">
<p>Lorem ipsum dolor sit amet ... </p>
</div>
/* CSS snippet */
#container {
height: 220px;
width: 300px;
border: 1px solid gray;
margin: 10px;
padding: 10px;
overflow: hidden;
}
图 5-7。溢出的内容现在是隐藏的,但没有办法访问它
不过,这让我们无法查看隐藏的文本。清单 5-6 通过将overflow-y
设置为auto
对此进行了改进,这导致div
保持相同的大小,但是突然具有了滚动的能力。你可能想知道为什么我不选择scroll
值而不是auto
。scroll
值 强制容器总是处于滚动模式,但是auto
值足够智能,只在确实有溢出的内容需要滚动时才呈现滚动条。请注意,在 Windows 8 中,系统会确定用户当前使用的是鼠标还是触摸,并相应地呈现滚动条。当使用鼠标时,用户将看到传统的滚动条,但当使用触摸时,用户将看到更干净、更小的滚动位置指示器,该指示器提供信息,而不必是交互式的。
清单 5-6。 设置溢出为“自动”使内容可滚动
<!-- HTML snippet -->
<div id="container">
<p>Lorem ipsum dolor sit amet ... </p>
</div>
/* CSS snippet */
#container {
height: 220px;
width: 300px;
border: 1px solid gray;
margin: 10px;
padding: 10px;
overflow-y: auto;
}
添加一个属性overflow-y: auto
;会导致容器在其内容溢出时呈现垂直滚动条。图 5-8 说明了这一点,并强调了用户使用鼠标和触摸时滚动条外观的不同。
图 5-8 。滚动条在使用触摸和鼠标时呈现不同
能见度
可以修改元素的可见性来确定该元素是否出现。
有两种不同的样式属性会影响元素的可见性:visibility
和display
。
visibility
属性可以设置为visible
、hidden
或collapse
。默认值是visible
,显然设置了一个元素出现。hidden
值使元素完全不可见。即使一个元素被隐藏,它仍然会影响布局,所以如果你设置它为 100 像素高,那么它仍然会占用 100 像素的垂直空间。最后,collapse
值的工作方式与hidden
值非常相似,除了对于表格的行和列,它还折叠行或列,因此它不会占用空间。
属性可以设置成许多不同的东西,但是大多数与目标元素的布局有关,而不是它的可见性。然而,一个可能的值是none
。将display
设置为none
不仅会隐藏目标元素,还会有效地将它从 DOM 中取出,使其不再影响布局。
jQuery 等一些库提供了一些函数(在 jQuery 中是show()
和hide()
),使得修改这些属性以及显示或隐藏元素变得更加容易。在附录 A 中,我将讨论一些 CSS 相关的库,以及如何在你的 Windows 8 应用中使用它们。
边距
元素的边距是元素外部和周围的空间量。元素是矩形的,每边都有属性,所以我们有以下属性:margin-top
、margin-right
、margin-bottom
和margin-left
。
为了说明边距,让我们创建三个元素,一个在另一个之上,然后对它们应用一些边距来查看效果。清单 5-7 包含了 HTML 和初始 CSS,没有任何与边距相关的样式。
清单 5-7。 一些没有应用边距的 div 元素
<!-- HTML snippet -->
<div id="parent">
<div></div>
<div></div>
<div></div>
</div>
/* CSS snippet */
#parent > div {
width: 200px;
height: 80px;
border: 1px solid black;
}
这三个div
元素被一个接一个地放置,导致图 5-9 中的三个盒子也被一个接一个地放置。
图 5-9 。div 元素相互对接,看起来可能很拥挤
您可以看到div
元素紧挨着彼此。事实上,他们甚至似乎共享同一边界。现在让我们在这些元素之间留出一点空间。要做到这一点,我们可以在每个页面的底部、顶部或两者都增加一些边距。根据 Windows 8 的设计原则,我们应该在磁贴之间留出 10 个像素的空间,让我们在每个元素周围添加 5 个像素的空白。清单 5-8 展示了如何使用 CSS 来完成这个任务。HTML 将与前面的清单相同。
清单 5-8 。一些应用了 5 像素边距 的 div 元素
/* default.css */
#parent > div {
width: 200px;
height: 80px;
border: 1px solid black;
margin: 5px;
}
图 5-10。div 元素之间现在有了一点空间
这就是元素之间 10 个像素的样子。这没什么难的。为了好玩,清单 5-9 给这些元素增加了不同级别的左边距。
清单 5-9 。仍然指定相同的 5 像素边距,现在增加了一些额外的左边距
/* default.css */
#parent > div {
width: 200px;
height: 80px;
border: 1px solid black;
margin: 5px;
}
#parent > div:nth-child(1) {
margin-left: 5px;
}
#parent > div:nth-child(2) {
margin-left: 50px;
}
#parent > div:nth-child(3) {
margin-left: 100px;
}
图 5-11。元素之间的边距仍然可见;额外的左边距也是如此
然而,margin
速记属性使得同时设置这四个属性变得更加容易。简写属性 将采用以下任何一种形式。
- 所有四边的页边距都可以通过依次指定顶部、右侧、底部和左侧页边距来表示,并由空格分隔,如
margin: 10px 8px 7px 2px;
所示 - 水平和垂直对称的页边距可以采用一个值来表示顶部和底部,另一个值表示左侧和右侧,如
margin: 20px 5px;
所示,在这种情况下,顶部和底部页边距将被设置为 20px,左侧和右侧被设置为 5px。 - 最后,四周相同的边距可以取一个值,如
margin: 10px;
所示,这将在四边创建 10px 的空间。
属性对于所有类型的间距都是非常有用的。它用于控制文本块中段落上方或下方的间距,以及列表中图块组之间的间距。它还用于遵循 Windows 8 的设计原则,并在每个视图的左侧添加 120 像素的空间。事实上,为了适应这种左边距,如果你使用导航应用项目模板来创建你的项目,那么每次你创建一个新的页面,你的 CSS 文件看起来就像清单 5-10 中的样式规则。
清单 5-10 。Visual Studio 中新页面控件的默认样式表
/* CSS snippet */
.pageTitle p {
margin-left: 120px;
}
此规则为页面默认获得的“内容在此处”段落设置 120 像素的左边距。我不觉得这有什么帮助,因为我很快替换了股票段落,很少在我的主要部分出现一个标签。因此,通过为我在主要部分(也就是角色为main
的部分)放置的任何东西设置左边距,用下面的规则替换这条规则效果很好,如清单 5-11 所示。
清单 5-11。 更好的设置标准左边距的方式来影响主节中的一切
/* CSS snippet */
.pageTitle section[role=main] > * {
margin-left: 120px;
}
如果你使用网格项目模板创建一个新的 Windows 8 项目,你的应用程序看起来马上就像图 5-12 ,你已经可以看到左边距的特征 120 像素已经被编程到该项目模板中。
图 5-12 。Windows 8 应用程序典型的 120 像素左边距在 grip 项目模板中显而易见。推荐的标准页边距还描述了列表项和组
边框
边框是围绕元素的线条。同样,这次我们得到了一个简写属性border—
,这样我们就不用每次都键入border-width
、border-style
和border-color
了。清单 5-12 展示了如何在div
周围创建一个细的黑色边框。
清单 5-12 。div 周围的细黑边框
/* CSS snippet */
div {
border: 1px solid black;
}
您可以为border-width
使用任何长度单位。border-style
的值有dashed
、dotted
、double
、groove
、hidden
、inset
、none
、outset
、ridge
和solid
。我在第三章中介绍了border-color
可以用无数种方式定义颜色。
清单 5-13 显示了更多的边框属性组合。
清单 5-13 。一些边界属性组合
/* CSS snippet */
.border1 { border: 1px solid red; } /* thin red */
.border2 { border: 8px solid rgb(0,255,0,.5) /* partially transparent, thick, green */
.border3 { border: 3px double black; }
填充
就像margin
决定元素外的空间一样,padding
决定元素内的空间(但在其内容外)。就像margin
属性一样,padding
是一个简写属性,它比每次都使用padding-top
、padding-right
、padding-bottom
和padding-left
更容易,并且设置它的工作方式也与margin
完全相同。
清单 5-14 显示了一个简单的div
,带有黑色边框,包含一段文本。div
的padding
被设置为50px
,你可以在结果中看到这么多填充的效果。
清单 5-14 。50 像素的填充为文本在其边框内提供了一些空间
<!-- default.html -->
<!DOCTYPE html>
<html lang="en" FontName2">http://www.w3.org/1999/xhtml ">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div>
<p>Lorem ipsum dolor sit amet...</p>
</div>
</body>
</html>
/* default.css */
div {
border: 1px solid black;
padding: 50px;
width:50%;
}
图 5-13。在一段文字周围增加了一些夸张的呼吸空间
背景
当您想要用颜色或图像影响元素的背景时,可以使用背景属性。分别是background-color
、background-image
、background-size
、background-repeat
、background-position-x
、background-position-y
、background-origin
、background-clip
、background-attachment
。
背景属性可用作背景图像、背景重复和背景颜色的速记属性,背景位置可用作背景属性 x 和背景属性 y 的速记属性。
背景色
您可以使用我们讨论过的所有标准颜色属性值来设置颜色。如果你回头看看我们讨论过的盒子模型,background-color
(以及background-image
)将填充内容、填充和边界区域。它呈现在内容、填充和边框之后。如果你设置你的边框有点透明,你会看到背景显示通过。
背景图像
background-image
的值应该是到一个或多个图像的绝对或相对链接,每个都用url(
“)
包裹,并用逗号分隔。包含多个图像会导致图像堆叠在一起,首先声明的那些图像会放在最上面。
清单 5-15 展示了一个 Windows 8 徽标被用作div
元素后的背景图像的例子。
清单 5-15 。指定为 div 背景图像的图像(Windows 8 徽标)
<!—HTML snippet -->
<div id="container"></div>
/* CSS snippet */
div#container {
width:600px;
height:400px;
border:1px solid gray;
background-image: urlimg/win8logo.png');
}
图 5-14 。图像出现在 div 元素的背景中,但是您可以看出它太大了
在图 5-14 的中,我们设置为 dev 元素背景的 Windows 8 logo 需要调整大小以适合 div,这个工作属于background-size
属性。
background-size
background-size
属性值可以是一对代表宽度和高度的长度或百分比。可以使用关键字auto
代替宽度或高度值,让长度值根据图像的长宽比和其他维度来确定,为宽度和高度指定auto
等同于根本不设置该属性。
除了明确指定背景图像的大小之外,cover
或contain
值可以用来以一种巧妙而有用的方式调整图像的大小。cover
值缩小图像以完全适合容器,contain
值放大图像以适合容器。在这两种情况下,都会调整图像的大小,但会保持其纵横比。
如果存在一个以上的背景图像,那么大小对它们的影响是一样的。让我们使用清单 5-16 中的这个属性来调整我们的 Windows 8 徽标的大小,以更好地适应我们的div
元素。
清单 5-16 。添加了一个背景大小属性来控制背景图像的大小
<!—HTML snippet -->
<div id="container"></div>
/* CSS snippet */
div#container {
width:600px;
height:400px;
border:1px solid gray;
background-image: urlimg/win8logo.png");
background-size: auto 100px;
}
图 5-15 显示了添加background-size
属性的效果。
图 5-15 。背景图像的大小已经被适当地调整了,但是这并不是我们想要的效果
图 5-15 中的图像是我们指定的 100 像素高,但是它重复并平铺整个背景。这是背景图像的默认行为,要覆盖它,我们需要使用background-repeat
属性。
提示cover
和contain
值提供的使背景图像适合其容器的功能在一个名为 ViewBox 的 WinJS 控件中扩展。视图框影响任何单个元素,即使该元素包含复杂的内容层次结构。这是一个非常强大的工具,可以根据当前屏幕的大小和形状动态调整内容。你会在第七章中读到更多关于视图框控件的内容。
背景-重复
默认情况下重复背景是有意义的,考虑到它们最初和主要的意图是用连续的图像贴墙纸。然而,这种行为是非常可定制的。属性提供了一些非常巧妙的功能。可以取值为no-repeat
、repeat
、repeat-x
、repeat-y
、round
或space
。
默认值是repeat
,要完全关闭该行为,可以使用no-repeat
。如果你想让图像只在 x 方向重复,那么使用repeat-x
,同样使用repeat-y
。round
值实际上会在两个方向上重复图像,但如果元素大小不是大小的整数倍,则不允许裁剪。适合的图像随后被放大以适合元素。space
值与此类似,但它不是放大结果图像,而是在它们之间添加空间来填充空间。
清单 5-17。 添加一个背景重复属性,其值为不重复
<!—HTML snippet -->
<div id="container"></div>
/* CSS snippet */
div#container {
width:600px;
height:400px;
border:1px solid gray;
background-image: urlimg/win8logo.png');
background-size: auto 100px;
background-repeat: no-repeat;
}
图 5-16。背景图像不再重复
背景-位置
CSS 还让我们可以控制背景图像应该呈现在包含元素中的什么位置。如果您关闭了重复,并且只有一个图像,那么您可以使用带有类似于left top
、right center
或center bottom
的值组合的background-position
属性。您也可以使用一对长度单位或百分比来分别表示 x 和 y 方向上的位置。
使用这种技术来设置一个相对暗淡的图像,使其出现在视图的右下角,这是一个添加你的品牌的好方法。无论用户如何滚动内容,图像都将保留在那个角落。
清单 5-18 将background-position
属性添加到我们的容器中。
清单 5-18 。添加一个值为“不重复”的背景重复属性
<!—HTML snippet -->
<div id="container"></div>
/* CSS snippet */
div#container {
width:600px;
height:400px;
border:1px solid gray;
background-image: urlimg/win8logo.png');
background-size: auto 100px;
background-repeat: no-repeat;
background-position: center center;
}
你在图 5-17 中看到的结果开始看起来像是我们想要做的事情!
图 5-17 。背景图像水平和垂直居中
在这里,我们选择了使用关键字center
将图像居中,但是我们也可以使用类似于background-position: 100px 100px
的东西将图像绝对放置,这样就可以将 logo 设置为距离容器顶部和左侧 100 个像素。
背景-原点
background-origin
用于确定background-position
坐标的起点。默认值是padding-box
,因此0% 0%
的background-position
或0px 0px
或left top
将意味着背景图像从填充的顶部和左侧开始对齐(即使默认情况下背景图像实际上也延伸到边框之下)。
background-clip
我前面提到过元素的背景会影响内容下面的区域、填充和边框,但是background-clip
属性给了我们一点控制权。该属性取值与background-origin
: border-box
,padding-box
,content-box
相同。省略它将意味着它使用其默认值border-box
。裁剪到边框意味着背景位于内容、填充和边框下的整个区域之下。然而,将background-clip
属性设置为值padding-box
将有效地剪切边框下的部分,这样背景仅在填充和内容下可见。最后,content-box
的值甚至会将它裁剪到填充区内,使它仅位于内容下方。
图 5-18。背景图像被剪切到盒子模型的特定区域
背景-附件
属性决定了当前景内容滚动时背景图像的行为。
值fixed
将背景图像附加到视口(通常是整个窗口),其效果是将其固定在页面上。
值scroll
将背景图像附加到文档上,因此如果正文的全部内容溢出页面并强制滚动,那么背景图像将随之滚动。
CSS3 中引入了第三个值local
,它将元素的背景图像附加到该元素的内容中。只有引入这个值,我们才能够用滚动的内容来滚动背景图像div
。
作为一个例子,请看清单 5-19 。一个包含三个相当大的文本段落的div
被分配了一个 CSS 样式规则,除了别的以外,该规则将它设置为在其中心呈现一个小的背景图像。overflow-y
使它可以滚动,但是我们很快会讨论这个属性。需要注意的属性是local
的background-attachment
。这将导致背景图像与其余内容一起滚动,正如您在结果中看到的那样。
清单 5-19 。local 的背景附件值用于将背景图像粘贴到它所在的滚动容器中
<!—HTML snippet -->
<div>
<p>Lorem ipsum dolor sit amet... </p>
<p>Sed rhoncus, erat in eleifend... </p>
<p>Nam mollis iaculis neque ut... </p>
<p>In eleifend purus et leo... </p>
<p>Sed quis sapien vitae elit... </p>
</div>
/* CSS snippet */
div {
padding: 10px;
border: 1px solid gray;
width: 500px;
height: 500px;
background: urlimg/win8logo.png') no-repeat;
background-position: center center;
background-attachment: local;
background-size: 80px 80px;
overflow-y: scroll;
}
将这个属性添加到我们的目标元素实际上将背景图像固定到包含元素的滚动部分。
图 5-19。带有本地附加背景图像的可滚动 div 将滚动图像及其内容
渐变
如果你有 web 开发的背景,你会非常清楚如何给文档的宽度或高度添加颜色渐变。我所指的 hack 是一个包含所需梯度的图像,在垂直于梯度的方向上只有一个像素。然后,该图像被设置为背景图像,并允许在页面上重复显示。它可以工作,但是不够优雅,而且有一些缺点。我想到的一种情况是,用户滚动到渐变的边缘,或者升级到更高分辨率的屏幕,然后出现渐变的突变边缘。这让网页设计师很尴尬,但是随着 CSS3 渐变的出现,这个问题已经解决了。
我想在这里加入一个软警告,不要不加考虑地使用渐变。渐变是有帮助的,但是微妙是关键。多余的图形工件通常会违反微软的设计原则,即使用颜色和形状作为信息,而不仅仅是为了吸引眼球。也就是说,在某些情况下,微妙的渐变背景可能正好合适。
渐变是在background-image
属性中实现的,使用linear-gradient()
函数实现线性渐变,或者使用radial-gradient()
函数实现径向渐变。
linear-gradient()
函数 接受渐变方向,然后至少两个颜色停止。清单 5-20 显示了从左到右从黑到白的渐变。
清单 5-20 。定义为 div 背景的线性渐变
<!-- HTML snippet -->
<div class="gradient"></div>
/* CSS snippet */
.gradient {
width:400px;
height:400px;
background-image: linear-gradient(to right, black 0%, white 100%)
}
图 5-20。平滑渐变 由黑变白
添加色标也很容易。清单 5-21 每 20%黑白交替一次。
清单 5-21 。带有交替色标的线性渐变
<!-- HTML snippet -->
<div class="gradient"></div>
/* CSS snippet */
.gradient {
width:400px;
height:400px;
background-image: linear-gradient(to right, black 0%, white 20%, black 40%,
white 60%, black 80%, white 100%);
}
图 5-21。更复杂的线性渐变
指示方向的第一个参数可以接受一个边(left
、right
、top
、bottom
)、一个角(top left
、top right
、bottom left
、bottom right
),或者像45deg
或320deg
这样的自定义度数。
你可以在微软的网站上找到更多关于线性渐变实现的信息。
创建径向渐变的函数有点复杂,我只展示一个例子,并再次鼓励你在http://msdn.microsoft.com/en-us/library/windows/apps/hh453718(v=vs.85).aspx
访问微软关于这个主题的文档,当你准备好自己实现它的时候。清单 5-22 将创建一个渐变,从中间的黑色开始,以白色向外辐射到最远的角落。
清单 5-22 。从中心到最远角的径向渐变
<!-- HTML snippet -->
<div class="gradient"></div>
/* CSS snippet */
.gradient {
width:400px;
height:400px;
background-image: radial-gradient(circle at 50% 50%, black 0%, white 100%);
}
图 5-22。从中间的黑色到外部的白色的径向渐变
影子
多年来,网页设计者想出了各种各样的技巧来创建阴影,因为直到现在,标准中还没有相关的规定。现在实现投影很容易,但更好的是它是标准的。
我会像对待渐变一样,对阴影的使用发出同样的警告。这是一种视觉装饰。阴影是一种 skeuemorphic 人工制品,因为它试图使你的应用程序中的一些元素看起来像在现实世界中一样。但这并不在现实世界中,不是吗?这是在数字世界中,Windows 8 的设计原则建议我们将我们的应用程序设计成真正的数字,而不要考虑现实世界效果可能带来的所有依赖和限制。
推荐与否,框阴影非常容易实现。清单 5-23 显示了一个带有简单阴影的小白框。这些值表示水平偏移、垂直偏移、模糊半径、扩散距离和阴影颜色。
清单 5-23 。div 元素上的方框阴影定义
<!-- HTML snippet -->
<div class="shadow"></div>
/* CSS snippet */
.shadow {
width: 100px;
height: 100px;
background-color: white;
border: 1px solid black;
box-shadow: 10px 10px 10px 0px hsla(0,0%,0%,.5);
}
图 5-23。白色方框 下的简单方框阴影
关于阴影的一个有趣的事情是,它们不仅仅可以用来创造阴影。清单 5-24 显示了两个例子。在第一个示例中,添加了一个没有水平或垂直偏移的阴影来创建发光效果。在第二个例子中,一个实心的阴影被用来明显地将盒子向外延伸,并且在一个虚线的边框之下,使得元素看起来像是在它的周围缝了针。
清单 5-24 。框阴影属性 的两种可选用法
<!-- HTML snippet -->
<div class="flex">
<div class="glowBox"></div>
<div class="stitches"></div>
</div>
/* CSS snippet */
.flex {
display:-ms-flexbox;
-ms-flex-pack:distribute;
-ms-flex-align:center;
height:200px;
width:600px;
}
.glowBox {
border:1px solid gray;
width:100px;
height:100px;
box-shadow: 0px 0px 40px 10px hsla(0,0%,0%,.5);
}
.stitches {
background-color: lightgray;
border:2px dashed black;
box-shadow: 0 0 0 4px lightgray;
color: black;
padding: 10px;
border-radius: 4px;
width:100px;
height:100px;
}
图 5-24。两个 div 元素——一个发光,另一个明显是缝合在一起的
摘要
在这一章中,我们已经了解了影响任何 HTML 元素的矩形模型的所有属性(我们称之为box)。我们定义影响大小(宽度和高度)、边距(外部空间)、边框、填充(内部空间)等的 CSS 属性。我们学习了设置内容的宽度和高度的相对值或绝对值,以确定其呈现的大小。我们还学习了如何处理对于它们的空间来说太大和溢出的元素内容。我们学习了单独或一起定义元素的左、右、上、下边距。我们学习了如何使用线条样式、大小和颜色来确定元素的边框。我们学习了如何定义填充,让内容在框架内有一点喘息的空间。
我们还研究了元素中的背景设置,可以是纯色、图像,甚至是线性或径向渐变。最后,我们学习了盒子阴影,并使用它们给我们的元素一些明显的深度和一点点创造性的兴趣。在理解后续概念之前,理解这些概念是很重要的,尤其是第七章中的高级布局概念。
现在我们对盒子属性有了基本的了解,我们将继续元素的转换和动画。我们不是确定元素的静态外观,而是确定它们的过渡和动画,真正让我们的 Windows 8 应用变得生动起来。`
六、变换、过渡和动画属性
注意动画在一个成功的 Windows 8 应用中远不止是点缀;相反,它通过吸引用户并使应用程序变得生动而变得重要。而一个引人入胜、生动活泼的 app 才是成功的 app。
一个没有足够动画的 Windows 8 应用程序至少会给用户留下一种潜意识的感觉,即缺少了什么或者什么东西死了。太多的动画可能会分散注意力,分散注意力,甚至可能会令人厌烦。所以动画应该足以让你的应用程序的视觉效果栩栩如生,仅此而已。
适量的动画是 Windows 8 设计的核心原则。涵盖 Windows 8 设计的原则之一是真正的数字化,也就是说,拥抱现代数字系统的功能和自由,摆脱物理系统的束缚。强调用户任务的动画和过渡符合这个原则。
与这个主题相关的还有另一个原则——你的 UI 应该快速流畅。你的界面不仅应该在性能上或与用户的接触上没有停顿,而且应该从一个屏幕流到下一个屏幕。有很好的理由让 UI 动画化,甚至有更好的理由不要动画化太多。
在动画方面,微软再次采用并实现了 W3C 标准,并在必要的地方对其进行了扩展,以满足现代应用程序的需求。由于您的动画在 Windows 8 中运行,它们将拥有操作系统硬件加速的巨大优势。您不必接受使用 web 堆栈带来的性能损失。
在这一章中,我们将讨论所有与 CSS 和动画相关的东西。我们将涵盖二维和三维的变换、过渡和动画。比起我们现在的时间和空间,更多的页面可以很容易地用于这些广泛的主题,但我希望传达这个概念,并让你对可能的事情感到兴奋。
变换
转换只是简单的变化。它可能是宽度的改变、颜色的改变或一些其他的属性。但是,您已经知道,这些属性的更改可以通过简单地修改属性值来完成,那么,当您可以简单地调整元素的位置属性并看到相同的效果时,为什么您要添加一个转换,例如,将元素向右移动一些像素呢?或者,当您可以增加其宽度和高度属性时,为什么要应用缩放变换来使某些东西增长呢?
答案是转换很容易应用和移除(甚至是通过编程)。它会在目标元素呈现后影响它,并且会影响整个目标元素,包括子元素。
此外,转换允许您以单独使用属性无法实现的方式影响元素。例如,如果没有变换,就不能给元素添加旋转。事实上,有一个完整的 CSS 转换子集可以用类似 3D 的效果来影响元素,而这些效果肯定不可能用标准属性来实现。
有许多可用的变换效果,然而只有大约六个 CSS 属性需要记住,它们是perspective
、perspective-origin
、backface-visibility
、transform-origin
、transform-style
和transform
。还有更多关于这些属性的细节。在http://www.w3.org/TR/css3-transforms/#transform-property
可以看到完整的列表。
变换函数
到目前为止,最有趣的属性是transform
属性。对于它的值,它期望一个或多个转换函数的列表。我将首先描述每个与转换相关的属性,然后非常详细地关注转换属性。
perspective
不要混淆这个属性值和马上要讨论的perspective()
函数的区别。它们有相同的视觉效果,但是这个(transform
函数的perspective
值)影响它所有子元素的变换,而perspective()
函数只影响它所在元素的变换。我将等到下一节来描述perspective()
函数的实际效果。perspective
属性值仅影响 3D 变换元素。
perspective-origin
perspective-origin
属性是虚拟摄像机从目标元素正前方的偏差(使用 x 和 y 坐标)。如果你看着一个正方形建筑的墙,并且你向右走得足够远,从你的角度来看,墙会改变形状,这正是你在修改这个属性时应该想到的。与perspective
一样,perspective-origin
影响其子变换的变换,但不影响自己的变换。
backface-visibility
属性决定了当我们旋转一个元素并看到它的背面时,它的内容会发生什么。如果在这种情况下您应该看到内容的后面,请将其设置为visible
,如果不应该,请将其设置为hidden
。
transform-origin
如果你在正方形的一个角附近插上一根针并旋转它,你会得到一个不同于把针插在正方形中心的结果。这就是transform-origin
属性为您做的事情。它指示转换应该从元素的哪个部分开始。根据转换的不同,它的行为会有所不同。
transform-style
您可以指定flat
或preserve-3d
作为transform-style
属性的值。如果您选择preserve-3d
,那么嵌套元素将保持它们在 3D 空间中的相对位置。但是,如果您选择flat
,那么所有元素都会折叠到一个共享平面。
transform
transform
函数是完成大部分繁重工作的函数。它的值可能很大,因为它由一个或多个可用的转换函数组成(用空格分隔)。transform 属性及其众多函数都非常复杂。欢迎你去 w3c.org,得到你所需要的公式和理论,但是我会保持我所有的描述和例子简单实用。我将更多地谈论你可能选择在你的应用程序中使用转换的原因,而不是背后的数学和理论。
2D 变换函数
有许多变换函数可供选择。您可以使用以下任何二维变换来影响您的目标元素:rotate()
、scale()
、scaleX()
、scaleY()
、skew()
、skewX()
、skewY()
、translate()
、translateX()
、translateY()
或matrix()
。
rotate()
rotate 函数的目的一点也不含糊。它将目标元素顺时针旋转指定的度数。度数单位为deg
,遵循从负无穷大到正的值。负值将逆时针旋转目标元素,正值将顺时针旋转目标元素。
rotate()
函数完全愿意接受大于 360 度旋转的数字,它将继续旋转。因此,440deg
的值将顺时针方向旋转目标一次半,最终将等于180deg
的值。
清单 6-1 展示了具有三个不同旋转值的相同div
元素。
注意在本章的代码清单中,您可能会注意到父容器的display
值可能被设置为-ms-flexbox
或-ms-grid
。目前,只知道这些是布局技术。flexbox 非常适合将它的孩子一个接一个地排列起来,在这种情况下,网格用于将他们堆叠在一起。我们将在第七章中详细讨论这些和其他布局技术。
清单 6-1 。 分别为 5 度、-45 度和 180 度的文本块
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: rotate(5deg);
}
.parent div:nth-of-type(2) {
transform: rotate(-45deg);
}
.parent div:nth-of-type(3) {
transform: rotate(180deg);
}
图 6-1。具有不同旋转级别的变换元素
scale()
缩放是调整目标元素及其所有内容的大小,它在呈现目标后生效。这意味着元素的子内容不会根据其父元素的大小进行布局,而是随着父元素一起缩放。
scale()
函数要求一个值的乘数。值0.5
会将对象缩放到其原始大小的一半,1
会保持其大小不变,2
会使其翻倍。清单 6-2 经历了完全相同的场景。
清单 6-2 。 将对象缩放到原来的一半再到两倍
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: scale(1);
}
.parent div:nth-of-type(2) {
transform: scale(0.5);
}
.parent div:nth-of-type(3) {
transform: scale(2);
}
图 6-2 。三个级别的规模
注意缩放后,图 6-2 中的 div 实际上是重叠的。仅仅基于传统的 HTML 经验,这似乎是不可能的。缩放仅在目标元素完全呈现后发生,这意味着这与简单地为宽度和高度属性指定替代值有很大的不同。
考虑清单 6-3 中的元素。它的内容有一个段落,其尺寸为 400 像素宽,200 像素高。
清单 6-3 。 一个 400 像素乘 200 像素的带文本内容的 div 元素
<!-- HTML snippet -->
<div id="textDiv">
<p>Lorem ipsum dolor sit amet...</p>
</div>
/* CSS snippet */
#textDiv {
width: 400px;
height: 200px;
}
现在让我们看看清单 6-4 中的,其中我们使用宽度和高度属性来调整div
的大小。您会注意到段落文本已经对其父文本的大小变化做出了反应。
清单 6-4 。 通过操作样式属性将 div 的大小调整为 800 像素乘 400 像素
/* CSS snippet */
#textDiv {
width: 800px;
height: 400px;
}
图 6-4。div 文本的布局适合其更大的容器
现在,相反地,清单 6-5 缩放元素。您会注意到,段落文本没有改变其布局,但形状保持不变,尽管大小是原来的两倍。
清单 6-5 。 使用变换而不是缩放来放大 div
/* CSS snippet */
#textDiv {
width: 200px;
height: 100px;
transform: scale(2,2);
}
图 6-5。文本完全按照它在较小容器中的样子进行布局,只是后来进行了缩放
可以在 x 轴和 y 轴上统一进行缩放,也可以独立于其中一个轴进行缩放。函数scaleX()
和 scaleY()存在并将只变换适当的轴,但是同样的事情可以通过简单地向 scale 方法提供两个值并确保将其中一个设置为值1
来完成。那么,清单 6-6 中的两个表达式是相同的。
清单 6-6 。 两种交替方式将目标元素的宽度增加一倍
/* CSS snippet */
div {
transform: scale(2,1);
}
div {
transform: scaleX(2);
}
skew()
skew()
函数向相反的方向平移目标元素的对边,扭曲元素的形状及其内容。它可以用来创造各种各样的效果。
倾斜可以用来显示透视效果。此外,如果您在屏幕上制作元素动画,可以使用倾斜来显示元素的加速和减速,但那只是动画。倾斜变换本身是静态的。
清单 6-7 显示了一个基本的倾斜变换,这次再次影响了一段文本。
清单 6-7 。 文本沿单轴的基本倾斜
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: skew(0deg,10deg);
}
.parent div:nth-of-type(2) {
transform: skew(-5deg,0deg);
}
.parent div:nth-of-type(3) {
transform: skew(15deg,15deg);
}
图 6-6。垂直倾斜、水平倾斜以及两者的组合
像缩放变换一样,倾斜变换也有skewX()
和skewY()
两种,但是我个人认为不值得使用它们,因为使用skew(n,n)
和传入两个值一样容易。
translate()
像它的表亲 scale 和 skew 一样,translate 也有独立的轴版本,正如你可能猜到的那样,它们是translateX()
和translateY()
。我有没有提到我个人认为它们不值得?
平移变换是一个非常重要的变换。翻译就是简单地移动。translateX()
功能沿 x 轴左右移动目标,translateY()
功能沿 y 轴上下移动目标。然后translate()
函数取两个值,并可以沿着 xy 平面移动它的目标。你可以想象这样一个函数有多少种用途。
清单 6-8 使用 flexbox 将 5 个div
元素并排放置。它们都有一个预先确定 75 像素的正方形,一些空白,和一个白色的边界来区分。然后,突出显示的块挑选出第 5 个div
,并应用变换将其向右下方移动 20 个像素。
***清单 6-8 。***rotate()、scale()和 translate()的组合赋予第一个字母一些活力
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1){
transform: translate(0,0)
}
.parent div:nth-of-type(2){
transform: translate(20px,20px);
}
.parent div:nth-of-type(3){
transform: translate(0,0);
}
图 6-7。中间的 div 从其原始位置向右移动了 20 个像素,向下移动了 20 个像素
matrix()
我们已经讨论过的函数背后的所有功能以及更多功能都可以通过matrix
函数实现。matrix
功能不适合心脏虚弱的人。这很乏味也很复杂,但是当你需要深入了解并使你的变换看起来如此时,这个函数(以及对你书架上的线性代数书的一点回顾)将带你去那里。
3D 变换功能
首先,3D 这个术语有点误导。这些所谓的三维变换并不比二维计算机屏幕上发生的任何事情更三维,但定义计算机上 3D 技术的东西是对象在投影到二维屏幕之前呈现的 3D 空间。这种效果充其量只能产生 3D 效果。
有许多可用的三维变换函数。可以选择perspective()
、perspective-origin()
、rotate3d()
、rotateX()
、rotateY()
、rotateZ()
、scale3d()
、scaleZ()
、translate3d()
、translateZ()
、matrix3d()
。
对于所有的 3D 变换,您应该想象您的平面的、渲染的元素在 3D 空间中站立,虚拟相机指向它们。一些属性将操作这个虚拟摄像机的位置,其他的将操作渲染元素的位置。
perspective()
perspective()
函数操纵被转换元素的虚拟摄像机。它采用具有较高值的长度值,这意味着虚拟相机离对象更远,并且元素将看起来更平,而较低值,这意味着虚拟相机离对象更近,并且元素将看起来更有深度。
很容易注意到引入的戏剧性深度,因为perspective()
功能被配置为使相机更靠近对象。清单 6-9 展示了缩小视角的视觉效果。
清单 6-9 。 三个 div 都以相同的角度旋转,透视值分别为无、400 像素和 200 像素
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: rotate3d(1,1,1,45deg);
}
.parent div:nth-of-type(2) {
transform: perspective(400px) rotate3d(1,1,1,45deg);
}
.parent div:nth-of-type(3) {
transform: perspective(200px) rotate3d(1,1,1,45deg);
}
图 6-8。减少透视值会导致表观深度增加
正如我前面提到的,您应该小心不要将这个perspective()
函数与perspective
属性混淆。同样,该函数会影响它所应用到的元素的变换。还要记住,perspective
对没有应用任何其他 3D 变换功能的对象没有任何效果。
rotate3d()
当然,当我们看 2D 变换时,旋转也是可用的,但是你可能期望在 3D 环境中有一些额外的功能,你是对的。在我们的新空间中,我们将能够使用rotate3d()
、rotateX()
、rotateY()
和rotateZ()
围绕所有三个轴旋转。后三种功能没有什么是前一种功能做不到的。rotate3d()
函数有四个参数。前三个是向量的 x、y 和 z 坐标,将被规范化为单位向量,第四个是元素围绕该向量旋转的度数(顺时针)。
然后,调用rotate3d(1,0,0,45deg)
,将围绕 x 轴顺时针旋转元素 45 度;rotate3d(0,1,0,45deg)
将绕 y 轴顺时针旋转 45 度;而rotate3d(1,1,0,45deg)
将围绕一个向量旋转它 45 度,这个向量从原点开始,直接投影在 xy 平面上的 x 轴和 y 轴之间。
在任何旋转函数中,正的角度值将围绕轴或单位向量顺时针旋转元素,负的角度值将逆时针旋转元素。
清单 6-10 旋转三维平面元素。
***清单 6-10 。***rotate 3d()函数用于围绕 x 轴、y 轴以及两者的组合旋转一个 div
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: rotate3d(1,0,0,45deg);
}
.parent div:nth-of-type(2) {
transform: rotate3d(0,1,0,45deg);
}
.parent div:nth-of-type(3) {
transform: rotate3d(1,1,0,45deg);
}
图 6-9。围绕 x 轴的旋转看起来就像元素被垂直挤压,围绕 y 轴的旋转看起来就像被水平挤压,结合起来看起来就像是 3D 的
注意从技术上讲,上述三种变换中的任何一种都可以使用正确的二维变换函数来实现,但这需要一个坐标系映射。换句话说,让我们想象你正试图让一个正方形的视觉元素看起来像是朝着用户打开的,就像一扇客厅的门。要使用二维变换做到这一点,您需要弄清楚什么样的倾斜、缩放和平移组合会产生这种效果。然而,使用三维变换只需要一个简单的rotateY()
函数调用,几乎不需要思考!
scale3d()
一旦你把你的元素放入三维空间,所有主要的变换功能——旋转、缩放和平移——都必须实现。像它的对应物一样,scale3d()
函数也伴随着scaleX()
、scaleY()
和scaleZ()
函数,同样,scale3d()
函数可以执行其他函数可以执行的任何函数。你发现一种模式了吗?
scale3d()
函数要求我们提供三个参数,它们是沿 x、y 和 z 轴的比例因子。清单 6-11 使用了三个后续的scale3d()
函数调用来最好地说明区别。
?? 列表 6-11 。 一个 div 配置为不按比例缩放(1,1,1),第二个 div 配置为按比例缩小(0.8,0.8,0.8),第三个 div 在 y 和 z 轴按比例放大,在 x 轴按比例缩小
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
perspective: 800px;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: rotate3d(1,1,0,45deg) scale3d(1,1,1)
}
.parent div:nth-of-type(2) {
transform: rotate3d(1,1,0,45deg) scale3d(0.8,0.8,0.8)
}
.parent div:nth-of-type(3) {
transform: rotate3d(1,1,0,45deg) scale3d(0.5,1.2,1.2);
}
图 6-10。三维缩放的结果
translate3d()
当涉及到在二维空间移动元素时,translateX()
和translateY()
函数覆盖了基础,但随着第三维空间的到来,需要一个translateZ()
,事实就是如此。translateZ()
功能将物体移近或移离观看者(假设观看者仍在他或她的原始位置perspective-origin: 50% 50%
)。
清单 6-12 显示了一个例子,三个不透明的元素直接堆叠在一起。使用沿 z 轴的 3D 平移在堆叠的元素之间增加了一些距离。整个场景已被旋转以显示隐藏的元素。
清单 6-12 。 样式规则旋转和平移三个元素。那个。覆盖父规则以使用网格使元素堆叠在彼此之上
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-grid;
}
.parent div {
border: 2px solid gray;
background-color: white;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: rotate3d(1, -1, 0, 45deg) translate3d(0, 0, 0);
}
.parent div:nth-of-type(2) {
transform: rotate3d(1, -1, 0, 45deg) translate3d(0, 0, 60px);
}
.parent div:nth-of-type(3) {
transform: rotate3d(1, -1, 0, 45deg) translate3d(0, 0, 120px);
}
图 6-11。场景的旋转和每个元素的不同平移级别使我们能够看到每个元素,即使它们是堆叠的
matrix3d()
matrix3d()
函数是所有其他转换函数的母体。所有其他的都是基于它的,所以它能做其他函数能做的一切,甚至更多。唯一的缺点是,除非你有高等数学学位,否则很难弄清楚如何使用它。
我只辅修过数学,所以清单 6-13 借用了 MSDN 网站上matrix3d
函数的一个例子(http://msdn.microsoft.com/en-us/library/windows/apps/jj193609.aspx
)。
***清单 6-13 。***matrix 3d()函数的十六个值导致目标元素发生组合转换
<!-- HTML snippet -->
<div class="parent">
<div>Lorem ipsum dolor sit amet...</div>
</div>
/* CSS snippet */
.parent {
display: -ms-flexbox;
}
.parent div {
border: 2px solid gray;
width: 200px;
height: 200px;
padding: 5px;
margin: 5px;
}
.parent div:nth-of-type(1) {
transform: matrix3d(
0.359127, -0.469472, 0.806613, 0,
0.190951, 0.882948, 0.428884, 0,
-0.913545, 0, 0.406737, 0,
0, 0, 0, 1
);
}
图 6-12。使用 matrix3d()函数完成的转换组合
转换是一种变化,但它是静态的,在应用程序的视图渲染时应用,并在视图渲染时保持不变。我们真正需要做的是让事情向前发展。例如,当从一个页面切换到下一个页面时,我们可能需要最微妙的动画来指示一个页面飞入,另一个页面飞出。当我们将字体从正常变为粗体时,我们可能希望文本加粗,而不仅仅是在看不清的瞬间加粗。
为了让事情进展顺利,我们需要使用过渡。
过渡
你可能认为动画是一个脚本函数,想知道它们在 CSS 而不是 JavaScript 中做什么。不过,过渡和动画都与风格有关。唯一的区别是,它们不仅考虑了静态风格,还考虑了动态风格。
过渡为介于两种风格之间的风格提供了一种实现。它们是从这里到那里应该发生的事情的描述。当一个元素突然被添加到屏幕上时,它应该如何到达那里?当它被移除时,它应该如何离开?
就像变换一样,没有大量的 CSS 属性适用于过渡——实际上只有四个,外加一个简写。您可以从transition-property
、transition-duration
、transition-timing-function
和transition-delay
中选择,或者您可以跳过长的属性名称,将它们全部组合成transition
速记法。这是更常见的方法。
一旦某个元素成为样式规则的目标,过渡就会生效,它们的动画也会开始。在下面的例子中,您将看到我们的转换在一个样式规则中,选择器中有一个:hover 伪类。这意味着用户将悬停在一个元素上,此时将成为包含转换的样式规则的目标;因此,它们将被转换,而不是简单地将样式属性从原来的样子更改为新规则要求的样子。
如果一个转换介于两个状态之间,那么我们显然是在处理某个开始状态和某个结束状态。转换总是由结束状态定义的。如果我们将一个div
从矮变高,那么这个变化是由定义高状态的样式规则定义的。
清单 6-14 和图 6-13 显示了一个非常简单的过渡。一个div
元素以每边 100 像素的大小开始。它有一个白色的背景和灰色的能见度边界。定义了第二个样式规则,该规则应用于处于悬停状态的框——也就是说,当用户将鼠标悬停在 div 上时。第二帧代表用户悬停的时刻。
图 6-13 。过渡的五个帧试图说明产生的动画
在第二个规则中,我们指定了两个属性,然后指定了一个非常简单的转换属性,该属性简单地表明该样式规则中的所有属性需要两秒钟才能生效。这意味着五帧代表两秒钟,这是白盒变成灰色和方形边缘获得边框半径所需的时间。
清单 6-14 。 一个非常简单的转换,配置为花费两秒钟,当目标元素悬停时应用于背景颜色和边框半径属性
<!-- HTML snippet -->
<div id="box">
</div>
/* CSS snippet */
#box {
width: 100px;
height: 100px;
border: 2px solid hsl(0,0%,70%);
}
#box:hover {
background-color: gray;
border-radius: 25px;
transition: 2s;
}
在最后一个例子中,我们创建了一个省略了所有属性的转换,并将其应用于所有属性。如果要限制过渡实际应用到哪些属性,必须指定它们。清单 6-15 显示了前一个例子中#box:hover
样式规则的另一个版本,图 6-14 显示了结果。当然,不同之处在于,虽然边框半径看起来像以前一样有动画效果,但是过渡属性不再考虑背景色,因为存在一个明确的属性列表,并且没有邀请背景色。因此,当用户将鼠标悬停在上面时,div
会变成灰色,在我们的图 6-14 中,第二帧和随后的帧描述的正是这种情况。
图 6-14 。导致背景色从翻译属性中排除,并且在第二帧中明显立即应用背景色
清单 6-15 。 边界半径属性明确包含在平移属性中
#box:hover {
background-color: gray;
border-radius: 25px;
transition: border-radius 2s;
}
指定过渡应该花费两秒钟是假设对象的渐进变化应该根据缓动功能发生。“减缓”功能的作用方式更像我们世界中受重力约束的真实对象,因为它开始时慢一点,结束时也慢一点。放松功能对眼睛来说很容易,因为即使它是潜意识的,它看起来也像我们人类大脑习惯看到的东西。
不过,我们不必遵循这个函数。在清单 6-16 中,注意速记属性仍然在使用,但是我们现在已经指定应该使用线性函数。在我的 5 帧动画中,动画的变化太细微了,无法察觉,所以你只能自己尝试了。定时功能的有效值为linear
、ease
、ease-in
、ease-out
、ease-in-out
、cubic-bezier()
、step-start
、step-end
或steps()
。
清单 6-16 。??【线性计时功能】增加了转场速记属性
/* CSS snippet */
#box:hover {
background-color: gray;
border-radius: 25px;
transition: border-radius linear 2s;
}
linear
、ease
、ease-in
、ease-out
和ease-in-out
的值很方便,而cubic-bezier()
允许你指定任何你想要的连续函数。step-start
和step-end
值和steps()
功能允许非连续计时,以便过渡以阶梯方式生效。
最后,如果你没有为transition-delay
属性指定一个值,那么就不会有延迟,CSS 样式规则生效的时候转换就开始了。增加延迟值2s
将在状态改变整整两秒后开始转换。
您也可以应用多个过渡属性,但不是通过添加多个样式属性来实现。相反,您将多个属性放入同一个transition
属性中,并用逗号分隔它们。
清单 6-17 将为我们的div
制作背景色和边框半径的动画,但是背景色在 2 秒内不会开始,需要 10 秒才能完成。希望这个例子能激发你对 CSS 转换可能性的想象。
清单 6-17 。 为两个属性指定不同的时序
/* CSS snippet */
#box:hover {
background-color: gray;
border-radius: 25px;
transition: border-radius 2s, background-color 10s;
}
不是每一个 CSS 属性都适合转换,但差不多如此。根据 W3C,可转换属性的实际列表包含background-image
、background-position
、border-color
、border-width
、border-spacing
、bottom
、color
、crop
、font-size
、font-weight
、grid-*
、height
、left
、letter-spacing
、line-height
、margin
、max-height
、max-width
、min-height
、min-width
、opacity
、outline-color
、outline-offset
、outline-width
转换让我们可以很好地控制元素从一种状态到另一种状态的变化。但是,如果我们真的要掌握应用程序中的东西是如何移动的,我们就需要深入研究适当的 CSS 动画这个主题。
动画
CSS 动画比过渡给了我们更多的对目标元素的控制。过渡允许我们定义从开始状态到结束状态的单个过渡,但是动画允许定义任意数量的关键帧,整个动画可以按顺序通过这些关键帧。有了转场,我可以把我的div
从白色变成灰色,但是有了动画,我可以把它从白色变成红色,变成绿色,变成紫色,然后变成灰色,而且我可以控制每一步的时间。
动画比过渡稍微复杂一点,但是像大多数 CSS 概念一样,肯定不会太难理解。动画分两步完成。
第一步是定义动画本身,除了它最终可能应用的任何目标元素。这是使用与媒体查询定义和字体定义类似的语法来完成的。一个动画定义看起来像清单 6-18 中的。
清单 6-18 。??【一个动画定义的基本结构】
@keyframes myAnimation {
{keyframe1} {
{properties}
}
{keyframe1} {
{properties}
}
...
{keyframeN} {
{properties}
}
}
动画可以有任意数量的关键帧。每个关键帧的标识符可以是from
、to
或数字百分比值。from
值相当于0%
,to
值相当于100%
。您不必指定开始关键帧(from
)或结束关键帧(to
)。如果您关闭其中任何一个,它会将目标元素的属性值恢复到应用动画之前的位置。
清单 6-19 定义了一个动画,它将把它的目标元素从原来的颜色变成灰色,然后再变回灰色。
清单 6-19 。 单个中点关键帧(开始和结束关键帧将被隐式假定)
/* CSS snippet */
@keyframes toGrayAndBack {
50% {
background-color: gray;
}
}
第二步是将动画应用到元素上。这可以简单地通过将animation-name
属性添加到元素样式集合中来完成(或者将一个类应用到包含animation-name
属性的元素中)。
像过渡一样,动画在应用程序生效时开始。如果一个元素是用 animation-name 属性定义的,那么动画将在页面加载时开始。要使用 JavaScript 触发动画,您可以将动画应用到某个样式,然后以编程方式将该样式添加到您希望制作动画的元素中。
动画属性有animation-name
、animation-duration
、animation-timing-function
、animation-iteration-count
、animation-direction
、animation-play-state
、animation-delay, animation-fill-mode
和animation
速记属性。我推荐使用animation
速记属性,因为它使得代码更加可读。
一个动画应用程序可能看起来像清单 6-20 中的,它将确定名为myAnimation
的动画等待一秒钟的延迟,然后执行一个缓时功能五秒钟,并重复三次。
***清单 6-20 。***my animation 动画对 myElement 元素的应用
#myElement {
animation: myAnimation 5s ease 1s 3;
}
注意清单 6-19 的中定义名称myAnimation
的方式,以及在清单 6-20 的中使用了完全相同的动画名称的事实。如果这些名称不完全匹配,则动画将不适用。
在清单 6-21 中,我们将把定义和应用放在一起。代码获取我们创建的toGrayAndBack
动画,并将其应用到一个div
元素。你可以看到图 6-15 中的div
花了四秒钟从白色变成灰色,然后又变回灰色。注意,第一个(from
)和最后一个(to
)状态在这个动画中没有定义。只定义了中间(50%
)。因此div
是白色的,因为没有其他背景色应用于它,这是动画默认的状态。
图 6-15 。显示元素背景色从白色到灰色再变回白色的动画的五帧
清单 6-21 。 将动画定义和应用结合在一起
<!-- HTML snippet -->
<div id="box"></div>
/* CSS snippet */
@keyframes toGrayAndBack {
50% {
background-color: gray;
}
}
#box { animation: toGrayAndBack 4s; }
现在,我们将通过定义多个关键帧来进行一些改进。清单 6-22 包括三个关键帧,其中第一个和最后一个不是从对象中假定的,而是明确指定的。请记住,如果您的第一个和最后一个关键帧不相同,那么您将很难在不引入不和谐过渡的情况下创建循环动画。
清单 6-22 。 明确包含开始和结束关键帧
<!-- HTML snippet -->
<div id="box">
</div>
/* CSS snippet */
@keyframes toBlackToGray {
start {
background-color: white;
}
50% {
background-color: black;
}
end {
background-color: gray;
}
}
#box {
animation: toBlackToGray 4s;
}
图 6-16。五帧说明背景从白色到黑色再到灰色的动画
我应该在这里记下一条方便的捷径。如果块定义相同,关键帧名称如start
、50%
和end
可以组合,并用逗号分隔。很多时候你会以相同的属性集开始和结束,你可以用这种方法简化它。清单 6-23 提供了一个将目标元素从白色变成黑色再变回白色的技术例子。
清单 6-23 。?? 两个关键帧被定义在一起。不按顺序定义关键帧没有问题。
/* CSS snippet */
@keyframes toBlackAndBack {
start, end {
background-color: white;
}
50% {
background-color: black;
}
}
最后,清单 6-24 通过使用三个中间关键帧在轨道上移动一个div
绕着另一个div
更进一步。
清单 6-24 。 HTML 和 CSS 创建两个 div 元素和动画,一个环绕另一个
<!-- HTML snippet -->
<div id="fixed"></div>
<div id="orbit"></div>
/* CSS snippet */
#fixed {
background-color: black;
width: 100px;
height: 100px;
position: relative;
left: 150px;
top: 250px;
}
#orbit {
background-color: gray;
width: 100px;
height: 100px;
position: relative;
left: 0px;
top: 0px;
animation: orbit 10s linear infinite;
}
@keyframes orbit {
25% {
left: 300px;
top: 0px;
}
50% {
left: 300px;
top: 300px;
}
75% {
left: 0px;
top: 300px;
}
}
图 6-17。灰色 div 遵循黑色 div 周围的线性时序路径
除了应该生效的属性列表之外,关键帧还可以指定计时功能。这意味着,您可以通过将计时功能放入目标元素的动画应用程序中,为所有关键帧指定一个计时功能,或者可以在每个关键帧中指定多个计时功能,并让它们按照您喜欢的方式工作,即使它们互不相同。
令人印象深刻的是,这么多的动画可以单独用声明式 CSS 完成,但很可能您需要将一些逻辑合并到您的视觉资产的动画中,并且您需要为此使用 JavaScript。例如,在一个纸牌游戏中,在用户做出选择之前,你不知道他/她会做出什么样的选择,你需要做出相应的反应和动画。
CSS 动画的首要特性之一是捕捉基于动画的事件的能力。可用的事件有animationstart
、animationiteration
和animationend
,每个事件的功能从其名称就很明显,所以我就不解释了。这些事件是在目标元素上触发的,所以你可以像清单 6-25 中的那样连接你的事件处理程序。
清单 6-25 。 为 animationstart 事件实现一个事件处理程序
ready: function (element, options) {
document.querySelector("#myElement").addEventListener("animationstart", function(e) {
// do something
});
}
当您需要对某个元素的动画状态做出逻辑反应时,动画事件当然非常有用。例如,您可能希望在一个动画结束时触发另一个动画的开始。该代码可能看起来像清单 6-26 ,其中当elementA
完成其动画时,一个类被添加到elementB
。
清单 6-26 。 给一个元素添加一个类,当另一个结束时触发一个动画
ready: function (element, options) {
var elementA = document.querySelector("#elementA");
var elementB = document.querySelector("#elementB");
elementA.addEventListener(“animationend”, function(e) {
elementB.classList.add(“flash”);
});
}
MSCSSMatrix 对象
我们已经讨论了无数种应用 CSS 属性来改进带有转换的应用程序的方法,但是如果没有 MSCSSMatrix 对象的介绍,这个讨论将是不完整的。除了您在 CSS 文件中指定的所有这些属性之外,MSCSSMatrix
JavaScript 对象允许您在脚本中应用我们到目前为止讨论过的所有转换。这意味着你可以添加逻辑和更复杂的时间。
一个简单的例子就能说明问题。清单 6-27 根本不包含 CSS,只包含 HTML 和 JavaScript。假设 JavaScript 存在于一个 ready 方法中,该方法在 DOM 就绪时触发。
清单 6-27 。 一个简单的 div,其文本由 JavaScript 指示绕 z 轴逆时针旋转 10 度
<!-- HTML snippet -->
<div class="parent">
Hello world
</div>
// JavaScript snippet
var d = document.querySelector(".parent");
d.style.transform = new MSCSSMatrix(d.style.transform).rotate(0, 0, -10);
图 6-18。结果,旋转的文本,完成没有显式的 CSS 编写
在这个例子中,我们使用了rotate
函数,但是所有其他的转换函数都是可用的,当然,你也可以手动设置你的矩阵值。
想象一下用 JavaScript 中 CSS 转换的力量可以做些什么是令人兴奋的。你可以在微软 MSDN 网站http://msdn.microsoft.com/en-us/library/windows/apps/hh453593.aspx
上找到更多关于 MSCSSMatrix 对象的信息。
CSS3 中变换、过渡和动画的引入只是 web stack 成为世界上最强大的(也是无处不在的)用户界面技术的部分原因。
摘要
到目前为止,我们一直在看只包含少量基本元素的例子。在一个真实的应用程序场景中,你需要在屏幕上获得更多的视觉资产,并以一种有意义和实现良好设计的方式来布局它们。
你将在 CSS 中得到的布局元素和技术,以及来自 WinJS 库的一些帮助,将会给你把你的设计变成一个工作模型所需要的能力,我们将在下一章中研究那些布局技术。