268

Just wondering if it's possible somehow to make the CSS content property insert html code instead string on :before or :after an element like:

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

this would be quite handy...It could be done through Javascript but using css for this would really make lives easier :)

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
zanona
  • 11,379
  • 24
  • 78
  • 137
  • @Kaiido OMG...it is not, didn't check the date of the question, I referred to your answer...really sorry, will delete both these comments :) – Ason Jun 28 '17 at 23:08

4 Answers4

219

Unfortunately, this is not possible. Per the spec:

Generated content does not alter the document tree. In particular, it is not fed back to the document language processor (e.g., for reparsing).

In other words, for string values this means the value is always treated literally. It is never interpreted as markup, regardless of the document language in use.

As an example, using the given CSS with the following HTML:

<h1 class="header">Title</h1>

... will result in the following output:

<a href="#top">Back</a>Title

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
  • 1
    agreed, but if you imagine that it already have support for images with the `url` attributes, adding a link wouldn't be that different in this perspective. – zanona Dec 22 '10 at 00:23
  • 14
    @ludicco: That's because the images themselves aren't DOM elements (not counting ``), they're just being drawn onto existing elements, so by applying background or list images you're not really modifying the DOM. – BoltClock Dec 22 '10 at 00:24
  • 1
    got it thanks, so I think I will have to pass this idea and go straight to js, cheers – zanona Dec 22 '10 at 00:25
  • 6
    @ludicco: Good question. Even I was searching through SO hoping this was possible. – Robin Maben Sep 12 '11 at 14:27
  • Does support svgs tho, which i just found out :) – dezman Oct 10 '13 at 15:19
  • 1
    @watson: Just saw your answer to the other question. You're right; I probably should clarify in my answer that you cannot add arbitrary markup - you have to specify an external file via `url()` instead, as with any other image. – BoltClock Oct 10 '13 at 15:59
59

As almost noted in comments to @BoltClock's answer, in modern browsers, you can actually add some html markup to pseudo-elements using the (url()) in combination with svg's <foreignObject> element.

You can either specify an URL pointing to an actual svg file, or create it with a dataURI version (data:image/svg+xml; charset=utf8, + encodeURIComponent(yourSvgMarkup))

But note that it is mostly a hack and that there are a lot of limitations :

  • You can not load any external resources from this markup (no CSS, no images, no media etc.).
  • You can not execute script.
  • Since this won't be part of the DOM, the only way to alter it, is to pass the markup as a dataURI, and edit this dataURI in document.styleSheets. for this part, DOMParser and XMLSerializer may help.
  • While the same operation allows us to load url-encoded media in <img> tags, this won't work in pseudo-elements (at least as of today, I don't know if it is specified anywhere that it shouldn't, so it may be a not-yet implemented feature).

Now, a small demo of some html markup in a pseudo element :

/* 
**  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>
Kaiido
  • 87,051
  • 7
  • 143
  • 194
  • I came across your answer, and it is a solution to some of my own issues. Can you explain how to format a URL pointing to a file? I tried `url('/relativePathToMySvg/mySvg.svg')` and it didn't work – Frank Jun 01 '16 at 13:08
  • @Frank, per specs, using a relative path will be relative to your css file's path i.e, if you've got your css file in `/root/css/yourFile.css`, then a relative funcIRI like `yourFile.svg` will be pointing to `/root/css/yourFile.svg/`. But, I think I remember that some earlier UA had a bug and made it relative to the document's baseURI. So the securest way is just to use absolute path. – Kaiido Jun 01 '16 at 13:40
  • 1
    @BoltClock, really ? I'm truly sorry about it. I came on this 6 years old question by an other one and felt I had to post it as an update, but maybe I should be even more clear that your answer is good, and was definitely correct 6 years ago ? Or if you have some good wordings that could fit as an header, feel free to edit my answer. – Kaiido Jun 11 '16 at 13:21
  • 1
    Nice. I used: `content: url('../../images/como-funciona.svg');` and it works fine – Eliut Islas Jan 09 '17 at 20:20
  • Here is an earlier post, which have an answer of mine, that dives a little deeper into the subject: [is-it-possible-to-display-an-html-document-or-html-fragment-at-css-content](https://stackoverflow.com/questions/36072936/is-it-possible-to-display-an-html-document-or-html-fragment-at-css-content) – Ason Jun 28 '17 at 14:53
7

In CSS3 paged media this is possible using position: running() and content: element().

Example from the CSS Generated Content for Paged Media Module draft:

@top-center {
  content: element(heading); 
}

.runner { 
  position: running(heading);
}

.runner can be any element and heading is an arbitrary name for the slot.

EDIT: to clarify, there is basically no browser support so this was mostly meant to be for future reference/in addition to the 'practical answers' given already.

sol
  • 1,427
  • 13
  • 27
  • Hey, could you explain this a little more. I am interested in your theory but can't seem to get it to execute. How would I include, say, an anchor tag using this method or a div. – Neil Nov 26 '17 at 21:38
  • the problem is that there is currently basically no browser support, but dedicated HTML renderers implement it as per the spec. The next not-so-good news are that there doesn't seem to be a good open source implementation; most are SaaS products like https://www.princexml.com/. – sol Nov 30 '17 at 17:47
0

It is not possible prolly cuz it would be so easy to XSS. Also , current HTML sanitizers that are available don't disallow content property.

(Definitely not the greatest answer here but I just wanted to share an insight other than the "according to spec... ")

Tilak Maddy
  • 3,027
  • 2
  • 26
  • 44