CSS内容属性:是否可以插入HTML而不是文本?

296

想知道是否有可能通过CSS的content属性在一个元素的:before:after伪元素中插入HTML代码而不是字符串,类似于:


.header:before{
  content: '<a href="#top">Back</a>';
}

这将非常方便...虽然可以通过JavaScript实现,但使用CSS确实会使生活更轻松 :)


@Kaiido 哎呀...不好意思,我没注意到问题的日期,我参考了你的答案...真的很抱歉,我会删除这两条评论 :) - Asons
5个回答

242
很遗憾,这是不可能的。根据规范

生成的内容不会改变文档树。特别地,它不会被反馈给文档语言处理器(例如,用于重新解析)。

换句话说,对于字符串值,这意味着该值始终被视为文字。无论使用哪种文档语言,它都不会被解释为标记。
例如,使用以下HTML和给定的CSS:
<h1 class="header">Title</h1>

...将导致以下输出:

<a href="#top">返回</a>标题


2
同意,但是如果你想象它已经支持带有 url 属性的图片,从这个角度来看添加链接并没有那么不同。 - zanona
15
这是因为这些图片本身不是DOM元素(除了<img>),它们只是被绘制在现有元素上,所以应用背景或列表图片并不会真正修改DOM。 - BoltClock
1
明白了,谢谢。所以我想我必须放弃这个想法,直接使用JS。干杯! - zanona
6
好问题。我也在 Stack Overflow 上搜索,希望这是可能的。 - Robin Maben
1
支持SVG,这是我刚发现的 :) - dezman
1
@watson:刚看到你对另一个问题的回答。你是对的;我可能应该在我的答案中澄清,不能添加任意标记 - 必须通过 url() 指定外部文件,就像任何其他图像一样。 - BoltClock

81

正如在 @BoltClock 的回答的评论中所提到的,在现代浏览器中,您实际上可以使用 (url()) 结合svg的<foreignObject>元素,在伪元素中添加一些html标记。

您可以指定指向实际svg文件的URL,也可以创建一个dataURI版本(data:image/svg+xml; charset=utf8, + encodeURIComponent(yourSvgMarkup))

但请注意,这基本上是一种hack,并且有很多限制:

  • 您不能从此标记中加载任何外部资源(没有CSS、图像、媒体等)。
  • 您无法执行脚本。
  • 由于这不会成为DOM的一部分,唯一更改它的方法是将标记作为dataURI传递,并在 document.styleSheets 中编辑此dataURI。对于此部分,DOMParserXMLSerializer 可以 帮助
  • 虽然相同的操作允许我们在 <img> 标记中加载url编码的媒体,但这在伪元素中不起作用(至少到目前为止,我不知道是否有指定它不应该这样做的地方,因此它可能是一个尚未实现的功能)。

现在,这里有一个小演示,展示了如何在一个伪元素中添加一些HTML标记:

/* 
**  original svg code :
*
*<svg width="200" height="60"
*     xmlns="http://www.w3.org/2000/svg">
*
* <foreignObject width="100%" height="100%" x="0" y="0">
* <div xmlns="http://www.w3.org/1999/xhtml" style="color: blue">
*  I am <pre>HTML</pre>
* </div>
* </foreignObject>
*</svg>
*
*/
#log::after {
  content: url('data:image/svg+xml;%20charset=utf8,%20%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%2260%22%20width%3D%22200%22%3E%0A%0A%20%20%3CforeignObject%20y%3D%220%22%20x%3D%220%22%20height%3D%22100%25%22%20width%3D%22100%25%22%3E%0A%09%3Cdiv%20style%3D%22color%3A%20blue%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%0A%09%09I%20am%20%3Cpre%3EHTML%3C%2Fpre%3E%0A%09%3C%2Fdiv%3E%0A%20%20%3C%2FforeignObject%3E%0A%3C%2Fsvg%3E');
}
<p id="log">hi</p>


我看到了你的回答,它解决了我的一些问题。你能否解释一下如何格式化指向文件的URL?我尝试使用 url('/relativePathToMySvg/mySvg.svg') 但它没有起作用。 - Frank
@Frank,根据规格说明,使用相对路径将相对于您的CSS文件路径,例如,如果您的CSS文件位于/root/css/yourFile.css中,则像yourFile.svg这样的相对funcIRI将指向/root/css/yourFile.svg/。但是,我记得早期的UA存在一个错误,将其相对于文档的baseURI。因此,最安全的方法就是使用绝对路径。 - Kaiido
1
@BoltClock,真的吗?我对此深感抱歉。我通过另一个问题进入了这个6年前的问题,并觉得我必须将其作为更新发布,但也许我应该更清楚地表明你的答案是好的,并且在6年前肯定是正确的?或者如果你有一些适合作为标题的好措辞,可以随意编辑我的回答。 - Kaiido
1
不错。我使用了 content: url('../../images/como-funciona.svg');,它运行良好。 - Eliut Islas
这是我之前的一篇帖子,其中有我的答案,深入探讨了这个主题:is-it-possible-to-display-an-html-document-or-html-fragment-at-css-content - Asons
很抱歉,这不允许添加链接。 - Rafael Kitover

10
在CSS3分页媒体中,可以使用position: running()content: element()来实现这一点。
来自CSS Generated Content for Paged Media Module草案的示例:
@top-center {
  content: element(heading); 
}

.runner { 
  position: running(heading);
}

.runner可以是任何元素,heading只是槽位的一个任意名称。

编辑:为了澄清,基本上没有浏览器支持,所以这主要是为了将来参考/补充已经给出的“实用答案”。


嘿,你能再解释一下吗?我对你的理论很感兴趣,但好像无法执行。如果我想使用这种方法包含一个锚标签或一个 div,应该怎么做呢? - Neil
问题是当前基本上没有浏览器支持,但专用的HTML渲染器根据规范实现它。下一个不太好的消息是似乎没有很好的开源实现;大多数都是SaaS产品,如https://www.princexml.com/。 - s-ol

2

可能是因为这样会很容易受到XSS攻击。而且,目前可用的HTML过滤器不会禁止content属性。

(这并不是最好的答案,但我只是想分享一些除了“按规范来说...”之外的见解)


1
如果您有能力在页面的其他位置添加HTML代码,可以将它重新定位到CSS内容显示的区域上方。
因此,您可以添加您的CSS内容:
   .cssClass::after {
    content: "Content and Words and Things";
    color: #0000EE;
        }

我将超链接的颜色改成了蓝色,这样看起来更像一个链接。

然后你需要添加一个href属性,在标签之间没有文本,但有一个可以引用的id或class。它可以放在任何位置,只要在同一页中即可。

<a id="link" href="#"></a>

然后将链接定位到您想要的内容上方:
a#link{
    height: 20px;
    width: 100%;
    left: 0;
    top: 5%;
    position: absolute;
}

我还需要制作类似的示例,但是从您的示例中我不明白如何将元素<a>放置在内容中。 - OrYo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接