So, I did some tests based on @SWilk's advice. Here is how I did it:
1) Set up a basic HTML page with an empty <style> in <head> and a simple example that he provided in the <script> at the bottom of the <body> :
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Performance test</title> <style> </style> </head> <body onload="onLoad()"> <div class="container"></div> <script> function onLoad() { var now = new Date().getTime(); var page_load_time = now - performance.timing.navigationStart; console.log("User-perceived page loading time: " + page_load_time); } </script> </body> </html>
2) Fill out the div.container loaaads HTML. In my case, I went to html-ipsum.com (there was no advertising), copied each sample, combined everything together and duplicated it several times. My last HTML file was 1.70 MB , and div.container had 33264 children (direct or not), I found out by calling console.log(document.querySelectorAll('.container *').length); )
3) I ran this page 10 times in recent Firefox and Chrome, each time with an empty cache.
Here are the results without a scary set of CSS rules (in ms):
Firefox : 1785 1503 1435 1551 1526 1429 1754 1526 2009 1486 Average : 1600 Chrome : 1102 1046 1073 1028 1038 1026 1011 1016 1035 985 Average : 1036
(If you're wondering why there is such a difference between the two, I have a lot more extensions in Firefox. I let them because I thought it would be interesting to further diversify the test environments.)
4) Add the CSS we want to test in the empty <style> :
html:before, html:after, body:before, body:after, div:before, div:after, p:before, p:after, ul:before, ul:after, li:before, li:after, h1:before, div:after, strong:before, strong:after, em:before, em:after, code:before, code:after, h2:before, div:after, ol:before, ol:after, blockquote:before, blockquote:after, h3:before, div:after, pre:before, pre:after, form:before, form:after, label:before, label:after, input:before, input:after, table:before, table:after, thead:before, thead:after, tbody:before, tbody:after, tr:before, tr:after, th:before, th:after, td:before, td:after, dl:before, dl:after, dt:before, dt:after, dd:before, dd:after, nav:before, nav:after { content: ''; }
... and start again. Here I indicate each tag used on the page, instead of * (since it is counter-performant in itself, and we want to track only the launch of the pseudo-element).
So, here are the results with all pseudo-elements called (still in ms):
Firefox : 1608 1885 1882 2035 2046 1987 2049 2376 1959 2160 Average : 1999 Chrome : 1517 1594 1582 1556 1548 1545 1553 1525 1542 1537 Average : 1550
According to these numbers, we can conclude that the page load is really slower (about 400-500 ms) with the content: '' declaration on each pseudo-element .
Now the remaining question: is this the additional loading time that we see here is significant, given the relatively large test page that was used ? I assume this depends on the size of the website / project, but I will let more experienced people with web performance give their opinion here if they want to.
If you conduct your own tests, feel free to post your findings here, as I am very interested in reading them, and I think that I will not be the only one.