content

Baseline 广泛可用 *

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

* 此特性的某些部分可能存在不同级别的支持。

content CSS 属性将内容替换为生成的值。它可以用来定义元素或伪元素内部渲染的内容。对于元素,content 属性指定元素是正常渲染(normalnone)还是被图像(以及相关的“替代”文本)替换。对于伪元素和页边距框,content 定义了内容为图像、文本、两者都有或没有,这决定了元素是否渲染。

使用 content 属性插入的对象是匿名的替换元素

试一试

.topic-games::before {
  content: "🎮 " / "games";
}

.topic-weather::before {
  content: "⛅ " / "cloudy";
}

.topic-hot::before {
  content: url("/shared-assets/images/examples/fire.png") / "On fire";
  margin-right: 6px;
}
<p class="topic-games">Game News: A new inFamous is not planned</p>

<p class="topic-weather">
  Weather for Today: Heat, violent storms and twisters
</p>

<p class="topic-hot">Trending Article: Must-watch videos of the week</p>

语法

css
/* Keywords that cannot be combined with other values */
content: normal;
content: none;

/* <content-replacement>: <image> values */
content: url("http://www.example.com/test.png");
content: linear-gradient(#e66465, #9198e5);
content: image-set("image1x.png" 1x, "image2x.png" 2x);

/* speech output: alternative text after a "/"  */
content: url("../img/test.png") / "This is the alt text";

/* <string> value */
content: "unparsed text";

/* <counter> values, optionally with <list-style-type> */
content: counter(chapter_counter);
content: counter(chapter_counter, upper-roman);
content: counters(section_counter, ".");
content: counters(section_counter, ".", decimal-leading-zero);

/* attr() value linked to the HTML attribute value */
content: attr(href);

/* <quote> values */
content: open-quote;
content: close-quote;
content: no-open-quote;
content: no-close-quote;

/* <content-list>: a list of content values. 
Several values can be used simultaneously */
content: "prefix" url("http://www.example.com/test.png");
content: "prefix" url("/img/test.png") "suffix" / "Alt text";
content: open-quote counter(chapter_counter);

/* Global values */
content: inherit;
content: initial;
content: revert;
content: revert-layer;
content: unset;

其值可以是:

  • 两个关键字之一:nonenormalnormal 是默认属性值。
  • 替换 DOM 节点时的 <content-replacement><content-replacement> 总是 <image>
  • 替换伪元素和页边距框时的 <content-list><content-list> 是一个或多个按指定顺序出现的匿名内联盒的列表。每个 <content-list> 项的类型为 <string><image><counter><quote><target><leader()>
  • 一个可选的 <string><counter> 替代文本值,前面有一个斜杠(/)。

上面提到的关键字和数据类型将在下面更详细地描述。

none

当应用于伪元素时,该伪元素不会被生成。当应用于元素时,该值没有效果。

normal

对于 ::before::after 伪元素,此值的计算结果为 none。对于其他伪元素,如 ::marker::placeholder::file-selector-button,它会生成元素的初始(或正常)内容。对于常规元素或页边距框,它的计算结果为元素的后代。这是默认值。

<string>

由匹配的单引号或双引号括起来的字符序列。多个字符串值将被连接(CSS 中没有连接操作符)。

<image>

一个 <image>,表示要显示的图像。这可以等于 <url>image-set()<gradient> 数据类型,或者网页本身的一部分,由 element() 函数定义。

<counter>

<counter> 值是一个 CSS 计数器,通常是由 <counter-reset><counter-increment> 属性定义的计算产生的数字。它可以使用 counter()counters() 函数来显示。

counter()

counter() 函数有两种形式:'counter(name)' 或 'counter(name, style)'。生成的文本是在给定伪元素作用域内具有给定名称的最内层计数器的值。它以指定的 <list-style-type>(默认为 decimal)进行格式化。

counters()

counters() 函数也有两种形式:'counters(name, string)' 或 'counters(name, string, style)'。生成的文本是在给定伪元素作用域内所有具有给定名称的计数器的值,从最外层到最内层,由指定的字符串分隔。计数器以指定的 <list-style-type>(默认为 decimal)进行渲染。

<quote>

<quote> 数据类型包括依赖于语言和位置的关键字。

open-quoteclose-quote

这些值被 quotes 属性中适当的字符串替换。

no-open-quoteno-close-quote

不引入内容,但增加(或减少)引用的嵌套级别。

<target>

<target> 数据类型包括三个目标函数,<target-counter()><target-counters()><target-text()>,它们创建从链接的目标端获得的交叉引用。请参阅正式语法

<leader()>

<leader()> 数据类型包含一个引导符函数:leader( <leader-type> )。该函数接受关键字值 dottedsolidspace(分别等于 leader(".")leader("_")leader(" ")),或一个 <string> 作为参数。当被支持并用作 content 的值时,提供的引导符类型将作为重复模式插入,以在水平线上直观地连接内容。

attr(x)

CSS 函数 attr(x) 检索所选元素或伪元素的源元素的属性值。元素属性 x 的值是表示该属性名称的未解析字符串。如果没有属性 x,则返回一个空字符串。属性名称参数的大小写敏感性取决于文档语言。

替代文本:/ <string> | <counter>

可以为图像或任何 <content-list> 项指定替代文本,方法是在其后附加一个正斜杠,然后是一个文本字符串或一个计数器。替代文本旨在供屏幕阅读器进行语音输出,但也可能在某些浏览器中显示。/ <string>/ <counter> 数据类型指定了元素的“alt 文本”。

正式定义

初始值normal
应用于所有元素、遵循树结构的伪元素和页边距框
继承性
计算值在元素上,始终计算为 normal。在 ::before::after 上,如果指定了 normal,则计算为 none。否则,对于 URI 值,为绝对 URI;对于 attr() 值,为结果字符串;对于其他关键字,按指定值计算。
动画类型离散

正式语法

content = 
normal |
none |
[ <content-replacement> | <content-list> ] [ / [ <string> | <counter> | <attr()> ]+ ]? |
<element()>

<content-replacement> =
<image>

<content-list> =
[ <string> | <image> | <attr()> | contents | <quote> | <leader()> | <target> | <string()> | <content()> | <counter> ]+

<counter> =
<counter()> |
<counters()>

<attr()> =
attr( <attr-name> <attr-type>? , <declaration-value>? )

<element()> =
element( <id-selector> )

<image> =
<url> |
<image()> |
<image-set()> |
<cross-fade()> |
<element()> |
<gradient>

<quote> =
open-quote |
close-quote |
no-open-quote |
no-close-quote

<leader()> =
leader( <leader-type> )

<target> =
<target-counter()> |
<target-counters()> |
<target-text()>

<string()> =
string( <custom-ident> , [ first | start | last | first-except ]? )

<content()> =
content( [ text | before | after | first-letter | marker ]? )

<counter()> =
counter( <counter-name> , <counter-style>? )

<counters()> =
counters( <counter-name> , <string> , <counter-style>? )

<attr-name> =
[ <ident-token>? '|' ]? <ident-token>

<attr-type> =
type( <syntax> ) |
raw-string |
number |
<attr-unit>

<id-selector> =
<hash-token>

<image()> =
image( <image-tags>? [ <image-src>? , <color>? ]! )

<image-set()> =
image-set( <image-set-option># )

<cross-fade()> =
cross-fade( <cf-image># )

<leader-type> =
dotted |
solid |
space |
<string>

<target-counter()> =
target-counter( [ <string> | <url> ] , <custom-ident> , <counter-style>? )

<target-counters()> =
target-counters( [ <string> | <url> ] , <custom-ident> , <string> , <counter-style>? )

<target-text()> =
target-text( [ <string> | <url> ] , [ content | before | after | first-letter ]? )

<counter-style> =
<counter-style-name> |
<symbols()>

<syntax> =
'*' |
<syntax-component> [ <syntax-combinator> <syntax-component> ]* |
<syntax-string>

<image-tags> =
ltr |
rtl

<image-src> =
<url> |
<string>

<image-set-option> =
[ <image> | <string> ] [ <resolution> || type( <string> ) ]?

<cf-image> =
[ <image> | <color> ] &&
<percentage [0,100]>?

<symbols()> =
symbols( <symbols-type>? [ <string> | <image> ]+ )

<syntax-component> =
<syntax-single-component> <syntax-multiplier>? |
'<' transform-list '>'

<syntax-combinator> =
'|'

<syntax-string> =
<string>

<symbols-type> =
cyclic |
numeric |
alphabetic |
symbolic |
fixed

<syntax-single-component> =
'<' <syntax-type-name> '>' |
<ident>

<syntax-multiplier> =
'#' |
'+'

<syntax-type-name> =
angle |
color |
custom-ident |
image |
integer |
length |
length-percentage |
number |
percentage |
resolution |
string |
time |
url |
transform-function

无障碍

CSS 生成的内容不包含在 DOM 中。因此,它不会在无障碍树中表示,某些辅助技术/浏览器组合将不会播报它。如果内容传达了对于理解页面目的至关重要的信息,最好将其包含在主文档中。

如果插入的内容不是装饰性的,请检查信息是否提供给了辅助技术,并且在关闭 CSS 时也可用。

示例

前五个示例在伪元素上创建生成的内容。后三个是元素替换的示例

根据元素的类附加字符串

此示例在具有特定类名的元素文本后插入生成的文本。该文本为红色。

HTML

html
<h2>Paperback Best Sellers</h2>
<ol>
  <li>Political Thriller</li>
  <li class="new-entry">Halloween Stories</li>
  <li>My Biography</li>
  <li class="new-entry">Vampire Romance</li>
</ol>

CSS

css
.new-entry::after {
  content: " New!"; /* The leading space creates separation
                       between the DOM node's content and the generated content
                       being added. */
  color: red;
}

结果

引号

此示例在引用内容周围插入不同颜色的引号。

HTML

html
<p>
  According to Sir Tim Berners-Lee,
  <q cite="http://www.w3.org/People/Berners-Lee/FAQ.html#Internet">
    I was lucky enough to invent the Web at the time when the Internet already
    existed - and had for a decade and a half.
  </q>
  We must understand that there is nothing fundamentally wrong with building on
  the contributions of others.
</p>
<p lang="fr-fr">
  Mais c'est Magritte qui a dit,
  <q lang="fr-fr"> Ceci n'est pas une pipe. </q>.
</p>

CSS

css
q {
  color: blue;
}

q::before,
q::after {
  font-size: larger;
  color: red;
  background: #cccccc;
}

q::before {
  content: open-quote;
}

q::after {
  content: close-quote;
}

结果

注意,生成的引号类型是基于语言的。默认情况下,浏览器会在 <q> 元素前后添加开引号和闭引号,因此即使没有明确设置,本例中的引号也会出现。可以通过将相应的 content 属性值设置为 no-open-quoteno-close-quote,或将它们都设置为 none 来关闭它们。也可以通过将 quotes 属性设置为 none 来关闭它们。

向列表项计数器添加文本

此示例将一个夹在两个 <string> 之间的计数器前置到所有列表项,为无序列表(<ol>)中的列表项(<li>)创建更详细的标记。

HTML

html
<ol>
  <li>Dogs</li>
  <li>Cats</li>
  <li>
    Birds
    <ol>
      <li>Owls</li>
      <li>Ducks</li>
      <li>Flightless</li>
    </ol>
  </li>
  <li>Marsupials</li>
</ol>

CSS

css
ol {
  counter-reset: items;
  margin-left: 2em;
}
li {
  counter-increment: items;
}
li::marker {
  content: "item " counters(items, ".", numeric) ": ";
}

结果

每个列表项标记上生成的内容添加了文本“item ”作为前缀,包括一个空格以将前缀与计数器分开,后面跟着“: ”,一个冒号和一个额外的空格。counters() 函数定义了一个数字 items 计数器,其中嵌套的有序列表的数字在大多数浏览器中用句点(.)分隔。

带属性值的字符串

这个例子对打印样式表很有用。它使用一个属性选择器来选择每个完全合格的安全链接,将 href 属性的值作为 ::after 伪元素的内容添加到链接文本之后。

HTML

html
<ul>
  <li><a href="https://mozilla.com">Mozilla</a></li>
  <li><a href="/">MDN</a></li>
  <li><a href="https://openwebdocs.org">OpenWebDocs</a></li>
</ul>

CSS

css
a[href^="https://"]::after
{
  content: " (URL: " attr(href) ")";
  color: darkgreen;
}

结果

生成的内容是 href 属性的值,前面加上“URL: ”,带有一个空格,全部放在括号里。

添加带替代文本的图像

这个例子在所有链接之前插入一个图像。提供了两个 content 值。后面的 content 值包含一个带有替代文本的图像,屏幕阅读器可以将其作为语音输出。

HTML

html
<a href="https://www.mozilla.org/en-US/">Mozilla Home Page</a>

CSS

下面显示了显示图像和设置替代文本的 CSS。这也设置了内容的字体和颜色。

css
a::before {
  content: url("https://mozorg.cdn.mozilla.net/media/img/favicon.ico") /
    " MOZILLA: ";
}

结果

注意:替代文本值在浏览器的无障碍树中公开。有关特定浏览器的无障碍面板,请参阅另请参阅部分。

如果使用屏幕阅读器,当它到达图像时,应该会读出“MOZILLA”这个词。您可以使用开发者工具的选择工具选择 ::before 伪元素,并在无障碍面板中查看可访问名称

使用 URL 替换元素

这个例子替换了一个常规元素!该元素的内容被一个使用 <url> 类型的 SVG 替换。

伪元素不会在替换元素上渲染。由于这个元素被替换了,任何匹配的 ::after::before 都不会被生成或应用。为了证明这一点,我们包含了一个 ::after 声明块,试图将 id 作为生成的内容添加。这个伪元素将不会被生成,因为元素被替换了。

HTML

html
<div id="replaced">This content is replaced!</div>

CSS

css
#replaced {
  content: url("mdn.svg");
}

/* will not show if element replacement is supported */
div::after {
  content: " (" attr(id) ")";
}

结果

在常规元素上生成内容时(而不仅仅是在伪元素上),整个元素都会被替换。这意味着 ::before::after 伪元素不会被生成。

使用 <gradient> 替换元素

这个例子演示了如何用任何类型的 <image> 替换元素的内容,在本例中是一个 CSS 渐变。元素的内容被一个 linear-gradient() 替换。我们提供了替代文本,因为所有图像都应该为可访问性进行描述。

HTML

html
<div id="replaced">I disappear</div>

CSS

css
div {
  border: 1px solid;
  background-color: #cccccc;
  min-height: 100px;
  min-width: 100px;
}

#replaced {
  content: repeating-linear-gradient(blue 0, orange 10%) /
    "Gradients and alt text are supported";
}

结果

请检查浏览器兼容性图表。所有浏览器都支持渐变,所有浏览器都支持用图像替换元素,但并非所有浏览器都支持渐变作为 content 的值。

使用 image-set() 替换元素

此示例使用 image-set() 替换元素的内容。如果用户显示器是普通分辨率,将显示 1x.png。具有更高分辨率的屏幕将显示 2x.png 图像。

HTML

html
<div id="replaced">I disappear!</div>

CSS

css
#replaced {
  content: image-set(
    "1x.png" 1x,
    "2x.png" 2x
  ) / "DPI";
}

结果

规范

规范
CSS Generated Content Module Level 3
# content-property

浏览器兼容性

另见