title: How did CSS `content` property work for `img` element in WebKit?
body: <p>Long time ago there was a draft of CSS3 Generated Content spec which allowed the <code>content</code> property <a href="https://www.w3.org/TR/2003/WD-css3-content-20030514/#inserting3" rel="noreferrer">for any HTML element</a> (not only ::before/::after pseudo-elements), without any formal restriction for empty or replaced elements. It was once supported by Opera Presto (<a href="http://www.css3.info/generated-content-in-css3/" rel="noreferrer">1</a>, <a href="https://dev.opera.com/articles/css-generated-content-techniques/" rel="noreferrer">2</a>) and, at least to some extent, by WebKit (<a href="https://css-tricks.com/css-content/#comment-79856" rel="noreferrer">3</a>). By the end of 2011, WebKit's implementation of <code>content</code> for <code>img</code> element seemed to effectively convert it from an empty replaced element to non-replaced element like <code>span</code> (even its context menu changed, removing options like 'Save image as...'). It also made it possible to apply pseudo elements like <code>img::before</code>.</p>
  
  <p>In the current Blink (Chrome etc.) implementation, seeting <code>content</code> property to <code>img</code> element has no visible effect. But the <code>img</code> element clearly has different structure depending on whether it loaded properly or is broken: if loaded, it is shown by the DOM Inspector as a simple empty element, but if broken, it exposes the internal Shadow DOM structure like this:</p>
  
  <pre><code>&lt;div id="alttext-container" style="overflow: hidden; border: 1px solid silver; display: inline-block; box-sizing: border-box; padding: 1px;"&gt;
    &lt;img id="alttext-image" width="16" height="16" align="left" style="margin: 0px; float: left; display: inline;"&gt;
    &lt;div id="alttext" style="overflow: hidden; display: block;"&gt;Alt text&lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Probably because the broken <code>img</code> is displayed with the help of the shadow <code>div</code>s, it's possible to apply pseudo elements to it in this case only (<a href="http://bitsofco.de/styling-broken-images/" rel="noreferrer">4</a>).</p>
  
  <p>Current WebKit doesn't support pseudo elements for <code>img</code>. But, interestingly, at least iOS 9.2.1 Safari starts to support them after setting the <code>content</code> property for that <code>img</code> (<a href="http://bitsofco.de/styling-broken-images/#comment-2559833379" rel="noreferrer">5</a>).</p>
  
  <p>Why does this property make such change? I guess that if an empty element gets any content (even generated), the browser has to provide something to display this content in, effectively replacing the empty element with some sort of a container (like Blink's shadow <code>div id="alttext-container"</code>), and this container can have pseudos. Am I wrong? And wasn't this behavior removed from the latest WebKit versions?</p>