Skip to main content

jan 17, 2025

🔗 Paper over files: print a blog post in plain markdown

Front-end developers spend a lot of time thinking about the way a website content is going to be consumed. Not only a web page must work well on devices of all sizes and formats, but a website content must also take accessibility into consideration. This means the markup should use all the proper semantics and attributes to be parsed effectively by screen readers and other assistive technologies. On top of this content and markup is constructed to be processed by search engines too, which means another set of attributes and metadata to be added to the page.

Interestingly, another way to consume a website content, which is often overlooked, is by printing it. The CSS specification for printing styles is actually quite rich has existed for a very long time. It allows to set specific styles for printing a page by using the @media print rule. This can be used to remove unnecessary elements from the page, like navigation bars, sidebars, and footers, and to style the content in a way that is more suitable for printing.

That made me think that printing a blog post, whose content was originally generated from a markdown file, can actually be a way of preserving its original content and make it even portable on the long term.

With few CSS rules, it is possible to style the content in a way that reflects the plain text which generated it, and it can be done without any JavaScript or server-side processing. This technique uses the CSS pseudo-elements ::before and ::after to add the markdown syntax to the content, like # for headings, * for strong text, _ for emphasized text, and - for list items. Here are some examples of how this can be done.

@media print {
	h1::before {
		content: "# ";
	}

	strong::before {
		content: "**";
	}

	strong::after {
		content: "**";
	}

	em::before {
		content: "_";
	}

	em::after {
		content: "_";
	}

	ul > li::marker {
		content: "- ";
	}

	pre[class*="language-"]::before {
		content: "```";
		display: block;
	}

	pre[class*="language-"]::after {
		content: "```";
		display: block;
	}
}

This technique can be used to generate the markdown syntax for links by using the attr() function to get the value of the href attribute of the link and add it to the content of the pseudo-element.

a::before {
	content: "[";
}

a::after {
	content: "](" attr(href) ")";
}

This method has some limitations though, as it can't be used to style images, since replaced elements can't have pseudo-elements. This means that images will be printed as they are, without any markdown syntax.

/* Not working because replaced elements can't have pseudo elements */
img::after,
picture::after {
	display: block;
	content: "![" attr(alt) "](" attr(src) ")";
}

This experiment is inspired by the original html quine, which uses the same technique to print the HTML tags next to the content.

This is it! 🖨️ Click CMD + P to print this page, and see how the plain markdown of this page looks. If are looking to implement this on your blog too you can grab the file in the repository and let me know how it goes.

# Repository

# Resources