In the realm of CSS layout, lists are an interesting case. The items in a list are simply block boxes, but with an extra bit that doesn’t really participate in the document layout hanging off to one side. With an ordered list, that extra bit contains a series of increasing numbers (or letters) that are calculated and mostly formatted by the user agent, not the author. Taking a cue from the document structure, the user agent generates the numbers and their basic presentation.
在 CSS 布局领域,列表是一个有趣的例子。列表中的项只是块框,但是有一个额外的部分并不真正参与文档布局。对于一个有序列表,这个额外的位包含一系列递增的数字(或字母),这些数字(或字母)是由用户代理(而不是作者)计算和格式化的。根据文档结构的提示,用户代理生成数字及其基本表示。
None of this content generation could be described in CSS1 terms—and, therefore, it couldn’t be controlled—but CSS2 introduced features that allow list-item numbering to be described. As a result, CSS now lets you, the author, define your own counting patterns and formats, and associate those counters with any
element, not just ordered list items. Furthermore, this basic mechanism makes it possible to insert other kinds of content, including text strings, attribute values, or even external resources into a document. Thus, it becomes possible to use CSS to insert link icons, editorial symbols, and more into a design without having to create extra markup.
所有这些内容生成都无法用 CSS1 术语描述,因此也无法对其进行控制,但是 CSS2 引入了允许描述列表项编号的特性。因此,CSS 现在允许您(作者)定义自己的计数模式和格式,并将这些计数器与“any”元素关联起来,而不仅仅是有序的列表项。此外,这种基本机制使得将其他类型的内容(包括文本字符串、属性值甚至外部资源)插入文档成为可能。因此,可以使用 CSS 在设计中插入链接图标、编辑符号等,而不必创建额外的标记。
To see how all these list options fit together, we’ll explore basic list styling before moving on to examine the generation of content and counters.
要查看所有这些列表选项是如何组合在一起的,我们将研究基本的列表样式,然后再研究内容和计数器的生成。
In a sense, almost anything that isn’t narrative text can be considered a list. The US Census, the solar system, my family tree, a restaurant menu, and even all of the friends you’ve ever had can be represented as a list, or perhaps as a list of lists. These many variations make lists fairly important, which is why it’s a shame that list styling in CSS isn’t more sophisticated.
在某种意义上,几乎所有非叙事性文本都可以被视为列表。美国人口普查,太阳系,我的家谱,餐馆菜单,甚至所有你曾经有过的朋友都可以被表示为一个列表,或者可能是一个列表中的列表。这些变化使得列表非常重要,这就是为什么 CSS 中的列表样式不是很复杂的原因。
The simplest (and best-supported) way to affect a list’s styles is to change its marker type. The marker
of a list item is, for example, the bullet that appears next to each item in an unordered list. In an ordered list, the marker could be a letter, number, or a symbol from some other counting system. You can even replace the markers with images. All of these are accomplished using the different list-style properties.
影响列表样式的最简单(也是最受支持的)方法是更改其标记类型。例如,列表项的
marker
是无序列表中每个项旁边的项目符号。在有序列表中,标记可以是字母、数字或来自其他计数系统的符号。你甚至可以用图像代替标记。所有这些都是使用不同的列表样式属性完成的。
To change the type of marker used for a list’s items, use the property list-style-type
.
要更改用于列表项的标记的类型,请使用属性
list-style-type
。
That’s quite a few keywords, I know—and that’s not even all the values that list-style-type
has historically borne! Some, such as urdu
and hangul-consonant
, are supported by one browser or another, but none of the older values have widespread support. By contrast, the list of values shown above has nearly universal support. Some examples are shown in Figure 15-1.
这是相当多的关键字,我知道-这甚至不是所有的价值,
list-style-type
一直以来所承担的!有些值,如urdu
和hangul-consonant
,在不同的浏览器中是受支持的,但是没有一个旧的值得到广泛的支持。相比之下,上面显示的值列表几乎得到了普遍支持。图 15-1 显示了一些示例。
The list-style-type
property, as well as all other list-related properties, can be applied only to an element that has a display
of list-item
, but CSS doesn’t distinguish between ordered and unordered list items. Thus, you can set an ordered list to use discs instead of numbers. In fact, the default value of list-style-type
is disc
, so you might theorize that without explicit declarations to the contrary, all lists (ordered or unordered) will use discs as the marker for each item. This would be logical, but, as it turns out, it’s up to the user agent to decide. Even if the user agent doesn’t have a predefined rule such as ol {list-style-type: decimal;}
, it may prohibit ordered markers from being applied to unordered lists, and vice versa. You can’t count on this, so be careful.
list-style-type
属性,以及所有其他与列表相关的属性,只能应用于一个“display”为“list-item”的元素,但 CSS 不区分有序和无序列表项。因此,您可以设置一个有序的列表来使用磁盘而不是数字。事实上,list-style-type
的默认值是“disc”,因此您可以推断,如果没有明确的相反声明,所有列表(有序或无序)都将使用 disc 作为每个项的标记。这是合乎逻辑的,但是,结果是由用户代理来决定的。即使用户代理没有“ol {list-style-type: decimal;}”这样的预定义规则,它也可能禁止将有序标记应用于无序列表,反之亦然。你不能指望这个,所以要小心。
A sampling of list style types
Historically, user agents treated any unrecognized keyword value as decimal
, as per CSS 2.1. The CSS Lists and Counters Module is less precise about this, as of early 2017, and appears to allow a fallback to either disc
or none
. (Chrome, for example, defaults to none
if an ordered list type is applied to an unordered list.)
过去,用户代理将任何无法识别的关键字值视为
decimal
,如 CSS 2.1 所示。从 2017 年初开始,CSS 列表和计数器模块在这方面就不那么精确了,似乎允许对disc
或none
进行回退。(例如,如果一个有序列表类型应用于一个无序列表,Chrome 默认为none
。)
If you want to suppress the display of markers altogether, then none
is the value you should use. none
causes the user agent to refrain from putting anything where the marker would ordinarily be, although it does not interrupt the counting in ordered lists. Thus, the following markup would have the result shown in Figure 15-2:
如果您想完全禁止显示标记,那么
none
是您应该使用的值。none
导致用户代理不将任何东西放在标记通常所在的位置,尽管它不会中断有序列表中的计数。因此,下面的标记将得到如图 15-2 所示的结果:
ol li {
list-style-type: decimal;
}
li.off {
list-style-type: none;
}
<ol>
<li>Item the first</li>
<li class="off">Item the second</li>
<li>Item the third</li>
<li class="off">Item the fourth</li>
<li>Item the fifth</li>
</ol>
Switching off list-item markers
list-style-type
is inherited, so if you want to have different styles of markers in nested lists, you’ll likely need to define them individually. You may also have to explicitly declare styles for nested lists because the user agent’s style sheet may have already defined them. For example, assume that a user agent has the following styles defined:
list-style-type
是继承的,所以如果你想在嵌套的列表中有不同风格的标记,你可能需要分别定义它们。您可能还必须显式地声明嵌套列表的样式,因为用户代理的样式表可能已经定义了它们。例如,假设用户代理定义了以下样式:
ul {
list-style-type: disc;
}
ul ul {
list-style-type: circle;
}
ul ul ul {
list-style-type: square;
}
If this is the case—and it’s likely that this, or something like it, will be—you will have to declare your own styles to overcome the user agent’s styles. Inheritance won’t be enough.
如果是这种情况(很可能是这种情况或类似的情况),则必须声明自己的样式以克服用户代理的样式。遗产是不够的。
CSS also allows authors to supply string values as list markers. This opens the field to anything you can input from the keyboard, as long as you don’t mind having the same string used for every marker in the list.
CSS 还允许作者提供字符串值作为列表标记。这将向您可以从键盘输入的任何内容打开字段,只要您不介意为列表中的每个标记使用相同的字符串。
Figure 15-3 shows the results of the following styles:
图 15-3 显示了以下几种风格的结果:
.list01 {
list-style-type: "%";
}
.list02 {
list-style-type: "Hi! ";
}
.list03 {
list-style-type: "†";
}
.list04 {
list-style-type: "⌘";
}
.list05 {
list-style-type: " ";
}
A sampling of string markers
As of late 2017, only the Firefox family of browsers supported string values for list markers.
Sometimes, a regular text marker just won’t do. You might prefer to use an image for each marker, which is possible with the property list-style-image
.
有时,一个普通的文本标记是不行的。您可能更喜欢为每个标记使用一个图像,这可以通过属性
list-style-image
实现。
Here’s how it works:
它是这样工作的:
ul li {
list-style-image: url(ohio.gif);
}
Yes, it’s really that simple. One simple url() value, and you’re putting images in for markers, as you can see in Figure 15-4.
是的,就是这么简单。一个简单的 url()值,然后将图像放入标记中,如图 15-4 所示。
Using images as markers
Of course, you should exercise care in the images you use, as the example shown in Figure 15-5 makes painfully clear:
当然,您应该在使用的图像中多加小心,如图 15-5 所示的示例清楚地表明:
ul li {
list-style-image: url(big-ohio.gif);
}
Using really big images as markers
It’s generally a good idea to provide a fallback marker type in case your image doesn’t load, gets corrupted, or is in a format that some user agents can’t display. Do this by defining a backup list-style-type
for the list:
一般来说,提供一个回退标记类型是一个好主意,以防您的图像无法加载、损坏或以某些用户代理无法显示的格式出现。通过为列表定义一个备份
list-style-type
来做到这一点:
ul li {
list-style-image: url(ohio.png);
list-style-type: square;
}
The other thing you can do with list-style-image
is set it to the default value of none
. This is good practice because list-style-image
is inherited, so any nested lists will pick up the image as the marker, unless you prevent that from happening:
list-style-image
可以做的另一件事是将它设置为none
的默认值。这是一个很好的做法,因为list-style-image
是继承的,所以任何嵌套的列表都会选择该图像作为标记,除非您阻止这种情况发生:
ul {
list-style-image: url(ohio.gif);
list-style-type: square;
}
ul ul {
list-style-image: none;
}
Since the nested list inherits the item type square
but has been set to use no image for its markers, squares are used for the markers in the nested list, as shown in Figure 15-6.
由于嵌套列表继承了项目类型
square
,但已设置为不使用图像作为其标记,所以使用正方形作为嵌套列表中的标记,如图 15-6 所示。
Switching off image markers in sublists
Remember that this scenario might not occur in the real world: a user agent may have already defined a list-style-type
for ul ul
, so the value of square
won’t be inherited after all. Instead, you might get a circle, disc, or other symbol.
Any image value is permitted for list-style-image
, including gradient images. Thus, the following styles would have a result like that shown in Figure 15-7:
list-style-image
允许任何图像值,包括渐变图像。因此,以下样式的结果如图 15-7 所示:
.list01 {
list-style-image: radial-gradient(
closest-side,
orange,
orange 60%,
blue 60%,
blue 95%,
transparent
);
}
.list02 {
list-style-image: linear-gradient(45deg, red, red 50%, orange 50%, orange);
}
.list03 {
list-style-image: repeating-linear-gradient(
-45deg,
red,
red 1px,
yellow 1px,
yellow 3px
);
}
.list04 {
list-style-image: radial-gradient(
farthest-side at bottom right,
lightblue,
lightblue 50%,
violet,
indigo,
blue,
green,
yellow,
orange,
red,
lightblue
);
}
Gradient list markers
There is one drawback to gradient markers: they tend to be very small. The size isn’t something that CSS allows you to control, so you’re stuck with whatever the browser decides is a good size. This size can be influenced by things like font size, because the marker size tends to scale with the list item’s content, but that’s about it.
梯度标记有一个缺点:它们往往非常小。CSS 不允许您控制大小,所以您只能选择浏览器认为合适的大小。这个大小可能会受到字体大小等因素的影响,因为标记的大小会随着列表项的内容而变化,但仅此而已。
CSS does define a way to style list markers directly, the ::marker
pseudo-element, but it wasn’t supported by anything as of early 2017.
As of early 2017, only the WebKit/Blink family of browsers supported gradient image values for list markers.
There is one other thing you can do to influence the appearance of list items under CSS: decide whether the marker appears outside or inside the content of the list item. This is accomplished with list-style-position
.
您还可以做另一件事来影响 CSS 下列表项的外观:决定标记是出现在列表项的内容外部还是内部。这是通过
list-style-position
来完成的。
If a marker’s position is set to outside
(the default), it will appear the way list items have since the beginning of the web. Should you desire a slightly different appearance, you can pull the marker in toward the content by setting the value of list-style-position
to inside
. This causes the marker to be placed “inside” the list item’s content. The exact way this happens is undefined, but Figure 15-8 shows one possibility:
如果一个标记的位置被设置为
outside
(默认),它将显示自 web 开始以来列表项的方式。如果你想要一个稍微不同的外观,你可以通过将list-style-position
的值设置为inside
来将标记拉向内容。这将导致标记被放置在列表项的内容“内部”。这种情况发生的确切方式尚未确定,但图 15-8 显示了一种可能性:
li.first {
list-style-position: inside;
}
li.second {
list-style-position: outside;
}
Placing the markers inside and outside list items
In practice, markers given an inside
placement are treated as if they’re an inline element inserted into the beginning of the list item’s content. This doesn’t mean the markers actually are
inline elements—you can’t style them separately from the rest of the element’s content, unless you wrap all the other content in an element like span
. It’s just that in layout terms, that’s what they act like.
在实践中,给定
inside
位置的标记被视为插入到列表项内容开头的内联元素。这并不意味着标记实际上是are
内联元素—您不能将它们与元素的其余内容分开进行样式设置,除非您将所有其他内容都包装在像span
这样的元素中。只是在布局方面,这就是它们的作用。
For brevity’s sake, you can combine the three list-style properties into a convenient single property: list-style
.
为了简单起见,您可以将这三个列表样式的属性组合成一个方便的单一属性:
list-style
。
For example:
li {
list-style: url(ohio.gif) square inside;
}
As you can see in Figure 15-9, all three values are applied to the list items.
如图 15-9 所示,所有三个值都应用于列表项。
Bringing it all together
The values for list-style
can be listed in any order, and any of them can be omitted.
list-style
的值可以以任何顺序列出,其中任何一个都可以省略。
As long as one is present, the rest will fill in their default values. For instance, the following two rules will have the same visual effect:
只要有一个,其余的将填充它们的默认值。例如,以下两条规则会产生相同的视觉效果:
li.norm {
list-style: url(img42.gif);
}
li.odd {
list-style: url(img42.gif) disc outside;
} /* the same thing */
They will also override any previous rules in the same way. For example:
它们还将以相同的方式覆盖以前的任何规则。例如:
li {
list-style-type: square;
}
li {
list-style: url(img42.gif);
}
li {
list-style: url(img42.gif) disc outside;
} /* the same thing */
The result will be the same as that in Figure 15-9 because the implied list-style-type
value of disc
will override the previous declared value of square
, just as the explicit value of disc
overrides it in the second rule.
结果将与图 15-9 相同,因为
disc
的隐含list-style-type
值将覆盖先前声明的square
值,就像disc
的显式值覆盖第二个规则中的值一样。
Now that we’ve looked at the basics of styling list markers, let’s consider how lists are laid out in various browsers. We’ll start with a set of three list items devoid of any markers and not yet placed within a list, as shown in Figure 15-10.
既然我们已经了解了样式列表标记的基础知识,现在让我们考虑一下列表在各种浏览器中是如何布局的。我们将从一组包含三个列表项的列表开始,这些列表项没有任何标记,也没有放在列表中,如图 15-10 所示。
Three list items
The border around the list items shows them to be, essentially, like block-level elements. Indeed, the value list-item
is defined to generate a block box. Now let’s add markers, as illustrated in Figure 15-11.
列表项周围的边框显示它们本质上类似于块级元素。实际上,定义值
list-item
是为了生成一个块框。现在让我们添加标记,如图 15-11 所示。
Markers are added
The distance between the marker and the list item’s content is not defined by CSS, and CSS does as yet not provide a way to affect that distance.
标记和列表项内容之间的距离不是由 CSS 定义的,而且 CSS 还没有提供影响该距离的方法。
With the markers outside the list items’ content, they don’t affect the layout of other elements, nor do they really even affect the layout of the list items themselves. They just hang a certain distance from the edge of the content, and wherever the content edge goes, the marker will follow. The behavior of the marker works much as though the marker were absolutely positioned in relation to the list-item content, something like position: absolute; left: -1.5em;
. When the marker is inside, it acts like an inline element at the beginning of the content.
使用列表项内容之外的标记,它们不会影响其他元素的布局,甚至不会真正影响列表项本身的布局。它们只是与内容边缘保持一定的距离,无论内容边缘走到哪里,标记都会跟着走。标记的行为非常类似于将标记绝对定位于列表项的内容,比如
position: absolute; left: -1.5em;
。当标记位于内部时,它的作用类似于内容开头的内联元素。
So far, we have yet to add an actual list container; in other words, there is neither a ul
nor an ol
element represented in the figures. We can add one to the mix, as shown in Figure 15-12 (it’s represented by a dashed border).
到目前为止,我们还没有添加一个实际的列表容器;换句话说,图中既没有
ul
元素,也没有ol
元素。我们可以向组合中添加一个,如图 15-12 所示(它由虚线边框表示)。
Adding a list border
Like the list items, the list element is a block box, one that encompasses its descendant elements. As we can see, however, the markers are not only placed outside the list item contents, but also outside the content area of the list element. The usual “indentation” you expect from lists has not yet been specified.
与列表项一样,列表元素也是一个块框,它包含它的子元素。但是,我们可以看到,标记不仅放在列表项内容之外,还放在列表元素的内容区域之外。列表中常见的“缩进”尚未指定。
Most browsers, as of this writing, indent list items by setting either padding or margins for the containing list element. For example, the user agent might apply a rule such as:
在撰写本文时,大多数浏览器通过设置包含列表元素的 padding 或 margin 来缩进列表项。例如,用户代理可能会应用这样的规则:
ul,
ol {
margin-left: 40px;
}
This is the basic rule employed by Internet Explorer and Opera. Most Gecko-based browsers, on the other hand, use a rule something like this:
这是 ie 和 Opera 使用的基本规则。另一方面,大多数基于 gecko 的浏览器使用这样的规则:
ul,
ol {
padding-left: 40px;
}
Neither is incorrect, but the discrepancy can lead to problems if you want to eliminate the indentation of the list items. Figure 15-13 shows the difference between the two approaches.
这两种方法都不正确,但是如果您想消除列表项的缩进,那么这种差异可能会导致问题。图 15-13 显示了这两种方法之间的差异。
Margins and padding as indentation devices
The distance of 40px
is a relic of early web browsers, which indented lists by a pixel amount. (Block quotes are indented by the same distance.) An alternate value might be something like 2.5em
, which would scale the indentation along with changes in the text size.
For authors who want to change the indentation distance of lists, I strongly recommend that you specify both padding and margins to ensure cross-browser compatibility. For example, if you want to use padding to indent a list, use this rule:
对于希望更改列表缩进距离的作者,我强烈建议您同时指定填充和空白,以确保跨浏览器兼容性。例如,如果你想使用内边距缩进列表,可以使用以下规则:
ul {
margin-left: 0;
padding-left: 1em;
}
If you prefer margins, write something like this instead:
ul {
margin-left: 1em;
padding-left: 0;
}
In either case, remember that the markers will be placed relative to the contents of the list items, and may therefore “hang” outside the main text of a document, or even beyond the edge of the browser window. This is most easily observed if very large images, or long text strings, are used for the list markers, as shown in Figure 15-14.
无论哪种情况,请记住标记将相对于列表项的内容放置,因此可能会“挂起”文档的主要文本之外,甚至超出浏览器窗口的边缘。如果使用非常大的图像或长文本字符串作为列表标记,则最容易观察到这一点,如图 15-14 所示。
Large markers and list layout
One feature many authors request is the ability to control the space between a marker and the content of a list item. CSS2 defined ways to do this, including a property called marker-offset
and a display
value of marker
. Implementation experience revealed this to be a clumsy approach, and these features were removed in CSS2.1 As of early 2017, the working draft of the CSS3 Lists and Counters module defines a more compact way to affect marker placement, which is the ::marker
pseudoelement. Assuming the module does not change before becoming a full Recommen dation, you may someday be able to write rules such as li::marker {margin-right: 0.125em; color: goldenrod;}
.
许多作者要求的一个特性是能够控制标记和列表项内容之间的空间。CSS2 定义了实现这一功能的方法,包括一个名为
marker-offset
的属性和一个名为display
的marker
值。实施经验表明这是一种笨拙的方法,在 CSS2.1 中删除了这些特性。到 2017 年初,CSS3 列表和计数器模块的工作草案定义了一种更紧凑的方式来影响标记的放置,即::marker
伪元素。假设模块在完全重新推荐之前没有变化,那么有一天您可能能够编写这样的规则:li::marker {margin-right: 0.125em; color: goldenrod;}
。
CSS defines methods to create what’s called generated content
. This is content inserted via CSS, but not represented either by markup or content.
CSS 定义了一些方法来创建所谓的
generated content
。这是通过 CSS 插入的内容,但不通过标记或内容表示。
For example, list markers are generated content. There is nothing in the markup of a list item that directly represents the markers, and you, the author, do not have to write the markers into your document’s content. The browser simply generates the appropriate marker automatically. For unordered lists, the marker will a symbol of some kind, such as a circle, disc, or square. In ordered lists, the marker is by default a counter that increments by one for each successive list item. (Or, as we saw in previous sections, you may replace either kind with an image or symbol.)
例如,列表标记是生成的内容。列表项的标记中没有直接表示标记的内容,作为作者,您不必将标记写入文档内容。浏览器只是自动生成适当的标记。对于无序列表,该标记将是某种符号,例如圆形、圆盘或正方形。在有序列表中,默认情况下,标记是一个计数器,对每个连续的列表项递增 1。(或者,正如我们在前面几节中看到的,您可以用图像或符号替换这两种类型。)
To understand how you can affect list markers and customize the counting of ordered lists (or anything else!), you must first look at more basic generated content.
要理解如何影响列表标记并自定义有序列表的计数(或其他任何东西!),您必须首先查看更基本的生成内容。
To insert generated content into the document, use the ::before
and ::after
pseudo-elements. These place generated content before or after the content
of an element by way of the content property (described in the next section).
要将生成的内容插入到文档中,请使用
::before
和::after
伪元素。通过 content 属性(在下一节中描述)将生成的内容放置在元素的“content”之前或之后。
For example, you might want to precede every hyperlink with the text “(link)” to mark them for printing. This is accomplished with a rule like the following, which has the effect shown in Figure 15-15:
例如,您可能希望在每个超链接之前加上文本“(链接)”,以便标记它们以便打印。这是通过如下规则完成的,其效果如图 15-15 所示:
a[href]::before {
content: "(link)";
}
Generating text content
Note that there isn’t a space between the generated content and the element content.
注意,生成的内容和元素内容之间没有空格。
This is because the value of content in the previous example doesn’t include a space.
这是因为前一个示例中的内容值不包含空格。
You could modify the declaration as follows to make sure there’s a space between generated and actual content:
您可以修改声明如下,以确保在生成的内容和实际内容之间有一个空格:
a[href]::before {
content: "(link) ";
}
It’s a small difference but an important one.
这是一个小的区别,但很重要。
In a similar manner, you might choose to insert a small icon at the end of links to PDF documents. The rule to accomplish this would look something like:
以类似的方式,您可以选择在链接到 PDF 文档的末尾插入一个小图标。完成此任务的规则如下:
a.pdf-doc::after {
content: url(pdf-doc-icon.gif);
}
Suppose you want to further style such links by placing a border around them. This is done with a second rule:
假设您想通过在这些链接周围放置边框来进一步设计它们的样式。这是通过第二条规则实现的:
a.pdf-doc {
border: 1px solid gray;
}
The result of these two rules is illustrated in Figure 15-16.
Generating icons
Notice how the link border extends around the generated content, just as the link underline extended under the “(link)” text in Figure 15-15. This happens because generated content is placed inside the element box of the element. As of CSS2.1, there isn’t a way to place generated content outside the element box, other than list markers.
请注意链接边框是如何围绕生成的内容扩展的,就像图 15-15 中的“(链接)”文本下的链接下划线一样。这是因为生成的内容被放置在元素的元素框中。在 CSS2.1 中,除了列表标记之外,没有办法将生成的内容放置在元素框之外。
You might think that positioning would do the trick, except CSS2 and CSS2.1 specifically prohibit the floating or positioning of ::before
and ::after
content. List-style properties, along with table properties, are similarly prohibited. In addition, the following restrictions apply:
您可能会认为定位可以解决这个问题,但是 CSS2 和 CSS2.1 特别禁止
::before
和::after
内容的浮动或定位。类似地,列表样式的属性和表属性也被禁止。此外,以下限制适用:
- If the subject of a
::before
or::after
selector is a block-level element, then the propertydisplay
can accept only the valuesnone
,inline
,block
, andmarker
. Any other value is treated asblock
. - If the subject of a
::before
or::after
selector is an inline-level element, then the propertydisplay
can accept only the valuesnone
andinline
. Any other value is treated asinline
.
- 如果“选择器”之前的
::before
或::after
选择器的主题是块级元素,那么display
属性只能接受none
、inline
、block
和marker
等值。任何其他值都被视为block
。- 如果
::before
或::after
选择器的主题是一个内联级元素,那么display
属性只能接受none
和inline
两个值。任何其他值都被视为inline
。
For example, consider:
例如,考虑:
em::after {
content: " (!) ";
display: block;
}
Since em
is an inline element, the generated content cannot be made block-level. The value block
is therefore reset to inline
. In this next example, however, the generated content is made block-level because the target element is also block-level:
因为
em
是一个内联元素,所以生成的内容不能是块级的。因此,值block
被重置为inline
。但是在下一个例子中,生成的内容是块级别的,因为目标元素也是块级别的:
h1::before {
content: "New Section";
display: block;
color: gray;
}
The result is illustrated in Figure 15-17.
结果如图 15-17 所示。
Generating block-level content
One interesting aspect of generated content is that it inherits values from the element to which it’s been attached. Thus, given the following rules, the generated text will be green, the same as the content of the paragraphs:
生成内容的一个有趣的方面是,它从附加的元素中继承值。因此,根据以下规则,生成的文本将是绿色的,与段落的内容相同:
p {
color: green;
}
p::before {
content: "::: ";
}
If you want the generated text to be purple instead, a simple declaration will suffice:
如果你想要生成的文本是紫色的,一个简单的声明就足够了:
p::before {
content: "::: ";
color: purple;
}
Such value inheritance happens only with inherited properties, of course. This is worth noting because it influences how certain effects must be approached. Consider:
当然,这种值继承只发生在继承属性中。这一点值得注意,因为它影响了必须如何处理某些效果。考虑:
h1 {
border-top: 3px solid black;
padding-top: 0.25em;
}
h1::before {
content: "New Section";
display: block;
color: gray;
border-bottom: 1px dotted black;
margin-bottom: 0.5em;
}
Since the generated content is placed inside the element box of the h1
, it will be placed under the top border of the element. It would also be placed within any padding, as shown in Figure 15-18.
由于生成的内容被放置在
h1
的元素框中,所以它将被放置在元素的顶部边框下。它也会被放置在任何填充内,如图 15-18 所示。
Taking placement into account
The bottom margin of the generated content, which has been made block-level, pushes the actual content of the element downward by half an em. In every sense, the effect of the generated content in this example is to break up the h1
element into two pieces: the generated-content box and the actual content box. This happens because the generated content has display: block
. If you were to change it to display: inline
, the effect would be as shown in Figure 15-19:
生成内容的底部边缘,块级,将元素的实际内容向下通过半。在每一个意义上,生成内容的影响在这个例子中就是 h1
元素分解成两部分:生成内容框和盒子的实际内容。这是因为生成的内容有 display: block
。如果将其更改为 display: inline
,效果将如图 15-19 所示:
h1 {
border-top: 3px solid black;
padding-top: 0.25em;
}
h1::before {
content: "New Section";
display: inline;
color: gray;
border-bottom: 1px dotted black;
margin-bottom: 0.5em;
}
Changing the generated content to be inline
Note how the borders are placed and how the top padding is still honored. So is the bottom margin on the generated content, but since the generated content is now inline and margins don’t affect line height, the margin has no visible effect.
请注意边框是如何放置的,以及顶部填充是如何显示的。生成内容的底部空白也是如此,但是由于生成的内容现在是内联的,并且空白不会影响行高,所以空白没有可见的效果。
With the basics of generating content established, let’s take a closer look at the way the actual generated content is specified.
在建立了生成内容的基础知识之后,让我们进一步了解如何指定实际生成的内容。
If you’re going to generate content, you need a way to describe the content to be generated. As you’ve already seen, this is handled with the content
property, but there’s a great deal more to this property than you’ve seen thus far.
如果您要生成内容,您需要一种方法来描述将要生成的内容。正如您已经看到的,这是通过' content '属性来处理的,但是这个属性要比您目前看到的多得多。
You’ve already seen string and URI values in action, and counters will be covered later in this chapter. Let’s talk about strings and URIs in a little more detail before we take a look at the attr( )
and quote values.
您已经看到了字符串和 URI 值的作用,本章后面将讨论计数器。在查看
attr( )
和引号值之前,让我们更详细地讨论一下字符串和 uri。
String values are presented literally, even if they contain what would otherwise be markup of some kind. Therefore, the following rule would be inserted verbatim into the document, as shown in Figure 15-20:
字符串值是按字面意义表示的,即使它们包含了某种标记。因此,将以下规则逐字插入到文档中,如图 15-20 所示:
h2::before {
content: "<em>¶</em> ";
color: gray;
}
Strings are displayed verbatim
This means that if you want a newline (return) as part of your generated content, you can’t use <br>
. Instead, you use the string \A
, which is the CSS way of representing a newline (based on the Unicode line-feed character, which is hexadecimal position A
).
这意味着如果你想要一个换行(返回)作为你生成内容的一部分,你不能使用
<br>
。而是使用字符串\A
,这是表示换行的 CSS 方法(基于 Unicode 换行字符,它是十六进制位置A
)。
Conversely, if you have a long string value and need to break it up over multiple lines, you escape out the line feeds with the \
character. These are both demonstrated by the following rule and illustrated in Figure 15-21:
相反,如果您有一个很长的字符串值,并且需要在多行中拆分它,那么您可以用
\
字符转义换行。这些都可以通过下面的规则来演示,如图 15-21 所示:
h2::before {
content: "We insert this text before all H2 elements because \
it is a good idea to show how these things work. It may be a bit long \
but the point should be clearly made. ";
color: gray;
}
Inserting and suppressing newlines
You can also use escapes to refer to hexadecimal Unicode values, such as \00AB
.
您还可以使用转义来引用十六进制 Unicode 值,比如
\00AB
。
As of this writing, support for inserting escaped content such as \A
and \00AB
is not very widespread, even among those browsers that support some generated content.
With URI values, you simply point to an external resource (an image, movie, sound clip, or anything else the user agent supports), which is then inserted into the document in the appropriate place. If the user agent can’t support the resource you point it to for any reason—say, you try to insert an SVG image into a browser that doesn’t understand SVG, or try to insert a movie into a document when it’s being printed—then the user agent is required to ignore the resource completely, and nothing will be inserted.
使用 URI 值,您只需指向外部资源(图像、电影、声音剪辑或用户代理支持的任何其他东西),然后将其插入文档的适当位置。如果用户代理不支持任何 reason-say 资源你点,你试着将 SVG 图像插入不理解 SVG 浏览器,或尝试电影插入文档的时候被 printed-then 用户代理必须完全忽略的资源,而不是将插入。
There are situations where you might want to take the value of an element’s attribute and make it a part of the document display. To pick a simple example, you can place the value of every link’s href
attribute immediately after the links, like this:
在某些情况下,您可能希望获取元素属性的值,并将其作为文档显示的一部分。举一个简单的例子,你可以把每个链接的' href '属性的值放在链接之后,就像这样:
a[href]::after {
content: attr(href);
}
Again, this leads to the problem of the generated content running smack into the actual content. To solve this, add some string values to the declaration, with the result shown in Figure 15-22:
同样,这也会导致生成的内容与实际内容发生冲突。为了解决这个问题,向声明中添加一些字符串值,结果如图 15-22 所示:
a[href]::after {
content: " [" attr(href) "]";
}
Inserting URLs
This can be useful for print style sheets, as an example. Any attribute value can be inserted as generated content: alt
text, class
or id
values—anything. An author might choose to make the citation information explicit for a block quote, like this:
例如,这对于打印样式表非常有用。任何属性值都可以作为生成的内容插入:
alt
文本、class
或id
值——任何值。作者可以选择将引用信息显示为引用块,如下所示:
blockquote::after {
content: "(" attr(cite) ")";
display: block;
text-align: right;
font-style: italic;
}
For that matter, a more complicated rule might reveal the text- and link-color values for a legacy document:
就此而言,更复杂的规则可能会显示遗留文档的文本和链接颜色值:
body::before {
content: "Text: " attr(text) " | Link: " attr(link) " | Visited: " attr(vlink)
" | Active: " attr(alink);
display: block;
padding: 0.33em;
border: 1px solid;
text-align: center;
color: red;
}
Note that if an attribute doesn’t exist, an empty string is put in its place. This is what happens in Figure 15-23, in which the previous example is applied to a document whose body
element has no alink
attribute.
注意,如果属性不存在,则在其位置上放置一个空字符串。这就是图 15-23 所示的情况,在图 15-23 中,前面的示例应用于一个文档,该文档的
body
元素没有alink
属性。
Missing attributes are skipped
The text “Active: ” (including the trailing space) is inserted into the document, as you can see, but there is nothing following it. This is convenient in situations where you want to insert the value of an attribute only when it exists.
可以看到,文本“Active:”(包括末尾的空格)被插入到文档中,但是后面什么也没有。这对于只希望在属性存在时插入属性值的情况非常方便。
CSS2.x defines the returned value of an attribute reference as an unparsed string. Therefore, if the value of an attribute contains markup or character entities, they will be displayed verbatim.
A specialized form of generated content is the quotation mark, and CSS2.x provides a powerful way to manage both quotes and their nesting behavior. This is possible due to the pairing of content values like open-quote
and the property quotes
.
生成内容的特殊形式是引号和 CSS2。x 提供了一种强大的方法来管理引号及其嵌套行为。这是由于内容值(如“开引号”和属性“引号”)的匹配。
Upon studying the value syntax, we find that other than the keywords none
and inherit
, the only valid value is one or more pairs
of strings. The first string of the pair defines the open-quote symbol, and the second defines the close-quote symbol.
通过研究值语法,我们发现除了关键字
none
和inherit
之外,惟一的有效值是一个或多个字符串“对”。对的第一个字符串定义开引号符号,第二个字符串定义闭引号符号。
Therefore, of the following two declarations, only the first is valid:
因此,在下列两项声明中,只有第一项是有效的:
quotes: '"' "'"; /* valid */
quotes: '"'; /* NOT VALID */
The first rule also illustrates one way to put string quotes around the strings themselves. The double quotation marks are surrounded by single quotation marks, and vice versa.
第一个规则还演示了一种将字符串引号括在字符串本身周围的方法。双引号被单引号包围,反之亦然。
Let’s look at a simple example. Suppose you’re creating an XML format to store a list of favorite quotations. Here’s one entry in the list:
让我们看一个简单的例子。假设您要创建一种 XML 格式来存储最喜欢的引用列表。以下是其中一项:
<quotation>
<quote>I hate quotations.</quote>
<quotee>Ralph Waldo Emerson</quotee>
</quotation>
To present the data in a useful way, you could employ the following rules, with the result shown in Figure 15-24:
为了以一种有用的方式显示数据,您可以采用以下规则,结果如图 15-24 所示:
quotation: display: block;}
quote {quotes: '“' '”';}
quote::before {content: open-quote;}
quote::after {content: close-quote;}
quotee::before {content: " (";}
quotee::after {content: ")";}
Inserting quotes and other content
The values open-quote
and close-quote
are used to insert whatever quoting symbols are appropriate (since different languages have different quotation marks). They use the value of quotes to determine how they should work. Thus, the quotation begins and ends with a double quotation mark.
值
open-quote
和close-quote
用于插入任何适当的引用符号(因为不同的语言有不同的引号)。他们使用引号的值来决定它们应该如何工作。因此,引号以双引号开始和结束。
With quotes
, you can define quotation patterns to as many nesting levels as you like.
使用
quotes
,您可以根据需要将引号模式定义为任意多个嵌套层次。
In English, for example, a common practice is to start out with a double quotation mark, and a quotation nested inside the first one gets single quotation marks. This can be recreated with “curly” quotation marks using the following rules:
例如,在英语中,一种常见的做法是以双引号开始,嵌套在第一个引号内的引号将得到单引号。这可以用“花括号”引号重新创建使用以下规则:
quotation: display: block;}
quote {quotes: '\201C' '\201D' '\2018' '\2019';}
quote::before, q::before{content: open-quote;}
quote::after, q::after {content: close-quote;}
When applied to the following markup, these rules will have the effect shown in Figure 15-25:
当应用于以下标记时,这些规则的效果如图 15-25 所示:
<quotation>
<quote>
In the beginning, there was nothing. And God said:
<q>Let there be light!</q> And there was still nothing, but you could see
it.</quote
>
</quotation>
Nested curly quotes
In a case where the nested level of quotation marks is greater than the number of defined pairs, the last pair is reused for the deeper levels. Thus, if we had applied the following rule to the markup shown in Figure 15-25, the inner quote would have had double quotation marks, the same as the outer quote:
当应用于以下标记时,这些规则的效果如图 15-25 所示:
quote {
quotes: "\201C""\201D";
}
These particular rules used the hexadecimal Unicode positions for the “curly quote” symbols. If your CSS uses UTF-8 character encoding (and it really should), then you can skip the escaped hexadecimal position approach and just include the curly-quote characters directly, as in previous examples.
Generated quotes make possible one other common typographic effect. In situations where there are several paragraphs of quoted text, the close-quote
of each paragraph is often omitted; only the opening quote marks are shown, with the exception of the last paragraph. This can be recreated using the no-close-quote
value:
生成的引号使另一种常见的排版效果成为可能。在有多个引用段落的情况下,每个段落的
close-quote
常常被省略;除最后一段外,只显示开头的引号。这可以用no-close-quote
值重新创建:
blockquote {
quotes: '"' '"' "'" "'" '"' '"';
}
blockquote p::before {
content: open-quote;
}
blockquote p::after {
content: no-close-quote;
}
This will start each paragraph with a double quotation mark but no closing mark.
这将以双引号开始每个段落,但没有结束标记。
This is true of the last paragraph as well, so if you need to add a closing quote mark, you’d need to class the final paragraph and declare a close-quote
for its ::after content
.
这也适用于最后一段,所以如果您需要添加一个结束引号,您需要对最后一段进行分类,并为它的
::after content
声明一个close-quote
。
This value is important because it decrements the quotation nesting level without actually generating a symbol. This is why each paragraph starts with a double quotation mark, instead of alternating between double and single marks until the third paragraph is reached. no-close-quote
closes the quotation nesting at the end of each paragraph, and thus every paragraph starts at the same nesting level.
这个值很重要,因为它在不实际生成符号的情况下降低了引号嵌套级别。这就是为什么每个段落都以双引号开头,而不是双引号和单引号交替使用,直到进入第三段。
no-close-quote
在每个段落末尾结束嵌套,因此每个段落都在相同的嵌套级别开始。
This is significant because, as the CSS2.1 specification notes, “Quoting depth is independent of the nesting of the source document or the formatting structure.” In other words, when you start a quotation level, it persists across elements until a close-quote
is encountered, and the quote nesting level is decremented.
这一点很重要,因为正如 CSS2.1 规范所指出的,“引用深度与源文档嵌套或格式结构无关。换句话说,当您开始一个引用级别时,它会跨元素持续存在,直到遇到一个
close-quote
,并且引用嵌套级别降低。
For the sake of completeness, there is a no-open-quote
keyword, which has a symmetrical effect to no-close-quote
. This keyword increments the quotation nesting level by one but does not generate a symbol.
为了完整起见,这里有一个
no-open-quote
关键字,它与no-close-quote
具有对称效果。此关键字将引号嵌套级别增加 1,但不生成符号。
We’re all familiar with counters; for example, the markers of the list items in ordered lists are counters. In CSS1, there was no way to affect them, largely because there was no need: HTML defined its own counting behaviors for ordered lists, and that was that. With the rise of XML, it’s now important to provide a method by which counters can be defined. CSS2 was not content to simply provide for the kind of simple counting found in HTML, however. Two properties and two content
values make it possible to define almost any counting format, including subsection counters employing multiple styles, such as “VII.2.c.”
我们都熟悉计数器;例如,有序列表中列表项的标记是计数器。在 CSS1 中,没有方法可以影响它们,这主要是因为没有必要:HTML 为有序列表定义了自己的计数行为,仅此而已。随着 XML 的兴起,现在提供一种可以定义计数器的方法很重要。然而,CSS2 并不满足于简单地提供 HTML 中常见的那种简单计数。两个属性和两个
content
值使得几乎可以定义任何计数格式,包括使用多种样式的子计数器,如“VII.2.c”。
The basis of creating counters is the ability to set both the starting point for a counter and to increment it by some amount. The former is handled by the property counter-reset
.
创建计数器的基础是同时设置计数器的起始点和按一定数量增加计数器的能力。前者由属性
counter-reset
处理。
A counter identifier
is simply a label created by the author. For example, you might name your subsection counter subsection
, subsec
, ss
, or bob
. The simple act of resetting (or incrementing) an identifier is sufficient to call it into being. In the following rule, the counter chapter
is defined as it is reset:
计数器
identifier
只是作者创建的一个标签。例如,你可以将你的子条目命名为subsection
,subsec
,ss
或bob
。重置(或递增)标识符的简单操作就足以调用它。在下面的规则中,计数器chapter
被定义为重置:
h1 {
counter-reset: chapter;
}
By default, a counter is reset to zero. If you want to reset to a different number, you can declare that number following the identifier:
默认情况下,计数器被重置为零。如果你想重置为一个不同的数字,你可以声明该数字以下的标识符:
h1#ch4 {
counter-reset: Chapter 4;
}
You can also reset multiple identifiers all at once in identifier-integer pairs. If you leave out an integer, then it defaults to zero:
还可以在标识符-整数对中一次性重置多个标识符。如果你省略了一个整数,那么它默认为 0:
h1 {
counter-reset: Chapter 4 section -1 subsec figure 1;
}
/* 'subsec' is reset to 0 */
As you can see from the previous example, negative values are permitted. It would be perfectly legal to set a counter to -32768
and count up from there.
从前面的示例中可以看到,允许使用负值。设置计数器为
-32768
并从那里开始计数是完全合法的。
CSS does not define what user agents should do with negative counter values in nonnumeric counting styles. For example, there is no defined behavior for what to do if a counter’s value is -5
but its display style is upper-alpha
.
To count up, you’ll need a property to indicate that an element increments a counter. Otherwise, the counter would remain at whatever value it was given with a counter-reset
declaration. The property in question is, not surprisingly, counter-increment
.
要进行计数,您需要一个属性来指示一个元素递增一个计数器。否则,计数器将保持
counter-reset
声明所赋予的任何值。毫无疑问,这个属性就是counter-increment
。
Like counter-reset
, counter-increment
accepts identifier-integer pairs, and the integer portion of these pairs can be zero or negative as well as positive. The difference is that if an integer is omitted from a pair in counter-increment
, it defaults to 1, not 0.
与
counter-reset
类似,counter-increment
接受标识整数对,这些对的整数部分可以是 0 或负的,也可以是正的。不同之处在于,如果一个整数在counter-increment
中从一对中被省略,它的默认值是 1,而不是 0。
As an example, here’s how a user agent might define counters to recreate the traditional 1, 2, 3 counting of ordered lists:
例如,用户代理可以定义计数器来重新创建传统的有序列表的 1、2、3 计数:
ol {
counter-reset: ordered;
} /* defaults to 0 */
ol li {
counter-increment: ordered;
} /* defaults to 1 */
On the other hand, an author might want to count backward from zero so that the list items use a rising negative system. This would require only a small edit:
另一方面,作者可能希望从 0 开始倒数,以便列表项使用递增负号系统。这将只需要一个小编辑:
ol {
counter-reset: ordered;
} /* defaults to 0 */
ol li {
counter-increment: ordered -1;
}
The counting of lists would then be -1, -2, -3
and so on. If you replaced the integer -1
with -2
, then lists would count -2, -4, -6
and so on.
列表的计数将是
-1, -2, -3
等等。如果将整数-1
替换为-2
,则列表将计数-2, -4, -6
,依此类推。
To actually display the counters, though, you need to use the content
property in conjunction with one of the counter-related values. To see how this works, let’s use an XML-based ordered list like this:
但是,要实际显示计数器,需要将
content
属性与一个与计数器相关的值一起使用。为了了解它是如何工作的,让我们使用一个基于 xml 的有序列表,如下所示:
<list type="ordered">
<item>First item</item>
<item>Item two</item>
<item>The third item</item>
</list>
By applying the following rules to XML employing this structure, you would get the result shown in Figure 15-26:
通过将下面的规则应用到使用这种结构的 XML 中,您将得到如图 15-26 所示的结果:
list[type="ordered"] {
counter-reset: ordered;
} /* defaults to 0 */
list[type="ordered"] item {
display: block;
}
list[type="ordered"] item::before {
counter-increment: ordered;
content: counter(ordered) ". ";
margin: 0.25em 0;
}
Counting the items
Note that the generated content is, as usual, placed as inline content at the beginning of the associated element. Thus, the effect is similar to an HTML list with list-style-position: inside;
declared.
请注意,与往常一样,生成的内容被作为内联内容放置在关联元素的开头。因此,其效果类似于声明了
list-style-position: inside;
的 HTML 列表。
Note also that the item
elements are ordinary elements generating block-level boxes, which means that counters are not restricted only to elements with a display
of list-item
. In fact, any element can make use of a counter. Consider the following rules:
还要注意,
item
元素是生成块级框的普通元素,这意味着计数器不局限于display
为list-item
的元素。事实上,任何元素都可以使用计数器。考虑以下规则:
h1 {
counter-reset: section subsec;
counter-increment: chapter;
}
h1::before {
content: counter(chapter) ". ";
}
h2 {
counter-reset: subsec;
counter-increment: section;
}
h2::before {
content: counter(chapter) "." counter(section) ". ";
}
h3 {
counter-increment: subsec;
}
h3::before {
content: counter(chapter) "." counter(section) "." counter(subsec) ". ";
}
These rules would have the effect shown in Figure 15-27.
这些规则的效果如图 15-27 所示。
Figure 15-27 illustrates some important points about counter resetting and incrementing. For instance, notice how the counters are reset on the elements, whereas the actual generated-content counters are inserted via the ::before
pseudo-elements. Attempting to reset counters in the pseudo-elements won’t work: you’ll get a lot of zeroes. You can increment them either on the elements or in the pseudo-elements, as you prefer.
图 15-27 说明了有关计数器重置和递增的一些要点。例如,请注意如何在元素上重置计数器,而实际生成的内容计数器是通过
::before
伪元素插入的。尝试重置伪元素中的计数器是行不通的:您将得到许多 0。您可以在元素或伪元素上增加它们,这取决于您的喜好。
Adding counters to headings
Also notice how the h1
element uses the counter chapter
, which defaults to zero and has a “1.” before the element’s text. When a counter is incremented and used by the same element, the incrementation happens before
the counter is displayed. In a similar way, if a counter is reset and shown in the same element, the reset happens before the counter is displayed. Consider:
还请注意
h1
元素是如何使用计数器chapter
的,它的默认值是 0,并有一个“1”。元素的文本之前。当计数器被相同的元素递增并使用时,递增发生在计数器显示之前。以类似的方式,如果计数器被重置并显示在相同的元素中,则重置将在计数器显示之前发生。考虑:
h1::before,
h2::before,
h3::before {
content: counter(chapter) "." counter(section) "." counter(subsec) ". ";
}
h1 {
counter-reset: section subsec;
counter-increment: chapter;
}
The first h1
element in the document would be preceded by the text “1.0.0. ” because the counters section
and subsec
were reset, but not incremented. This means that if you want the first displayed instance of an incremented counter to be 0, then you need to reset that counter to -1
, as follows:
文档中的第一个
h1
元素前面是文本“1.0.0”。“因为计数器section
和subsec
被重置了,但没有增加。这意味着,如果你想要一个递增的计数器的第一个显示实例为 0,那么你需要将该计数器重置为-1
,如下所示:
body {
counter-reset: chapter -1;
}
h1::before {
counter-increment: chapter;
content: counter(chapter) ". ";
}
You can do some interesting things with counters. Consider the following XML:
你可以用计数器做一些有趣的事情。考虑以下 XML:
<code type="BASIC">
<line>PRINT "Hello world!"</line>
<line>REM This is what the kids are calling a "comment"</line>
<line>GOTO 10</line>
</code>
You can recreate the traditional format of a BASIC program listing with the following rules:
你可以用以下规则重新创建一个基本程序列表的传统格式:
code[type="BASIC"] {
counter-reset: linenum;
font-family: monospace;
}
code[type="BASIC"] line {
display: block;
}
code[type="BASIC"] line::before {
counter-increment: linenum;
content: counter(linenum 10) ": ";
}
It’s also possible to define a list style for each counter as part of the counter( )
format. You can do this by adding a comma-separated list-style-type
keyword after the counter’s identifier. The following modification of the heading-counter example is illustrated in Figure 15-28:
还可以将每个计数器的列表样式定义为
counter( )
格式的一部分。您可以通过在计数器的标识符后面添加一个逗号分隔的list-style-type
关键字来实现这一点。下面对 head-counter 示例的修改如图 15-28 所示:
h1 {
counter-reset: section subsec;
counter-increment: chapter;
}
h1::before {
content: counter(chapter, upper-alpha) ". ";
}
h2 {
counter-reset: subsec;
counter-increment: section;
}
h2::before {
content: counter(chapter, upper-alpha) "." counter(section) ". ";
}
h3 {
counter-increment: subsec;
}
h3::before {
content: counter(chapter, upper-alpha) "." counter(section) "." counter(
subsec,
lower-roman
) ". ";
}
Changing counter styles
Notice that the counter section
was not given a style keyword, so it defaulted to the decimal counting style. You can even set counters to use the styles disc
, circle
, square
, and none
if you so desire.
注意,计数器“section”没有提供样式关键字,因此它默认为十进制计数样式。您甚至可以设置计数器来使用样式“disc”、“circle”、“square”和“none”,如果您愿意的话。
One interesting point to note is that elements with a display
of none
do not increment counters, even if the rule seems to indicate otherwise. In contrast, elements with a visibility
of hidden
do increment counters:
值得注意的一点是,' display '为' none '的元素不会增加计数器,即使规则似乎表明不是这样。相反,具有“可见性”的“隐藏”元素会增加计数器:
.suppress {
counter-increment: cntr;
display: none;
}
/* 'cntr' is NOT incremented */
.invisible {
counter-increment: cntr;
visibility: hidden;
}
/* 'cntr' IS incremented */
So far, we’ve seen how to string multiple counters together to create section-andsubsection counting. Often, this is something authors desire for nested ordered lists as well, but it would quickly become clumsy to try to create enough counters to cover deep nesting levels. Just to get it working for five-level-deep nested lists would require a bunch of rules like this:
到目前为止,我们已经了解了如何将多个计数器连接在一起来创建分段计数和分段计数。通常,这也是作者希望嵌套的有序列表所具有的特性,但是如果试图创建足够的计数器来覆盖深度嵌套级别,那么很快就会变得很笨拙。为了让它在五层深嵌套列表中工作,需要一堆这样的规则:
ol ol ol ol ol li::before {
counter-increment: ord1 ord2 ord3 ord4 ord5;
content: counter(ord1) "." counter(ord2) "." counter(ord3) "." counter(ord4)
"." counter(ord5) ".";
}
Imagine writing enough rules to cover nesting up to 50 levels! (I’m not saying you should nest ordered lists 50 deep. Just follow along for the moment.)
想象一下,编写足够多的规则来覆盖高达 50 个级别的嵌套!(我不是说你应该嵌套有序列表 50 深。现在就跟着做吧。)
Fortunately, CSS2.x described the concept of scope
when it comes to counters. Stated simply, every level of nesting creates a new scope for any given counter. Scope is what makes it possible for the following rules to cover nested-list counting in the usual HTML way:
幸运的是,CSS2。x 描述了计数器的
scope
概念。简单地说,每一层嵌套都会为任何给定的计数器创建一个新的作用域。作用域是使以下规则以通常的 HTML 方式覆盖嵌套列表计数成为可能的因素:
ol {
counter-reset: ordered;
}
ol li::before {
counter-increment: ordered;
content: counter(ordered) ". ";
}
These rules will all make ordered lists, even those nested inside others, start counting from 1 and increment each item by one—exactly how it’s been done in HTML from the beginning.
这些规则都将创建有序的列表,即使是嵌套在其他列表中的列表,也将从 1 开始计数,并将每个项增加 1—这与在 HTML 中从一开始就做的一样。
This works because a new instance of the counter ordered
is created at each level of nesting. So, for the first ordered list, an instance of ordered
is created. Then, for every list nested inside the first one, another new instance is created, and the counting starts anew with each list.
这是因为在每一层嵌套中都会创建一个新的计数器
ordered
实例。因此,对于第一个有序列表,将创建一个ordered
实例。然后,对于嵌套在第一个列表中的每个列表,将创建另一个新实例,并对每个列表重新进行计数。
However, suppose you want ordered lists to count so that each level of nesting creates a new counter appended to the old: 1, 1.1, 1.2, 1.2.1, 1.2.2, 1.3, 2, 2.1, and so on. This can’t be done with counter( )
, but it can
be done with counters( )
. What a difference an “s” makes.
但是,假设您希望有序列表计数,以便每一层嵌套都创建一个新计数器,该计数器追加到旧的计数器上:1、1.1、1.2、1.2.1、1.2.2、1.3、2、2.1 等等。这不能用
counter( )
来完成,但是可以用counters( )
来完成。一个“s”会带来多大的不同。
To create the nested-counter style shown in Figure 15-29, you need these rules:
要创建如图 15-29 所示的嵌套计数器样式,您需要以下规则:
ol {
counter-reset: ordered;
list-style: none;
}
ol li:before {
content: counters(ordered, ".") ": ";
counter-increment: ordered;
}
Nested counters
Basically, the keyword counters(ordered,".")
displays the ordered
counter from each scope with a period appended, and strings together all of the scoped counters for a given element. Thus, an item in a third-level-nested list would be prefaced with the ordered
value for the outermost list’s scope, the scope of the list between the outer and current list, and the current list’s scope, with each of those followed by a period. The rest of the content
value causes a space, hyphen, and space to be added after all of those counters.
基本上,关键字
counters(ordered,".")
显示来自每个作用域的ordered
计数器,并附加一个句点,将给定元素的所有作用域计数器串在一起。因此,第三层嵌套列表中的项将以ordered
值作为前缀,该值表示最外层列表的作用域、外部列表和当前列表之间的列表作用域,以及当前列表的作用域,每个作用域后面都有一个句点。content
值的其余部分导致在所有这些计数器之后添加空格、连字符和空格。
As with counter( )
, you can define a list style for nested counters, but the same style applies to all of the counters. Thus, if you changed your previous CSS to read as follows, the list items in Figure 15-29 would all use lowercase letters for the counters instead of numbers:
与
counter( )
一样,您可以为嵌套的计数器定义一个列表样式,但是相同的样式适用于所有的计数器。因此,如果您将之前的 CSS 改为如下所示,那么图 15-29 中的列表项都将使用小写字母表示计数器,而不是数字:
ol li::before {
counter-increment: ordered;
content: counters(ordered, ".", lower-alpha) ": ";
}
You may have noticed that list-style: none
was applied to the ol
elements in the previous examples. That’s because the counters being inserted were generated content, not replacement list markers. In other words, had the list-style: none
been left out, each list item would have had its user agent-supplied list counter, plus
the generated-content counters we defined.
您可能已经注意到,在前面的示例中,
list-style: none
应用于ol
元素。这是因为要插入的计数器是生成的内容,而不是替换列表标记。换句话说,如果去掉list-style: none
,每个列表项都将有其用户代理提供的列表计数器,plus
我们定义的生成内容计数器。
That ability can be very useful, but sometimes you really just want to redefine the markers themselves. That’s where counting patterns come in.
这种能力可能非常有用,但有时您真的只想重新定义标记本身。这就是计数模式的用武之地。
In recent years, a new method of defining counter patterns has arisen in CSS. It uses the @counter-style
block format, with a number of dedicated descriptors to manage the outcome. The general pattern is:
近年来,在 CSS 中出现了一种定义计数器模式的新方法。它使用
@counter-style
块格式,使用许多专用的描述符来管理结果。一般的模式是:
@counter-style <name> {
…declarations…
}
where <name>
is an author-supplied name for the pattern in question. For example, to create a series of alternating triangle markers, the block might look something like this:
其中
<name>
是作者提供的模式名称。例如,要创建一系列交替的三角形标记,块可能看起来像这样:
@counter-style triangles {
system: cyclic;
symbols: ▶ ▷;
}
This would have the result shown in Figure 15-30.
结果如图 15-30 所示。
A simple counter pattern
As of early 2017, @counter-style
and the related topics discussed in this section were only supported by the Firefox family of browsers. They’re fun to use, but don’t rely on them in copy—that is, don’t say things like “refer to step 1A” if your counters are being generated using @counter-style
.
There are a number of descriptors available, summarized here.
有许多可用的描述符,总结在这里。
We’ll start with simple systems and work our way up in complexity, but first, let’s see the precise definitions for the two most basic descriptors: system
and symbols
.
我们将从简单的系统开始,逐步增加复杂性,但首先,让我们看看两个最基本的描述符:
system
和symbols
的精确定义。
For pretty much any @counter-style
block, those are the minimum two descriptors. You can leave out system
if you’re defining a symbolic
system, but it’s generally better to include it so that you’re clear about what kind of system you’re setting up. Remember, the next person to work on the styles may not be as familiar with counter styling as you!
对于几乎所有的
@counter-style
块,这是最小的两个描述符。如果你要定义一个symbolic
系统,你可以省略system
,但是通常最好包括它,这样你就能清楚地知道你要建立什么样的系统。请记住,下一个处理样式的人可能不像您这样熟悉反样式!
The simplest kind of counter pattern is a fixed
system. Fixed systems are used in cases where you want to define an exact sequence of counter markers that doesn’t repeat once you’ve run out of markers. Consider this example, which has the result shown in Figure 15-31:
最简单的反模式是“固定”系统。固定的系统用于您想要定义一个精确的计数器标记序列的情况,该序列在您用完标记之后不会重复。考虑这个例子,其结果如图 15-31 所示:
@counter-style emoji {
system: fixed;
symbols: ;
ul.emoji {list-style: emoji;}
A fixed counter pattern
Once the list gets past the fifth list item, the counter system runs out of emoji, and since no fallback was defined (we’ll get to that shortly), the markers for subsequent list items fall back to the default for unordered lists.
一旦列表通过了第五个列表项,计数器系统就会用完表情符号,由于没有定义回退(我们很快就会讲到),后续列表项的标记就会回到无序列表的默认值。
Notice that the symbols in the symbols
descriptor are space-separated. If they were all jammed together with no space separation, as shown here, you’d get the result something like that seen in Figure 15-32:
注意,
symbols
描述符中的符号是空格分隔的。如果它们都挤在一起,没有空间分隔,如图所示,您将得到如图 15-32 所示的结果:
@counter-style emoji {
system: fixed;
symbols: ;
}
ul.emoji {
list-style: emoji;
}
When symbols get too close
This does mean you can define a fixed sequence of markers where each marker is composed of multiple symbols. (If you want to define a set of symbols that are combined in patterns to create a counting system, just wait: we’re getting to that soon.)
这意味着您可以定义一个固定的标记序列,其中每个标记由多个符号组成。(如果你想定义一组组合在一起的符号来创建一个计数系统,那就等着吧:我们很快就会讲到。)
If you want to use ASCII symbols in your markers, it’s generally advisable to quote them. This avoids problems like angle brackets being mistaken for pieces of HTML by the parser. Thus you might do something like:
如果您想在标记中使用 ASCII 符号,通常建议引用它们。这避免了诸如尖括号被解析器误认为 HTML 片段之类的问题。因此,你可以这样做:
@counter-style emoji {
system: fixed;
symbols: #$ % ">";
}
It’s acceptable to quote all symbols, and it might be a good idea to get into the habit.
引用所有符号是可以接受的,养成习惯可能是个好主意。
That means more typing—the value above would become "#" "$" "%" ">"
—but it’s less error-prone.
这意味着更多的类型——上面的值将变成
"#" "$" "%" ">"
——但它更不容易出错。
In fixed counter systems, you can define a starting value in the system
descriptor itself. If you want to start the counting at 5, for example, you’d write:
在固定的计数器系统中,您可以在
system
描述符本身中定义一个初始值。例如,如果你想从 5 开始计算,你可以这样写:
@counter-style emoji {
system: fixed 5;
symbols: ;
}
ul.emoji {
list-style: emoji;
}
In this case, the first five symbols represent counters 5 through 9. If the fallback counter style is decimal numbers, then the sixth counter in the sequence would have a value of 10 (in upper-Roman, it would be “J”).
在本例中,前 5 个符号表示计数器 5 到 9。如果回退计数器样式是十进制数,那么序列中的第六个计数器的值将是 10(用大写字母表示,它将是“J”)。
This ability to set a starting number is not
available in any of the other counter system types.
The next step beyond fixed patterns is cyclic patterns. These are simply fixed patterns that repeat. Let’s take the fixed emoji pattern from the previous section and convert it to be cyclic. This will have the result shown in Figure 15-33:
超越固定模式的下一步是循环模式。这些只是重复的固定模式。让我们把上一节中固定的表情符号模式转换成循环的。结果如图 15-33 所示:
@counter-style emojiverse {
system: cyclic;
symbols: ;
}
ul.emoji {
list-style: emojiverse;
}
A cyclic counter pattern
The defined symbols are used in order, over and over, until there are no more markers left in the counting sequence.
所定义的符号是按顺序反复使用的,直到计数序列中没有剩余的标记为止。
It’s possible to use cyclic
to supply a single marker that’s used for the entire pattern, much in the manner of supplying a string for list-style-type
. In this case, it would look something like this:
可以使用
cyclic
来提供用于整个模式的单个标记,就像为list-style-type
提供字符串一样。在这种情况下,它看起来是这样的:
@counter-style thinker {
system: cyclic;
symbols: ;
/* equivalent to list-style-type: " " */
}
ul.hmmm {
list-style: thinker;
}
One thing you may have noticed is that so far, all our counters have been followed by a full stop (or a period, if you prefer). This is due to the default value of the suffix
descriptor. suffix
has a cousin descriptor, prefix
.
您可能已经注意到,到目前为止,我们所有的计数器后面都有一个句号(或句号,如果您愿意)。这是由于
suffix
描述符的默认值。suffix
有一个表兄描述符prefix
。
With these descriptors, you can define symbols that are inserted before and after every marker in the pattern. Thus, we might give our thinker ASCII wings like so, as illustrated in Figure 15-34:
使用这些描述符,您可以定义插入模式中每个标记之前和之后的符号。因此,我们可以像图 15-34 中所示的那样,为我们的思想家 ASCII 设置翼:
@counter-style wingthinker {
system: cyclic;
symbols: ;
prefix: "~";
suffix: "~";
}
ul.hmmm {
list-style: wingthinker;
}
Putting “wings” on the thinker
suffix
is particularly useful if you want to remove the default suffix from your markers. Here’s one example of how to do so:
suffix
是特别有用的,如果你想删除默认后缀从您的标记。下面是如何做到这一点的一个例子:
@counter-style thisisfine {
system: cyclic;
symbols: ;
suffix: "";
}
Of course, you could also extend the markers in creative ways using prefix
and suffix
, as shown in Figure 15-35:
当然,您也可以使用
prefix
和suffix
创造性地扩展标记,如图 15-35 所示:
@counter-style thisisfine {
system: cyclic;
symbols: ;
prefix: " ";
suffix: ;
}
This list is fine
You might wonder why the prefix
value was quoted in that example, while the suffix
value was not. There was literally no reason other than to demonstrate that both approaches work. As stated before, quoting symbols is safer, but it’s rarely required.
您可能想知道为什么在这个示例中引用了
prefix
值,而没有引用suffix
值。除了证明这两种方法都有效外,没有其他理由。如前所述,引用符号更安全,但很少需要。
You may also see (or already been seeing) some differences between the Unicode glyphs in the CSS examples here, and those shown in the figures. This is an unavoidable aspect of using emoji and other such characters—what appears on one person’s user agent may be different on someone else’s. Just to pick one example: the differences in emoji rendering between Mac OS, iOS, Android, Samsung, Windows desktop, Windows mobile, Linux, and so on.
您还可以看到(或已经看到)这里的 CSS 示例中的 Unicode 符号与图中所示的符号之间的一些差异。这是使用表情符号和其他类似字符时不可避免的一个方面——在一个人的用户代理上出现的内容可能在其他人的用户代理上有所不同。举个例子:苹果操作系统、iOS、安卓、三星、Windows 桌面、Windows 移动、Linux 等操作系统在表情符号呈现上的差异。
Keep in mind that you can use images for your counters, at least in theory. As an example, suppose you want to use a series of Klingon glyphs, which have no Unicode equivalents. (It’s a longstanding industry myth that Klingon is in Unicode. It was proposed in 1997 and rejected in 2001. A new proposal was made in 2016, with no resolution as of this writing.) We won’t represent the entire set of symbols here, but it would start something like this:
请记住,您可以使用图像作为计数器,至少在理论上是这样。例如,假设您想要使用一系列 Klingon 字形,它们没有对应的 Unicode 字符。(长久以来,业界一直认为 Klingon 使用 Unicode。1997 年提出,2001 年被否决。2016 年提出了一项新提案,截至撰写本文时还没有决议。)我们不会代表所有的符号,但是它可以这样开头:
@counter-style klingon-letters {
system: cyclic;
symbols: url(i/klingon-a.svg) url(i/klingon-b.svg) url(i/klingon-ch.svg)
url(i/klingon-d.svg) url(i/klingon-e.svg) url(i/klingon-gh.svg);
suffix: url(i/klingon-full-stop.svg);
}
This would cycle from A through GH and then repeat, but still, you’d get some Klingon symbology, which might be enough. We’ll see ways to build up alphabetic and numeric systems later in the chapter.
这将从 A 循环到 GH,然后重复,但你仍然会得到一些克林贡符号,这可能就足够了。我们将在本章后面看到如何建立字母和数字系统。
As of early 2017, browser support for images as counting symbols was essentially nonexistent.
A symbolic
counting system is similar to a cyclic system, except in symbolic systems, the symbols add a repetition on each restart of the symbol sequence. This may be familiar to you from footnote symbols, or some varieties of alphabetic systems. Examples of each are shown here, with the result shown in Figure 15-36:
symbolic
计数系统类似于循环系统,除了在符号系统中,符号在每次重新启动符号序列时都会增加重复。这可能是你熟悉的脚注符号,或一些品种的字母系统。每种方法的示例如图 15-36 所示:
@counter-style footnotes {
system: symbolic;
symbols: "*" "†" "§";
suffix: " ";
}
@counter-style letters {
system: symbolic;
symbols: A B C D E;
}
Two patterns of symbolic counting
One thing to watch out for is that if you only have a few symbols applied to a very long list, the markers will quickly get quite large. Consider the letter counters shown in the previous example. Figure 15-37 shows what the 135th through 150th entries in a list using that system would look like.
需要注意的一件事是,如果您只有几个符号应用到一个非常长的列表中,那么标记将很快变得非常大。考虑前面示例中显示的字母计数器。图 15-37 显示了使用该系统的列表中的第 135 到 150 个条目的样子。
Very long symbolic markers
This sort of consideration will become more of an issue from here on out, because the counter styles are all additive in one sense or another. There is a way to limit your exposure to these kinds of problems: the range
descriptor.
从现在开始,这种考虑将成为一个更大的问题,因为计数器样式在某种意义上都是可添加的。有一种方法可以限制您对这类问题的暴露:
range
描述符。
With range
, you can supply one or more space-separated pairs of values, with each pair separated from the others by commas. Let’s suppose we want to stop the letterdoubling after three iterations. There are five symbols, so we can restrict their use to the range of 1-15 like so, with the result shown in Figure 15-38 (which has been arranged in two columns to keep the figure size reasonable):
使用
range
,您可以提供一个或多个空格分隔的值对,每对之间用逗号分隔。假设我们希望在三次迭代之后停止字母重复。有 5 个符号,所以我们可以像这样将它们的使用范围限制在 1-15 之间,结果如图 15-38 所示(为了保持图形大小合理,将其排列成两列):
@counter-style letters {
system: symbolic;
symbols: A B C D E;
range: 1 15;
}
Using range to limit a symbolic counter pattern
If there were, for whatever reason, a need to supply a second range of counter usage, it would look like this:
如果出于某种原因需要提供第二个范围的计数器使用,它应该是这样的:
@counter-style letters {
system: symbolic;
symbols: A B C D E;
range: 1 15, 101 115;
}
In that case, the symbolic letter system defined by letters
would be applied in the range 1-15, and also 101-115 (which would be “AAAAAAAAAAAAAAAAAAAAA” through “EEEEEEEEEEEEEEEEEEEEEEE,” rather appropriately).
在这种情况下,由“字母”定义的符号字母系统将在 1-15 和 101-115 范围内应用(从“AAAAAAAAAAAAAAAAAAAAA”到“eeeeeeeeeeeeeeeee,”相当合适)。
So what happens to the counters that fall outside of the range(s) defined by range
? They fall back to a default marker style. You can leave that up to the user agent to handle, or you can provide some direction by means of the fallback
descriptor.
那么,超出
range
定义的范围的计数器会发生什么情况?它们回到默认的标记样式。您可以将其留给用户代理来处理,或者您可以通过fallback
描述符提供一些方向
As an example, you might decide to handle any beyond-the-range counters with Hebrew counting.
例如,您可能决定使用希伯来计数处理任何超出范围的计数器。
@counter-style letters {
system: symbolic;
symbols: A B C D E;
range: 1 15, 101 115;
fallback: hebrew;
}
You could just as easily use lower-greek
, upper-latin
, or even a non-counting style like square.
你可以很容易地使用
lower-greek
,upper-latin
,甚至是像 square 这样的非计数风格。
This will also be the style used as a fallback in any system where a counter can’t be represented by the primary system, for whatever reason. A simple example is a counting system that uses images for its symbols, and one of the images fails to load. In the following, assume south.svg
fails to load. In that case, the missing image would be replaced with a lower-latin
counter representing the value of the current item:
在任何系统中,如果由于某种原因,主系统不能表示计数器,那么也可以使用这种样式作为回退。一个简单的例子是一个使用图像作为其符号的计数系统,其中一个图像无法加载。在下面,假设
south.svg
加载失败。在这种情况下,缺失的图像将被替换为代表当前项的值的lower-latin
计数器:
@counter-style compass {
system: symbolic;
symbols: url(north.svg) url(east.svg) url(south.svg) url(west.svg);
fallback: lower-latin;
}
An alpahbetic
counting system is very similar to a symbolic
system, except the manner of repeating changes. Remember, with symbolic counting, the number of symbols goes up with each iteration through the cycle. In alphabetic systems, each symbol is treated as a digit in a numbering system. If you’ve spent any time in spread‐sheets, this counting method may be familiar to you from the column labels.
一个
alpahbetic
计数系统非常类似于一个symbolic
系统,除了重复变化的方式。记住,使用符号计数,符号的数量随着循环的每次迭代而增加。在字母系统中,每个符号在编号系统中被视为一个数字。如果你花了时间在列表上,这种计数方法对你来说可能很熟悉。
To illustrate this, let’s reuse the letter symbols from the previous section, and change from a symbolic to an alphabetic system. The result is shown in Figure 15-39 (once again formatted as two columns for compactness’ sake):
为了说明这一点,让我们重新使用前一节中的字母符号,并将符号系统改为字母系统。结果如图 15-39 所示(为了紧凑起见,再次格式化为两列):
@counter-style letters {
system: alphabetic;
symbols: A B C D E;
/* once more cut off at 'E' to show the pattern’s effects more quickly */
}
Alphabetic counting
Notice how the second iteration of the pattern, which runs from “AA” to “AE” before switching over to “BA” through “BE”, then on to “CA” and so on. In the symbolic version of this, we’d already be up to “EEEEEE” by the time “EE” was reached in the alphabetic system.
注意模式的第二次迭代,从“AA”运行到“AE”,然后从“BE”切换到“BA”,然后再切换到“CA”,等等。在这个符号版本中,当字母系统中的“EE”到达时,我们已经达到了“EEEEEE”。
Note that in order to be valid, an alphabetic system must have a minimum of two
symbols supplied in the symbols
descriptor. If only one symbol is supplied, the entire @counter-style
block is rendered invalid. Any two symbols are valid; they can be letters, numbers, or really anything in Unicode, as well as images (again, in theory).
请注意,为了有效,字母系统必须在“符号”描述符中提供至少
two
符号。如果只提供一个符号,则整个@counter-style
块将无效。任意两个符号有效;它们可以是字母、数字或 Unicode 中的任何东西,也可以是图像(同样,在理论上)。
When you define a numeric
system, you’re technically using the symbols you supply to define a positional numbering
system. That is, the symbols are used as digits in a place-number counting system. Defining ordinary decimal counting, for example, would be done like this:
当您定义一个
numeric
系统时,您实际上是在使用您提供的符号来定义一个positional numbering
系统。也就是说,这些符号在一个地点数字计数系统中被用作数字。例如,定义普通十进制计数可以这样做:
@counter-style decimal {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
}
This is easily extensible to create hexadecimal counting, like so:
这是很容易扩展,以创建十六进制计数,像这样:
@counter-style hexadecimal {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F";
}
This will count from 1 through F, roll over to 10 and count up to 1F, then 20 to 2F, 30 to 3F, etc. Much more simply, it’s a breeze to set up binary counting:
从 1 数到 F,转到 10,一直数到 1F,然后从 20 数到 2F,从 30 数到 3F,等等。更简单的是,设置二进制计数很容易:
@counter-style binary {
system: numeric;
symbols: "0" "1";
}
Examples of each of those three counting patterns are shown in Figure 15-40.
图 15-40 显示了这三种计数模式的每个示例。
Three numeric counting patterns
An interesting question to consider is: what happens if a counter value is negative? In decimal counting, we generally expect negative numbers to be preceded by a minus sign (-
), but what about in other systems, like symbolic? What if we define a letterbased numeric counting system? Or if we want to use accounting-style formatting, which puts negative values into parentheses? This is where the negative
descriptor comes into play.
一个值得考虑的有趣问题是:如果计数器的值是负数,会发生什么?在十进制计数中,我们通常希望负数前面有一个负号(
-
),但是在其他系统中呢,比如符号系统?如果我们定义一个基于字母的数字计数系统呢?或者,如果我们想使用会计风格的格式,将负值放在括号中?这就是negative
描述符发挥作用的地方。
negative
is like its own little self-contained combination of prefix
and suffix
, but is only applied in situations where the counter is a negative value. Its symbols are placed inside the prefix and suffix symbols.
negative
类似于prefix
和suffix
的独立组合,但仅适用于计数器为负数的情况。它的符号被放在前缀和后缀符号里面。
So let’s say we want to use accounting-style formatting, and also add prefix and suffix symbols to all counters. That would be done as follows, with the result shown in Figure 15-41:
因此,假设我们想使用会计风格的格式,并添加前缀和后缀符号的所有计数器。具体做法如下,结果如图 15-41 所示:
@counter-style accounting {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
negative: "(" ")";
prefix: "$";
suffix: " - ";
}
ol.kaching {
list-style: accounting;
}
Negative-value formatting
Another common feature of numeric counting systems is the desire to pad out low values so that their length matches that of higher values. For example, rather than “1” and “100,” a counting pattern might use leading zeroes to create “001” and “100.” This can be accomplished with the pad
descriptor.
数字计数系统的另一个常见特性是希望填充较低的值,使其长度与较高的值匹配。例如,计数模式可能使用前导零来创建“001”和“100”,而不是“1”和“100”。“这可以通过
pad
描述符来完成。
The pattern of this descriptor is a little interesting. The first part is an integer, and defines the number of digits that every counter should have. The second part is a string that’s used to fill out any value that has fewer than the defined number of digits. Consider this example:
这个描述符的模式有点意思。第一部分是一个整数,定义每个计数器应有的位数。第二部分是一个字符串,用于填充任何小于定义的位数的值。考虑一下这个例子:
@counter-style padded {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
suffix: ".";
pad: 4 "0";
}
ol {
list-style: decimal;
}
ol.padded {
list-style: padded;
}
Given these styles, ordered lists will all used decimal counting by default: 1, 2, 3, 4, 5…. Those with a class
of padded
will use padded decimal counting: 0001, 0002, 0003, 0004, 0005…. An example of this is shown in Figure 15-42.
给定这些样式,有序列表将默认使用十进制计数:1、2、3、4、5…那些
class
为padded
将使用带软垫的十进制计数:0001,0002,0003,0004,0005…图 15-42 显示了一个示例。
Padding values
Note how the padded counters use the 0
symbol to fill in any missing leading digits, in order to make every counter be at least four digits long. The “at least” part of that last sentence is important: if a counter gets up to five digits, it won’t be padded. More importantly, if a counter reaches five digits, none of the other shorter counters will get additional zeroes. They’ll stay four digits long, because of the 4 in 4 "0"
.
请注意填充计数器如何使用
0
符号来填充任何丢失的前导数字,以使每个计数器至少有四位数字长。最后这句话的“至少”部分很重要:如果计数器的位数达到 5 位,就不会填充它。更重要的是,如果计数器达到 5 位,其他较短的计数器都不会得到额外的 0。他们将保持 4 位数字的长度,因为4 in 4 "0"
。
Any symbol can be used to pad values, not just 0
. You could use underlines, periods, emoji, arrow symbols, empty spaces, or anything else you like. In fact, you can have multiple characters in the <symbol>
part of the value. The following is perfectly acceptable, if not necessarily desirable:
任何符号都可以用来填充值,而不仅仅是
0
。你可以使用下划线、句号、表情符号、箭头符号、空格或任何你喜欢的东西。实际上,可以在值的<symbol>
部分中包含多个字符。以下是完全可以接受的,但不一定是理想的:
@counter-style crazy {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
suffix: ".";
pad: 4 " ";
}
ol {
list-style: decimal;
}
ol.padded {
list-style: padded;
}
Given a counter value of 1
, the result of that crazy counting system would be “1.”
给定计数器值
1
,这个疯狂的计数系统的结果将是“1”。
Note that negative symbols count toward symbol length, and thus eat into padding. Also note that the negative sign will come outside
any padding. Thus, given the following styles, we’d get the result shown in Figure 15-43:
请注意,负符号会计算符号长度,因此会消耗填充。还要注意,负号会出现在任何填充物之外。因此,给定以下样式,我们将得到如图 15-43 所示的结果:
@counter-style negativezeropad {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
suffix: ". ";
negative: "–";
pad: 4 "0";
}
@counter-style negativespacepad {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
suffix: ". ";
negative: "–";
pad: 4 " ";
}
Padding values
We have one more system type to explore, which is additive-symbol
counting. In additive counting systems, different symbols are used to represent values. Putting a number of the symbols together properly, and adding up the numbers each represents, yields the counter value.
我们还需要探索另一种系统类型,即
additive-symbol
计数。在加法计数系统中,不同的符号用来表示值。将一些符号正确地放在一起,并将每个符号所代表的数字相加,就得到了计数器的值。
It’s much easier to show this than explain it. Here’s an example adapted from Kseso:
展示它比解释它容易得多。下面是一个来自 Kseso 的例子:
@counter-style roman {
system: additive;
additive-symbols: 1000 M, 900 CM, 500 D, 400 CD, 100 C, 90 XC, 50 L, 40 XL,
10 X, 9 IX, 5 V, 4 IV, 1 I;
}
This will count in classical Roman style. Another good example can be found in the specification for counting styles, which defines a dice-counting system:
这在古典罗马风格中也算。另一个很好的例子可以在计数风格的规范中找到,它定义了一个骰子计数系统:
@counter-style dice {
system: additive;
additive-symbols: 6, 5, 4, 3, 2, 1, 0 "__";
suffix: " ";
}
The results of both counting systems are shown in Figure 15-44; this time, each list has been formatted as three columns.
两种计数系统的结果如图 15-44 所示;这一次,每个列表都被格式化为三列。
Additive values
Symbols can be quoted for clarity; e.g., 6 "⚅", 5 "⚅", 4 "⚅"
, and so on. The most important thing to keep in mind is that the order of the symbols and their equivalent values matters. Notice how both the Roman and dice-counting systems supplied values from largest to smallest, not the other way around? That’s because if you put the values in any order other than descending, the entire block is rendered invalid.
为了清晰,可以引用符号;例如,
6 "⚅", 5 "⚅", 4 "⚅"
,等等。最重要的是要记住符号的顺序和它们等价的值。注意到罗马计数系统和骰子计数系统是如何提供从大到小的值的,而不是反过来吗?这是因为如果您将值按除降序以外的任何顺序排列,那么整个块都是无效的。
Also notice the use of the additive-symbols
descriptor instead of symbols
. This is important to keep in mind, since defining an additive system and then trying to use the symbols
descriptor will render the entire counter-styles
block invalid. (Similarly, attempting to use the additive-symbols
description in non-additive
systems will render those
blocks invalid.)
还要注意使用“加法符号”描述符而不是“符号”。记住这一点很重要,因为定义一个附加的系统,然后尝试使用“符号”描述符将使整个“反样式”块无效。(类似地,试图在非“加性”系统中使用“加性符号”描述将使“那些”块无效。)
One last thing to note about additive systems is that, due to the way the additivecounter algorithm is defined, it’s possible to create additive systems where some values can’t be represented even though it seems like they should be. Consider this definition:
关于可加性系统的最后一点需要注意的是,由于 additivecounter 算法的定义方式,可能会创建可加性系统,其中有些值无法表示,尽管它们看起来应该是这样。考虑这个定义:
@counter-style problem {
system: additive;
additive-symbols: 3 "Y", 2 "X";
fallback: decimal;
}
This would yield the following counters for the first five numbers: 1, X, Y, 4, YX. You might think “4” should be “XX,” and that may make intuitive sense, but the algorithm for additive symbols doesn’t permit it. To quote the specification: “While unfortunate, this is required to maintain the property that the algorithm runs in linear time relative to the size of the counter value.”
这将为前 5 个数字产生以下计数器:1、X、Y、4、YX。您可能认为“4”应该是“XX”,这可能很直观,但是添加符号的算法不允许这样做。引用该规范:“不幸的是,这需要维护算法在与计数器值的大小相关的线性时间内运行的属性。”
So how does Roman counting manage to get “III” for 3? Again, the answer is in the algorithm. It’s a little too complicated to get into here, so if you’re truly curious, I recommend you read the CSS Counter Styles Level 3 specification, which defines the additive counting algorithm. Even if that doesn’t interest you, just remember: make sure you have a symbol whose value equates to 1
, and you’ll avoid this problem.
There may come a time when you just want to vary an existing counting system a bit. For example, suppose you want to change regular decimal counting to use closeparentheses symbols as suffixes, and pad up to two leading zeroes. You could write it all out longhand, like so:
也许有一天,你只是想改变一下现有的计数系统。例如,假设您想要更改常规的十进制计数,以使用封闭括号符号作为后缀,并将两个前导零加起来。你可以把它写下来,就像这样:
@counter-style mydecimals {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
suffix: ") ";
pad: 2 "0";
}
That works, but it’s clumsy. Well, worry not: extends
is here to help.
这是可行的,但是很笨拙。好吧,别担心:
extends
这个词可以帮上忙。
extends
is sort of a system type, but only in the sense that it builds on an existing system type. The previous example would be rewritten with extends
as follows:
extends
是一种系统类型,但只是在它构建于现有系统类型的意义上。前面的例子可以用extends
重写,如下:
@counter-style mydecimals {
system: extends decimal;
suffix: ") ";
pad: 2 "0";
}
That takes the existing decimal
system familiar from list-style-type
and reformats it a bit. Thus, there’s no need to re-type the whole symbol chain. You just adjust the options, as it were.
它采用了现有的
decimal
系统,与list-style-type
类似,并对其进行了一些格式调整。因此,不需要重新键入整个符号链。你只需要调整选项。
In fact, you can only adjust the options: if you try use either symbols
or additive-symbols
in an extneds
system, the entire @counter-style
block will be invalid and ignored. In other words, symbols cannot be extended. As an example, you can’t define hexadecimal counting by extending decimal counting.
实际上,您只能调整选项:如果您尝试在“extneds”系统中使用“符号”或“加法符号”,那么整个“@counter-style”块将无效并被忽略。换句话说,符号不能被扩展。例如,您不能通过扩展十进制计数来定义十六进制计数。
However, you can vary the hexadecimal counting for different contexts. As an example, you could set up basic hex counting and then define some variant display patterns, as shown in the following code and illustrated in Figure 15-45. (Note that each list jumps from 19 to 253, thanks to a value="253"
on one of the list items.)
但是,您可以根据不同的上下文改变十六进制计数。例如,您可以设置基本的十六进制计数,然后定义一些不同的显示模式,如下面的代码所示,如图 15-45 所示。(注意每个列表从 19 跳到 253,这是由于其中一个列表项上的“value="253")。
@counter-style hexadecimal {
system: numeric;
symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F";
}
@counter-style hexpad {
system: extends hexadecimal;
pad: 2 "0";
}
@counter-style hexcolon {
system: extends hexadecimal;
suffix: ": ";
}
@counter-style hexcolonlimited {
system: extends hexcolon;
range: 1 255; /* stops at FF */
}
Various hexadecimal counting patterns
Notice how the last of the four counter styles, hexcolonlimited
, extends the third, hexcolon
, which itself extends the first, hexadecimal
. In hexcolonlimited
, the hexadecimal counting stops at FF
(255), thanks to the range: 1 255;
declaration.
注意这四种计数器样式中的最后一种样式
hexcolonlimited
扩展了第三种样式hexcolon
,而后者本身扩展了第一种样式hexadecimal
。在hexcolonlimited
中,十六进制计数止于FF
(255),这得益于range: 1 255;
声明。
While it’s fun to build counters out of symbols, the result can be a real mess for spoken technologies such as Apple’s VoiceOver or the JAWS screen reader. Imagine, for example, a screen reader trying to read dice counters, or phases of the moon. To help, the speak-as
descriptor allows you to define an audible fallback.
虽然用符号构建计数器很有趣,但对于苹果(Apple)的画外音或 JAWS 屏幕阅读器等语音技术来说,结果可能会非常糟糕。例如,设想一个屏幕阅读器试图读取骰子计数器或月相。为了提供帮助,
speak-as
描述符允许您定义一个可听见的回退。
Let’s take the values backward. With a <counter-style-name>
, you’re able to define an alternate counting style that the user agent likely already recognizes. For example, you might provide an audio fallback for dice-counting to be decimal counting when spoken:
我们把这些值往回取。使用
<counter-style-name>
,您可以定义用户代理可能已经识别的另一种计数样式。例如,你可以提供一个音频回退为十进制计数时,说话:
@counter-style dice {
system: additive;
speak-as: decimal;
additive-symbols: 6, 5, 4, 3, 2, 1;
suffix: " ";
}
Given those styles, the counter “⚅⚅⚂
” would be spoken as “fifteen.” Alternatively, if the speak-as
value is changed to lower-latin
, that counter will be spoken as “oh” (capital letter O).
考虑到这些风格,柜台“
⚅⚅⚂
”会说“十五岁。或者,如果speak-as
的值被更改为lower-latin
,那么该计数器将被说成' oh '(大写字母 O)。
spell-out
seems fairly straightforward, but it’s a little more complicated than it first appears. What is spelled out by the user agent is a “counter representation,” which is then spelled out letter by letter. It’s hard to predict what that will mean, since the method of generated a counter representation isn’t precisely defined: the specification says “counter representations are constructed by concatenating counter symbols together.” And that’s all.
“拼出”这个词看起来很简单,但其实比它第一次出现的时候要复杂一些。用户代理拼出的是“计数器表示”,然后逐个字母拼出。很难预测这将意味着什么,因为生成计数器表示的方法并没有精确定义:规范中说“计数器表示是由将计数器符号连接在一起来构造的。”“就这些。
words
is similar to spell-out
, except the counter representation is spoken as words instead of spelling out each letter. Again, the exact process is not defined.
“words”与“spellout”类似,只是反表示是作为单词而不是拼写出每个字母。同样,没有定义确切的过程。
With the value numbers
, the counters are spoken as numbers in the document language. This is very similar to the previous code sample, where “⚅⚅⚂
” is spoken as “fifteen,” at least in English documents. If it’s another language, then that language is used for counting: “quince” in Spanish, “fünfzehn” in German, “shíwǔ
” in Chinese, and so on.
使用数值
numbers
,计数器在文档语言中被表示为数字。这非常类似于前面的代码示例中,在那里 “⚅⚅⚂
” 说作为“十五”,至少在英语文档。如果它是另一种语言,那么语言是用于计算:“海棠”在西班牙语中,“funfzehn”在德国,“shíwǔ
”在中国,等等。
Given bullets
, the user agent says whatever it says when reading a bullet (marker) in an unordered list. This may mean saying nothing at all, or producing an audio cue such as a chime or click.
有了
bullets
,用户代理在无序列表中读取子弹(标记)时就会说任何它想说的话。这可能意味着什么也不说,或产生一个音频提示,如编钟或点击。
Finally, consider the default value of auto
. We saved this for last because its actual effect depends on the counting system in use. If it’s a alphabetic
system, then speak-as: auto
has the same effect as speak-as: spell-out
. In cyclic
systems, auto
is the same as bullets
. Otherwise, the effect is the same as speak-as: numbers
.
最后,考虑“auto”的默认值。我们把它留到最后,因为它的实际效果取决于使用的计数系统。如果是“字母”系统,那么“speak-as: auto”与“speak-as: spell-out”的效果相同。在“循环”系统中,“自动”等同于“子弹”。否则,它的效果和“说话是数字”是一样的。
The exception to this rule is if the system is an extends
system, in which case auto
’s effects are determined based on the system being extended. Therefore, given the following styles, the counters in an emojibrackets
list will be spoken as if speak-as
were set to bullets
:
这个规则的例外是,如果系统是一个
extends
系统,在这种情况下,auto
的效果是根据被扩展的系统来确定的。因此,考虑到以下风格,emojibrackets
列表中的计数器将被设置为bullets
:
@counter-style emojilist {
emojiverse {
system: cyclic;
symbols: ;
@counter-style emojibrackets {
system: extends emojilist;
suffix: "]] ";
speak-as: auto;
}
Even though list styling isn’t as sophisticated as we might like, and browser support for generated content is somewhat spotty (as of this writing, anyway), the ability to style lists is still highly useful. One relatively common use is to take a list of links, remove the markers and indentation, and thus create a navigation sidebar. The combination of simple markup and flexible layout is difficult to resist. With the anticipated enhancements to list styling in CSS3, I expect that lists will become more and more useful.
尽管列表样式并不像我们希望的那样复杂,而且浏览器对生成内容的支持也有些参差不齐(至少在撰写本文时是这样),但对列表样式化的能力仍然非常有用。一个比较常见的用法是获取链接列表,删除标记和缩进,从而创建导航侧栏。简单的标记和灵活的布局是难以抗拒的。随着 CSS3 中列表样式的预期增强,我预计列表将变得越来越有用。
For now, in situations where a markup language doesn’t have intrinsic list elements, generated content can be an enormous help—say, for inserting content such as icons to point to certain types of links (PDF files, Word documents, or even just links to another web site). Generated content also makes it easy to print out link URLs, and its ability to insert and format quotation marks leads to true typographic joy. It’s safe to say that the usefulness of generated content is limited only by your imagination. Even better, thanks to counters, you can now associate ordering information to elements that are not typically lists, such as headings or code blocks. Now, if you want to support such features with design that mimics the appearance of the user’s operating system, read on. The next chapter will discuss ways to change the placement, shape, and even perspective of your design.
目前,在标记语言没有固有的列表元素的情况下,生成的内容可能是一个巨大的帮助—比方说,用于插入指向某些类型链接(PDF 文件、Word 文档,甚至只是指向另一个 web 站点的链接)的图标之类的内容。生成的内容还使打印链接 url 变得很容易,它插入和格式化引号的能力带来了真正的排版乐趣。可以肯定地说,生成内容的有用性仅仅受到想象力的限制。更棒的是,由于有了计数器,现在可以将排序信息与通常不是列表的元素(如标题或代码块)关联起来。现在,如果您希望通过模仿用户操作系统外观的设计来支持这些特性,请继续阅读。下一章将讨论如何更改设计的位置、形状甚至透视图。