<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[PrintCSS - Medium]]></title>
        <description><![CDATA[On PrintCSS.blog you find everything you need to know about PrintCSS, aka CSS Paged Media! You will get news on different rendering tools and tips and tricks to improve your print documents. - Medium]]></description>
        <link>https://medium.com/printcss?source=rss----25c26773acba---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>PrintCSS - Medium</title>
            <link>https://medium.com/printcss?source=rss----25c26773acba---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 10:43:16 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/printcss" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[The string-set property and the string() function]]></title>
            <link>https://medium.com/printcss/the-string-set-property-and-the-string-function-5fc8f73e413?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/5fc8f73e413</guid>
            <category><![CDATA[css-paged-media-module]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[named-strings]]></category>
            <category><![CDATA[pdf]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Sun, 17 Oct 2021 12:30:34 GMT</pubDate>
            <atom:updated>2021-10-17T12:30:33.853Z</atom:updated>
            <content:encoded><![CDATA[<p>In today’s post, I want to show you how to use <a href="https://www.w3.org/TR/css-gcpm-3/#setting-named-strings-the-string-set-pro">the string-set property</a> and <a href="https://www.w3.org/TR/css-gcpm-3/#using-named-strings">the string() function</a> in your PrintCSS project.</p><p>With <a href="https://www.w3.org/TR/css-gcpm-3/#setting-named-strings-the-string-set-pro">string-set</a>, you can copy an element’s text content or attribute value to a named string (variable). You can use this <a href="https://www.w3.org/TR/css-gcpm-3/#named-strings">named string</a> in other elements with the help of the content property and <a href="https://www.w3.org/TR/css-gcpm-3/#using-named-strings">the string() function</a>.</p><p>One practical example is showing the current chapter title in the header of each page.</p><figure><img alt="A sample page with the chapter title “Platea curae”" src="https://cdn-images-1.medium.com/max/811/1*5tcISeAQMu1YzUdlY0Vhmg.png" /><figcaption>A sample page with the chapter title “Platea curae”</figcaption></figure><p>Let’s assume we have the following HTML:</p><pre>&lt;!DOCTYPE html&gt;<br>&lt;html&gt;<br>    &lt;head&gt;<br>        &lt;meta charset=&quot;UTF-8&quot;&gt;<br>        &lt;title&gt;The string-set property and the string() function&lt;/title&gt;<br>        &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot; /&gt;<br>    &lt;/head&gt;<br>    &lt;body&gt;<br>        &lt;h1&gt;Semper purus dolor&lt;/h1&gt;<br>        &lt;p&gt;<br>            Semper purus dolor, in interdum imperdiet! Egestas eleifend conubia platea pellentesque nostra vitae ut nisi vestibulum pulvinar. Tempus elementum dapibus natoque primis lectus hendrerit ad phasellus potenti. Elementum dui fames laoreet proin neque platea taciti. Tortor, at aliquam mollis. Vivamus vehicula habitasse tincidunt aliquet himenaeos maecenas parturient fusce dictum. Tempor taciti auctor tempus taciti neque. Hac primis ante, viverra nam in! Magna gravida accumsan dis.<br>        &lt;/p&gt;<br>        &lt;p&gt;<br>            Commodo nibh congue commodo praesent torquent morbi sociis. Laoreet ad class dolor mus pretium at odio vulputate euismod! Massa, quis ornare sit consequat elit fames suscipit diam felis vulputate tristique aliquet? Aenean vivamus duis elit ipsum nullam diam velit quisque faucibus nullam! Facilisis ultricies cras molestie quam pharetra nullam tincidunt ipsum. Tempus commodo congue inceptos varius ligula? Facilisis vestibulum pulvinar taciti ad cum tincidunt.<br>        &lt;/p&gt;<br>        &lt;p&gt;<br>            Commodo nibh congue commodo praesent torquent morbi sociis. Laoreet ad class dolor mus pretium at odio vulputate euismod! Massa, quis ornare sit consequat elit fames suscipit diam felis vulputate tristique aliquet? Aenean vivamus duis elit ipsum nullam diam velit quisque faucibus nullam! Facilisis ultricies cras molestie quam pharetra nullam tincidunt ipsum. Tempus commodo congue inceptos varius ligula? Facilisis vestibulum pulvinar taciti ad cum tincidunt.<br>        &lt;/p&gt;<br>        &lt;h1&gt;Platea curae&lt;/h1&gt;<br>        &lt;p&gt;<br>            Platea curae; ultrices donec arcu sociis phasellus justo turpis ante interdum velit semper? Etiam natoque velit sem per? Habitant lobortis, blandit aliquet molestie congue metus eu venenatis mattis urna fermentum potenti. Molestie nascetur lectus leo. Adipiscing blandit tristique conubia commodo elementum rutrum vulputate. Consequat consectetur natoque diam pharetra, sociis vivamus fusce cubilia. Maecenas fringilla taciti condimentum litora. Rhoncus conubia facilisi suspendisse sociis habitasse ad penatibus iaculis ultricies montes. Dolor penatibus curae; molestie quam pellentesque rutrum. Porttitor praesent vulputate dictum bibendum lacus inceptos, tempor nam.<br>        &lt;/p&gt;<br>        &lt;p&gt;<br>            Commodo nibh congue commodo praesent torquent morbi sociis. Laoreet ad class dolor mus pretium at odio vulputate euismod! Massa, quis ornare sit consequat elit fames suscipit diam felis vulputate tristique aliquet? Aenean vivamus duis elit ipsum nullam diam velit quisque faucibus nullam! Facilisis ultricies cras molestie quam pharetra nullam tincidunt ipsum. Tempus commodo congue inceptos varius ligula? Facilisis vestibulum pulvinar taciti ad cum tincidunt.<br>        &lt;/p&gt;<br>        &lt;h1&gt;Commodo&lt;/h1&gt;<br>        &lt;p&gt;<br>            Commodo nibh congue commodo praesent torquent morbi sociis. Laoreet ad class dolor mus pretium at odio vulputate euismod! Massa, quis ornare sit consequat elit fames suscipit diam felis vulputate tristique aliquet? Aenean vivamus duis elit ipsum nullam diam velit quisque faucibus nullam! Facilisis ultricies cras molestie quam pharetra nullam tincidunt ipsum. Tempus commodo congue inceptos varius ligula? Facilisis vestibulum pulvinar taciti ad cum tincidunt.<br>        &lt;/p&gt;<br>        &lt;p&gt;<br>            Leo vivamus, convallis mauris primis. Quis netus eros, consequat metus ligula facilisis id primis in facilisis vehicula neque! Nisl quam dis quis pellentesque diam parturient sociis sed adipiscing. Sociosqu at aliquam viverra vehicula. Turpis maecenas nascetur facilisi? Potenti hendrerit sollicitudin mollis lorem fusce taciti molestie tempor mollis. Nulla semper quam cursus dictumst elementum fusce ridiculus amet sed primis nunc ipsum. Vel vel et ac a, nec nullam inceptos proin aliquet dignissim. Sociosqu scelerisque tristique orci posuere gravida massa? Sem cras aliquet, lectus class vulputate ullamcorper potenti eleifend dictumst cubilia.<br>        &lt;/p&gt;<br>        &lt;p&gt;<br>            Maecenas porttitor parturient at. Neque euismod ipsum congue vulputate placerat. Enim vestibulum diam eu sociosqu felis sociis nascetur nascetur quam nibh rhoncus? Vehicula non egestas inceptos arcu ultrices feugiat aliquet ad. Ipsum venenatis hendrerit ligula! Aliquam ridiculus ultrices morbi magnis malesuada massa nulla consequat? Dis quam sociis phasellus nascetur egestas cursus parturient eget sollicitudin euismod non magnis. Fringilla eget vestibulum mauris montes, sociosqu sodales lacus! Habitasse est eleifend facilisi venenatis ac. At nunc dictumst nulla cursus bibendum nec fermentum ultrices etiam. Primis consectetur fames convallis lobortis! Fermentum.<br>        &lt;/p&gt;<br>    &lt;/body&gt;<br>&lt;/html&gt;</pre><p>And a basic CSS that defines the page size and margin via <a href="https://www.w3.org/TR/css-page-3/#at-page-rule">the @page rule</a>. Additionally, we define that each H1 element should start on a new page. For the first H1 element, we do not want a page break as we would get an empty first page otherwise.</p><pre>@page{<br>    size: A6;<br>    margin: 20mm;<br>}</pre><pre>h1{<br>  break-before:always;<br>}</pre><pre>h1:first-of-type{<br>  break-before:none;<br>}</pre><p>Now we want to show the current chapter’s name (the content of the H1 element) as the header on each page.</p><p>For this, we first need to set our <a href="https://www.w3.org/TR/css-gcpm-3/#named-strings">named string</a> in the CSS:</p><pre>@page{<br>    size: A6;<br>    margin: 20mm;<br>}</pre><pre>h1{<br>  break-before:always;<br>  string-set: chapterTitle content();<br>}</pre><pre>h1:first-of-type{<br>  break-before:none;<br>}</pre><p>After that, we need to define the desired page margin box, and use that named string with <a href="https://www.w3.org/TR/css-gcpm-3/#using-named-strings">the string() function</a>.</p><pre>@page{<br>    size: A6;<br>    margin: 20mm;<br>    <br>    @top-center{<br>      content: string(chapterTitle, first);<br>    }<br>}<br><br>h1{<br>  break-before:always;<br>  string-set: chapterTitle content();<br>}<br><br>h1:first-of-type{<br>  break-before:none;<br>}</pre><p>The second parameter of <a href="https://www.w3.org/TR/css-gcpm-3/#using-named-strings">the string() function</a> defines whether you want to use the first or last named string on the page. This is an important setting if you have two H1 elements on one page and, for example, want to show the content of the last one. There are also other parameters you can pass. You find the documentation in the <a href="https://www.w3.org/TR/css-gcpm-3/#using-named-strings">W3C working draft for CSS Generated Content for Paged Media Module</a>.</p><p>Now you might ask yourself which rendering tools are supporting <a href="https://www.w3.org/TR/css-gcpm-3/#setting-named-strings-the-string-set-pro">string-set</a> and <a href="https://www.w3.org/TR/css-gcpm-3/#using-named-strings">string()</a>.</p><p>Checking on <a href="https://printcss.live/">printcss.live</a>, it is supported by:</p><ul><li>AH Formatter</li><li>Prince (and, of course, the API Version DocRaptor)</li><li>PagedJS</li><li>PDFReactor</li><li>Vivliostyle</li><li>and WeasyPrint</li></ul><p>You can get <a href="https://github.com/azettl/printcss.examples/tree/main/PrintCSS%20Features/Named%20Strings">the complete code on Github</a> or view it directly on <a href="https://printcss.live/WJxboVKagw">the PrintCSS Playground</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5fc8f73e413" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/the-string-set-property-and-the-string-function-5fc8f73e413">The string-set property and the string() function</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Magazine the WordPress Plugin for PrintCSS]]></title>
            <link>https://medium.com/printcss/magazine-the-wordpress-plugin-for-printcss-e357fd0fb6ff?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/e357fd0fb6ff</guid>
            <category><![CDATA[wordpress-plugins]]></category>
            <category><![CDATA[pdf]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[wordpress]]></category>
            <category><![CDATA[wordpress-web-development]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Fri, 26 Mar 2021 01:14:26 GMT</pubDate>
            <atom:updated>2021-03-26T20:24:20.869Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/678/1*UAuhn-yXSzL21uYPDF4Nxg.png" /></figure><p>In the last few weeks, I am working on a <a href="https://gumroad.com/l/wp-magazine-printcss-cloud">WordPress Plugin</a>, which allows you to generate PDFs from one or multiple posts/pages. Initially, it was designed to work only with my <a href="https://printcss.cloud/">PrintCSS Cloud</a>, which I introduced in the <a href="https://printcss.blog/introducing-printcss-cloud-686622f4042a">previous article</a>, but now the plugin is opened to any rendering tool you want to use.</p><h3>Installation and Setup</h3><p>All you need to do to install the plugin is download it from <a href="https://gumroad.com/l/wp-magazine-printcss-cloud">Gumroad</a>. You can pay what you want starting from <strong>$0</strong>!</p><p>Once you installed the ZIP file via the WordPress ‘Upload Plugins’ function or placed the extracted folder in your ‘wp-content/plugins’ directory, you need to activate the plugin.</p><p>After the installation, you will need to provide an API key or locally installed rendering tool command on the settings page under ‘Settings’ &gt; ‘Magazine’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Xd3k9yJU3PkdSXVfdGNG_A.png" /><figcaption>The Settings of the Magazine Plugin</figcaption></figure><p>On the settings screen, you find the following options.</p><ul><li><strong>Rendering Tool: </strong>Depending on the filled API Key and Local Command Options, you see the supported rendering tools here. You need to use at least one of the API or the local command options for a rendering tool to appear in this selection.</li><li><strong>RapidAPI Key: </strong>To send the PrintCSS Cloud API request, you <a href="https://rapidapi.com/azettl/api/printcss-cloud/pricing">need to subscribe to a plan on RapidAPI</a>. With this, you get the API key required to authenticate with the PrintCSS Cloud REST service. The PrintCSS Cloud supports the rendering tools <a href="https://weasyprint.org/">WeasyPrint</a>, <a href="https://www.pagedjs.org/">PagedJS</a>, and <a href="https://vivliostyle.org/">Vivliostyle</a>.</li><li><strong>DocRaptor Key: </strong>To send the DocRaptor API request, you <a href="https://docraptor.com/signup">need to subscribe to a plan on docraptor.com</a>. With this, you get the API key that is required to authenticate with the REST service.</li><li><strong>Typeset.sh Project Key &amp; Project Token: </strong>To send the request to the typeset.sh API, you <a href="https://typeset.sh/en/register">need to subscribe to a plan on typeset.sh</a>. With this, you get the project key and token required to authenticate with their REST service.</li><li><strong>Local Command: </strong>If you have a PDF rendering tool installed locally, you can provide the command here, be aware that the tool needs to support getting the HTML via STDIN and needs to return the PDF via STDOUT.</li><li><em>AH Formatter Example:</em> /usr/AHFormatterV71_64/run.sh -x 4 -d @STDIN -o @STDOUT</li><li><em>Prince Example:</em> prince — no-warn-css — javascript -</li><li><em>PDFreactor Example:</em> cd /path/to/sh/script/ &amp;&amp; ./pdfreactor.sh (Get the script <a href="https://gist.github.com/azettl/8546b17bd4880ce44c9b5b2b2ca596a9">on GitHub</a>)</li></ul><h3>Change the Demo Theme and Add Multiple Themes</h3><p>All magazine themes are placed in the ‘wp-content/magazine_themes’ folder and can be directly edited there. If you prefer editing your theme directly in the WordPress UI, you can do so under ‘Appearance’ &gt; ‘Magazine’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HrhdNRS7nZif0NE44xzpgw.png" /><figcaption>The Magazine Theme Editor</figcaption></figure><p>A magazine theme for PDF generation is using the following files. All of them are optional. If you use the magazine theme editor, all files will be generated even if you do not provide any content for some of them.</p><p>Besides editing the theme, you can also duplicate, upload and download themes from this section in the WordPress backend.</p><h4>HTML</h4><p>In the HTML section of the magazine theme editor, you can edit all HTML files.</p><ul><li><strong>Prefix (prefix.html): </strong>The prefix HTML you can use for front covers or intros, basically anything which should be added only once at the beginning of the PDF. In the prefix, you can not use any placeholders.</li><li><strong>Post (post.html): </strong>The post HTML will be loaded whenever you want to render a Blogpost PDF; this file gets added once per selected Blogpost. So if you choose 5 Blogposts, this HTML gets repeated five times. Within the post HTML, you can use any placeholders, for example, the <em>{{title}}</em> to always show the current Blogpost title.</li><li><strong>Page (page.html): </strong>The page HTML will be loaded whenever you want to render a PDF from a page. This file gets added once per selected page. So if you choose five pages, this HTML gets repeated five times. Within the page HTML, you can use any placeholders, for example, the <em>{{title}}</em> to always show the current page title.</li><li><strong>Postfix (postfix.html): </strong>The postfix HTML you can use for back covers or indexes, basically anything which should be added only once at the end of the PDF. In the postfix, you can not use any placeholders.</li></ul><p>You can leave any of these HTML files empty if you do not need them. For example, if you do not need a cover, do not put content into the prefix HTML.</p><h4>CSS</h4><p>In the magazine theme editor’s CSS section, you can edit all CSS files of any theme.</p><ul><li><strong>Main (style.css): </strong>The main CSS is loaded for any rendering you do. In the main CSS, you can not use any placeholders.</li><li><strong>Post (post.css): </strong>The post CSS will be loaded whenever you want to render a Blogpost PDF; this file gets added once per selected Blogpost. So if you choose 5 Blogposts, this CSS gets repeated five times. Within the post CSS, you can use any placeholders, for example, the <em>{{slug}}</em> to get one class per Blogpost slug.</li><li><strong>Page (page.css): </strong>The page CSS will be loaded whenever you want to render a page PDF; this file gets added once per selected page. So if you choose five pages, this CSS gets repeated five times. Within the post CSS, you can use any placeholders, for example, the <em>{{slug}}</em> to get one class per page slug.</li></ul><p>You can also leave any of these CSS files empty if you do not need them. For example, if you do not need a Blogpost specific CSS, do not put content into the post CSS file.</p><h4>JavaScript</h4><p>In the magazine theme editor’s JavaScript section, you can edit all JavaScript files of your theme. <strong>Be aware that some rendering tools only support HTML and CSS.</strong></p><ul><li><strong>Main (script.js): </strong>The main JavaScript is loaded for any rendering you do. In the main JavaScript, you can not use any placeholders.</li><li><strong>Post (post.js): </strong>The post JavaScript will be loaded whenever you want to render a Blogpost PDF; this file gets added once per selected Blogpost. So if you choose 5 Blogposts, this JavaScript gets repeated five times. Within the post JavaScript, you can use any placeholders, for example, the <em>{{slug}}</em> to get one class per Blogpost slug.</li><li><strong>Page (page.js): </strong>The page JavaScript will be loaded whenever you want to render a page PDF; this file gets added once per selected page. So if you choose five pages, this JavaScript gets repeated five times. Within the post JavaScript, you can use any placeholders, for example, the <em>{{slug}}</em> to get one class per page slug.</li></ul><p>You can leave any of these JavaScript files empty if you do not need them. For example, if you do not need a Blogpost specific JavaScript, do not put content into the post JavaScript file.</p><h4>The Placeholders</h4><p>The placeholders <em>{{slug}}</em>, <em>{{title}}</em>, <em>{{feature_image}}</em> and <em>{{content}}</em> are for the post/page slug, title, feature image and content. Additionally you can use the placeholders <em>{{author}}</em>, <em>{{date}}</em>, <em>{{date_gmt}}</em>, <em>{{excerpt}}</em>, <em>{{status}}</em>. If you need to show the date of the post/page in a different format you can use the placeholders <em>{{year}}</em>, <em>{{month}}</em>, <em>{{day}}</em>, <em>{{hour}}</em>, <em>{{minute}}</em>.</p><p><strong>Please be aware that images need to be available via a public URL for the APIs to use them.</strong></p><p>ACF is also supported. Just add <em>{{ACF_YOUR_FIELD_NAME}}</em>. <strong>Important: use the name, not the label!</strong></p><h3>The Widget</h3><p>If your WordPress theme support widgets, you can configure a simple PDF rendering widget for your frontend. The widget options are the title of your PDF rendering link and the magazine theme you want to render the PDF with. This way, you allow your users to generate PDFs anytime they want to.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2GZsaxNg8Ly1YtDJgWXCeg.png" /><figcaption>The Magazine Render PDF Widget with Text and Theme Options.</figcaption></figure><h3>Shortcode</h3><p>You can also use a shortcode to display a link to render the PDF in any location of your post or page.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/759/1*0DoGa3LrQL-_MMcDAUBoAw.png" /><figcaption>The shortcode added to a post.</figcaption></figure><p>The primary usage is just the tag and an attribute that defines the theme <em>[magazine theme=”Demo”]</em>. If you also want to change the text of the link, you can pass it with <em>[magazine theme=”Demo” text=”Click here for PDF Version”]</em>.</p><h3>Backend and Bulk PDF Rendering</h3><p>When you want to render a PDF from one or multiple pages/blog posts, just navigate to the ‘All Posts’ or ‘All Pages’ sites in the backend. Select the pages/posts you want to have in your PDF and click on the ‘Bulk Actions’ dropdown. Depending on your magazine themes, you will see one or multiple entries like ‘Render PDF with Demo Theme’, select the theme you like and click on apply. Currently, the rendering process is always synchronous, so you will need to wait for the API/local tool to answer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uoY6OsKYyFyOUvjMq4F9FQ.png" /><figcaption>Bulk Actions for the three different Magazine Themes on my system.</figcaption></figure><p>The resulting PDF is stored in the Media Library. It is also offered to you for downloading in a notification on the page where you started the rendering process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r-72e2jPb4RZLIiWqYFh0Q.png" /><figcaption>Result Notification</figcaption></figure><p><strong><em>The plugin is currently in alpha status, and I am looking forward to your feedback and ideas on how to improve it.</em></strong></p><p><strong><em>Lastly, again the link for you to download the plugin: </em></strong><a href="https://gumroad.com/l/wp-magazine-printcss-cloud"><strong><em>Magazine (gumroad.com)</em></strong></a><strong><em>.</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e357fd0fb6ff" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/magazine-the-wordpress-plugin-for-printcss-e357fd0fb6ff">Magazine the WordPress Plugin for PrintCSS</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing PrintCSS Cloud]]></title>
            <link>https://medium.com/printcss/introducing-printcss-cloud-686622f4042a?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/686622f4042a</guid>
            <category><![CDATA[cloud-services]]></category>
            <category><![CDATA[pdf]]></category>
            <category><![CDATA[rest-api]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[html-to-pdf]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Sat, 27 Feb 2021 20:52:36 GMT</pubDate>
            <atom:updated>2021-02-27T20:52:36.177Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/657/1*JLmL-KG_CxLxv41e8ARXQw.png" /><figcaption>PrintCSS Cloud Logo</figcaption></figure><p>Today I want to talk to you about my latest project, <a href="https://printcss.cloud/">PrintCSS Cloud</a>, an HTML to PDF REST API. Another HTML to PDF API you might ask, yes! Other APIs usually lack even minimal CSS Paged Media support. Some of them support the @page rule and nothing else. PrintCSS Cloud supports most of the features defined in CSS Paged Media. This works because there is not only a headless Chromium used to generate the PDFs but three of the most advanced OpenSource rendering tools, <a href="https://weasyprint.org/">WeasyPrint</a>, <a href="https://www.pagedjs.org/">PagedJS</a>, and <a href="https://vivliostyle.org/">Vivliostyle</a>!</p><p>The Print CSS features covered thanks to these renderers are:</p><ul><li><strong>Running Headers and Footers: </strong>This feature is supported by two of the three rendering tools, WeasyPrint and PagedJS. Have a look at a sample document on <a href="https://printcss.live/oBDbDxbl2E">printcss.live</a>.</li><li><strong>Counters and Cross References: </strong>CSS counters and the target-counters property can be used with WeasyPrint and Vivliostyle; again, there is a sample document on <a href="https://printcss.live/K4oeEva0By">printcss.live</a>.</li><li><strong>Page Margin Boxes: </strong>16 Page Margin Boxes are waiting for your content in all three rendering tools, have a look on <a href="https://printcss.live/xYRdG7dDzO">printcss.live</a> to see how this is working.</li><li><strong>Footnotes: </strong>Does your PDF need footnotes? Then it would be best if you rendered with Vivliostyle; this renderer offers basic footnote support. See a sample on the <a href="https://printcss.live/1YQdJ2dOGp">PrintCSS Playground</a>.</li><li><strong>Page Selectors and Page Breaks: </strong>The best support for page selectors like @page:blank you get with WeasyPrint, but no worries, the other tools support the most selectors too! See it in action on the <a href="https://printcss.live/4y1aKReQGw">PrintCSS Playground</a>.</li><li><strong>JavaScript Support: </strong>PagedJS and Vivliostyle both handle JavaScript just like your browser would do. Why? Because they also use a headless Chromium in the background but have a layer on top to support the modern CSS Paged Media features.</li></ul><p>The API is currently in alpha status, and I would really appreciate your feedback! Till the final Go-Live, I only have a free plan including 500 requests per month, which should be more than enough to give you an idea of the possibilities and test the API. If you still need more requests for testing, please let me know.</p><p>But now, let us see how to work with the API. To send a request to the API, you <a href="https://rapidapi.com/azettl/api/printcss-cloud/pricing">need to subscribe to a plan on RapidAPI</a>. With this, you get the API key that is required to authenticate with the REST service.</p><h3>A simple request with HTML and CSS</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qhY0tccMIrRhYVthtwrkXg.png" /><figcaption>The result of the API request below.</figcaption></figure><p>To create a PDF from your HTML, you need to pass both HTML and CSS code in a JSON structure as the body of the POST request to the API. The JSON structure you need to send should look like the following:</p><pre>{<br>	&quot;html&quot;: &quot;&quot;,<br>	&quot;css&quot;:  &quot;&quot;<br>}</pre><p>Now let us assume you have the following HTML and CSS code.</p><pre>&lt;!DOCTYPE html&gt;<br>&lt;html&gt;<br>    &lt;head&gt;<br>        &lt;meta charset=&quot;UTF-8&quot;&gt;<br>        &lt;title&gt;Basic Example&lt;/title&gt;<br>        &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot; /&gt;<br>    &lt;/head&gt;<br>    &lt;body&gt;<br>     &lt;h1&gt;Hello PrintCSS Cloud!&lt;/h1&gt;<br>    &lt;/body&gt;<br>&lt;/html&gt;</pre><p>The style.css, mentioned in the HTML code, only sets the color of the H1 element to blue.</p><pre>h1{  color:blue; }</pre><p>You will only need the HTML, which is in between the BODY tag. The rest can be skipped. So the same content in your JSON structure would look like this:</p><pre>{<br>	&quot;html&quot;: &quot;&lt;h1&gt;Hello PrintCSS Cloud!&lt;/h1&gt;&quot;,<br>	&quot;css&quot;:  &quot;h1{ color:blue; }&quot;<br>}</pre><p>All you need to do to get the PDF is to send one POST request to the API and not forget to add your <a href="https://rapidapi.com/azettl/api/printcss-cloud">RapidAPI authentification key</a>.</p><pre>curl --location --request POST &#39;https://printcss-cloud.p.rapidapi.com/render&#39; \<br>--header &#39;x-rapidapi-host: printcss-cloud.p.rapidapi.com&#39; \<br>--header &#39;x-rapidapi-key: YOUR_API_KEY&#39; \<br>--data-raw &#39;{<br>    &quot;html&quot;: &quot;&lt;h1&gt;Hello PrintCSS Cloud!&lt;/h1&gt;&quot;,<br>    &quot;css&quot;:  &quot;h1{ color:blue; }&quot;<br>}&#39;</pre><p>The same request in PHP would look like this:</p><pre>&lt;?php</pre><pre>$curl = curl_init();</pre><pre>curl_setopt_array($curl, array(<br>  CURLOPT_URL =&gt; &#39;https://printcss-cloud.p.rapidapi.com/render&#39;,<br>  CURLOPT_RETURNTRANSFER =&gt; true,<br>  CURLOPT_ENCODING =&gt; &#39;&#39;,<br>  CURLOPT_MAXREDIRS =&gt; 10,<br>  CURLOPT_TIMEOUT =&gt; 0,<br>  CURLOPT_FOLLOWLOCATION =&gt; true,<br>  CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,<br>  CURLOPT_CUSTOMREQUEST =&gt; &#39;POST&#39;,<br>  CURLOPT_POSTFIELDS =&gt;&#39;{<br> &quot;html&quot;: &quot;&lt;h1&gt;Hello PrintCSS Cloud!&lt;/h1&gt;&quot;,<br> &quot;css&quot;:  &quot;h1{ color:blue; }&quot;<br>}&#39;,<br>  CURLOPT_HTTPHEADER =&gt; array(<br>    &#39;x-rapidapi-host: printcss-cloud.p.rapidapi.com&#39;,<br>    &#39;x-rapidapi-key: YOUR_API_KEY&#39;<br>  ),<br>));</pre><pre>$response = curl_exec($curl);</pre><pre>curl_close($curl);<br>echo $response;</pre><p>and in JavaScript:</p><pre>var data = &quot;{\r\n \&quot;html\&quot;: \&quot;&lt;h1&gt;Hello PrintCSS Cloud!&lt;/h1&gt;\&quot;,\r\n \&quot;css\&quot;:  \&quot;h1{ color:blue; }\&quot;\r\n}&quot;;</pre><pre>var xhr = new XMLHttpRequest();<br>xhr.withCredentials = true;</pre><pre>xhr.addEventListener(&quot;readystatechange&quot;, function() {<br>  if(this.readyState === 4) {<br>    console.log(this.responseText);<br>  }<br>});</pre><pre>xhr.open(&quot;POST&quot;, &quot;https://printcss-cloud.p.rapidapi.com/render&quot;);<br>xhr.setRequestHeader(&quot;x-rapidapi-host&quot;, &quot;printcss-cloud.p.rapidapi.com&quot;);<br>xhr.setRequestHeader(&quot;x-rapidapi-key&quot;, &quot;YOUR_API_KEY&quot;);</pre><pre>xhr.send(data);</pre><p>As the <a href="https://printcss.cloud/">PrintCSS Cloud API</a> offers the three rendering tools <a href="https://weasyprint.org/">WeasyPrint</a> (default), <a href="https://www.pagedjs.org/">PagedJS</a>, and <a href="https://vivliostyle.org/">Vivliostyle</a>. You can change the tool within your request’s body JSON.</p><pre>{<br>	&quot;html&quot;: &quot;&lt;h1&gt;Hello PrintCSS Cloud!&lt;/h1&gt;&quot;,<br>	&quot;css&quot;:  &quot;h1{ color:blue; }&quot;,<br>	&quot;options&quot;: {<br>		&quot;renderer&quot;: &quot;vivliostyle&quot;<br>	}<br>}</pre><p>As you see in the above request body, the renderer needs to be provided in lowercase. This request would now render the PDF with Vivliostyle instead of the standard WeasyPrint.</p><h3>Add JavaScript</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vdUQhSexL--eyZVJvpXJJg.png" /><figcaption>The background color is set via JavaScript.</figcaption></figure><p><a href="https://www.pagedjs.org/">PagedJS</a> and <a href="https://vivliostyle.org/">Vivliostyle</a> both handle JavaScript just like your browser would do. WeasyPrint does not support JavaScript, so if you pass the <em>javascript </em>key in the request’s body, the default renderer changes to PagedJS. If you pass JavaScript in the HTML directly, you would need to change the renderer yourself, as shown above.</p><p>To send JavaScript, either you directly put it in a SCRIPT tag within your HTML or add it in the JavaScript section within the JSON body.</p><pre>{<br>	&quot;html&quot;: &quot;&lt;h1 id=&#39;js&#39;&gt;Hello PrintCSS Cloud!&lt;/h1&gt;&quot;,<br>	&quot;css&quot;:  &quot;h1{ color:red; }&quot;,<br>	&quot;javascript&quot;: &quot;document.getElementById(&#39;js&#39;).style.backgroundColor=&#39;blue&#39;;&quot;<br>}</pre><p>The above JS code should set the background color of the header element to blue. Compared to the samples before, the text color in this one got changed to red.</p><p>The request looks the same as for the simple HTML and CSS sample just that we added the JavaScript:</p><pre>curl --location --request POST &#39;https://printcss-cloud.p.rapidapi.com/render&#39; \<br>--header &#39;x-rapidapi-host: printcss-cloud.p.rapidapi.com&#39; \<br>--header &#39;x-rapidapi-key: YOUR_API_KEY&#39; \<br>--data-raw &#39;{<br>	&quot;html&quot;: &quot;&lt;h1 id=&#39;\&#39;&#39;js&#39;\&#39;&#39;&gt;Hello PrintCSS Cloud!&lt;/h1&gt;&quot;,<br>	&quot;css&quot;:  &quot;h1{ color:red; }&quot;,<br>	&quot;javascript&quot;: &quot;document.getElementById(&#39;\&#39;&#39;js&#39;\&#39;&#39;).style.backgroundColor=&#39;\&#39;&#39;blue&#39;\&#39;&#39;;&quot;<br>}&#39;</pre><h3>Include Images and Fonts without using external URLs</h3><p>There are two ways to include your images or fonts in the PDF either you have them available via a public URL or provide a base64 encoded ZIP file within the requests body. The ZIP file is the preferred way as you do not need to provide your assets elsewhere. The API supports the following file types for images:</p><ul><li>gif</li><li>jpeg</li><li>jpg</li><li>png</li><li>svg</li><li>bmp</li><li>tif</li><li>tiff</li></ul><p>Next to images, the API also supports CSS, JavaScript, and custom Fonts in the assets ZIP if they have one of the file types below:</p><ul><li>css</li><li>js</li><li>woff</li><li>ttf</li><li>otf</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/333/1*h6ANUGdU64L8OjL6nDLBQg.png" /><figcaption>The assets ZIP file</figcaption></figure><p>You can reference your ZIP file’s content with relative links inside the HTML, CSS, and JavaScript code that you provide in the request body. Let us say you have a base64 encoded ZIP containing three images, tree.png, lake.png, and mountain.png, and you want to show them in your PDF. The requests JSON body would look like the following:</p><pre>{<br> &quot;css&quot;: &quot;body{ color:red; } img{display:block;width:auto;height:400px;border:4px solid green;}&quot;,<br> &quot;html&quot;: &quot;&lt;h1&gt;Hello PrintCSS Cloud&lt;/h1&gt;&lt;p&gt;Here is a picture of a tree:&lt;/p&gt;&lt;img src=&#39;tree.png&#39;/&gt;&lt;p&gt;and a lake:&lt;/p&gt;&lt;img src=&#39;lake.png&#39; /&gt;&lt;p&gt;and we also have a picture of a mountain for you:&lt;/p&gt;&lt;img src=&#39;mountain.png&#39; /&gt;&quot;,<br> &quot;assets&quot;: &quot;BASE64_ENCODED_ZIP_FILE_CONTAINING_THE_ASSETS&quot;<br>}</pre><p>Sending this request works again the same as mentioned before, so I skip that part here and just show you a screenshot of the resulting PDF.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1013/1*lXvguP3R7i0v5dym3gyZgg.png" /><figcaption>Relative Linked Images from the passed ZIP file.</figcaption></figure><h3>Dynamic Content</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*weShyAZ94RtP7jO0M28BZA.png" /><figcaption>Rendering date and text transformation via Twig.</figcaption></figure><p>The <a href="https://printcss.cloud/">PrintCSS Cloud API</a> supports the <a href="https://twig.symfony.com/">templating engine Twig</a> for your HTML content. So you can add some dynamic content like the date and time of the PDF rendering or reformat some content, for example, to uppercase. For the full details of Twig’s possibilities, please check their <a href="https://twig.symfony.com/">documentation</a>.</p><p>A small example of what is possible can be seen in the requests JSON body below.</p><pre>{<br> &quot;css&quot;: &quot;body{ color:red; }&quot;,<br> &quot;html&quot;: &quot;Hello PrintCSS Cloud&lt;br/&gt;This document was rendered on {{ &#39;now&#39;|date(timezone=&#39;Europe/Paris&#39;) }}&lt;br/&gt;{% apply upper %}This text becomes uppercase{% endapply %}&quot;<br>}</pre><p>Look at the HTML there are two parts in brackets, the first one will print the current date and time, and the second will transform the text to uppercase.</p><h3>Templating</h3><p>Thanks to Twig, you can also render the same HTML multiple times with different data. Let’s say when you want to create business cards for your whole team or create multiple bills within one document.</p><p>In the JSON body below, you see how to create business cards for 3 different people. The HTML contains placeholders like <em>{{FirstName}} </em>which appear as keys in the single data objects. For each data object, the HTML gets rendered once.</p><pre>{<br> &quot;css&quot;: &quot;@page{size:3.5in 2in;marks:crop;bleed:0.125in;margin:0.25in;}@page back{background:rgb(188,11,6);background-image:url(https://www.html2pdf.guru/assets/img/html2pdf.guru.png);background-position:center;background-repeat:no-repeat;margin:0;}body{font-size:10pt;}b{color:rgb(188,11,6);font-size:1.5rem;}.head{display:inline-block;margin-bottom:.5rem;}.foot{display:inline-block;margin-top:.75rem;border-left:.25rem solid rgb(188,11,6);padding-left:.5rem;}.break{page:back;page-break-after:always;break-after:always;}&quot;,<br> &quot;html&quot;: &quot;&lt;div class=&#39;break&#39;&gt;&lt;/div&gt;&lt;span class=&#39;head&#39;&gt;&lt;b&gt;{{FirstName}} {{LastName}}&lt;/b&gt;&lt;br /&gt;{{Title}}&lt;/span&gt;&lt;br /&gt;{{EMail}}&lt;br /&gt;Mobile {{Phone}}&lt;br /&gt;www.example.com&lt;br /&gt;&lt;span class=&#39;foot&#39;&gt;Example Company&lt;br /&gt;Busystreet 5 &amp;amp;amp;amp;amp;amp;middot; 00001 Gotham&lt;/span&gt;&quot;,<br> &quot;data&quot;: [<br>  {&quot;FirstName&quot;: &quot;Fabien&quot;, &quot;LastName&quot;: &quot;Sample&quot;, &quot;Title&quot;: &quot;Senior Developer&quot;, &quot;EMail&quot;: &quot;f.sample@example.com&quot;, &quot;Phone&quot;: &quot;+49 1234 4444 5555&quot;},<br>  {&quot;FirstName&quot;: &quot;Martin&quot;, &quot;LastName&quot;: &quot;Muster&quot;, &quot;Title&quot;: &quot;Junior Developer&quot;, &quot;EMail&quot;: &quot;m.mustermann@example.com&quot;, &quot;Phone&quot;: &quot;+49 1234 4444 5566&quot;},<br>  {&quot;FirstName&quot;: &quot;Andreas&quot;, &quot;LastName&quot;: &quot;Doe&quot;, &quot;Title&quot;: &quot;CFO&quot;, &quot;EMail&quot;: &quot;a.doe@example.com&quot;, &quot;Phone&quot;: &quot;+49 1234 4444 5577&quot;}<br> ]<br>}</pre><p>The result is an excellent PDF with all the required business cards!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A5xBvKiswQzHtUUxvr30dA.png" /><figcaption>Business Cards, three times the same HTML rendered with the passed data.</figcaption></figure><h3>Asynchronous Requests</h3><p>All you need to do to send the request asynchronous is set sync to false in the requests body JSON. Here is an example of how you can do this:</p><pre>{<br> &quot;css&quot;: &quot;body{ color:red; }&quot;,<br> &quot;html&quot;: &quot;Hello PrintCSS Cloud&quot;,<br> &quot;options&quot;: {<br>  &quot;sync&quot;: &quot;false&quot;<br> }<br>}</pre><p>The response to such an API request will be a JSON with the <em>pdfid</em>:</p><pre>{<br> &quot;pdfid&quot;: &quot;OqE89kpPy7LDdwmLza1YKXAxljVwBJ&quot;<br>}</pre><p>To check your PDF rendering request status, you can pass this JSON as a request body to the API. So your request body looks exactly like the response:</p><pre>{<br> &quot;pdfid&quot;: &quot;OqE89kpPy7LDdwmLza1YKXAxljVwBJ&quot;<br>}</pre><p>As a result, you either get the PDF if the rendering is finished. Or a JSON object telling you your rendering request is still open, in progress, or ran into an error. A sample of such a return can be seen below.</p><pre>{<br> &quot;pdfid&quot;: &quot;OqE89kpPy7LDdwmLza1YKXAxljVwBJ&quot;,<br> &quot;status&quot;: &quot;in_progress&quot;,<br> &quot;message&quot;: &quot;PDF rendering is currently in progress&quot;<br>}</pre><p>In the end, I just wanted to say again that I would really appreciate your feedback! Let me know what you think about the API, how your testing went, and what should be improved or added in the comments below.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=686622f4042a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/introducing-printcss-cloud-686622f4042a">Introducing PrintCSS Cloud</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PrintCSS: Create Planet Posters]]></title>
            <link>https://medium.com/printcss/printcss-create-planet-posters-f68e4c904fac?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/f68e4c904fac</guid>
            <category><![CDATA[poster-design]]></category>
            <category><![CDATA[html-css]]></category>
            <category><![CDATA[poster-printing]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[html2pdf]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Wed, 24 Feb 2021 21:22:27 GMT</pubDate>
            <atom:updated>2021-02-24T21:22:27.686Z</atom:updated>
            <content:encoded><![CDATA[<p>In <a href="https://medium.com/printcss/printcss-create-a-bauhaus-poster-with-the-help-of-html-and-css-d4f97a912b71">the last article</a>, I covered <a href="https://medium.com/printcss/printcss-create-a-bauhaus-poster-with-the-help-of-html-and-css-d4f97a912b71">how to create a Bauhaus Poster with HTML and CSS</a>. Now let us try to recreate a <a href="https://desenio.de/de/saturn-space-poster">Saturn</a> and <a href="https://desenio.de/de/earth-03-poster">Earth</a> planet poster from <a href="https://desenio.de/">DESENIO</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bNIPlBLrO6ylHJr5kx_prQ.png" /><figcaption>The Saturn Poster rendered with WeasyPrint</figcaption></figure><p>The HTML code is tiny. All we need is a div element for the circle and some elements for the black vertical lines. I decided to use 25 list elements for the lines.</p><pre>&lt;ul class=&quot;flex-container&quot;&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>  &lt;li class=&quot;flex-item&quot;&gt;&lt;/li&gt;<br>&lt;/ul&gt;<br>&lt;div class=&quot;circle&quot;&gt;&lt;/div&gt;</pre><p>The CSS code is equally easy. First, let’s decide on a font for the planet name and number in the footer. Then we define the page size, margin, and background color.</p><p>The name and number get added via the bottom left and right <a href="https://www.w3.org/TR/css-page-3/#margin-boxes">page margin boxes</a>.</p><pre>@import url(https://medium.com/&#39;https://fonts.googleapis.com/css2?family=Roboto:wght@900&amp;display=swap&#39;);<br>  <br>@page{<br>  size:30cm 40cm;<br>  background-color:rgb(233,227,213); <br>  margin:1cm 1cm 4cm 1cm;<br>  <br>  <br>  @bottom-left{<br>    content:&quot;06&quot;;<br>    font-size:64pt;<br>    font-weight:bold;<br>    font-family: &#39;Roboto&#39;, sans-serif;<br>  }<br>  <br>  @bottom-right{<br>    content:&quot;Saturn&quot;;<br>    text-transform:uppercase;<br>    font-size:64pt;<br>    font-weight:bold;<br>    font-family: &#39;Roboto&#39;, sans-serif;<br>  }<br>}</pre><p>Now all that’s left is designing the lines and the circle. The UL element gives a display property of flexbox and set justify-content to space between so the lines are equally distributed.</p><pre>.flex-container {<br>  padding: 0;<br>  margin: 0;<br>  list-style: none;<br>  display: flex;<br>  justify-content: space-between; <br>}</pre><p>The LI elements, so the lines themselves, get their background color and size.</p><pre>.flex-item {<br>  background:black;<br>  width:.5cm;<br>  height:34cm;<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/295/1*xQBX74_Im8-wF5WYP95cnw.png" /><figcaption>The Poster with the lines and footer text</figcaption></figure><p>In the circle, we position absolute in the center. Why do we position it 4 cm from the left? Because left and right, we have a page margin of 1 cm, and the circle should be 20 cm wide. So it is 30 cm (page width) — 2 cm (page margins) — 20 cm (circle width) = 8 cm / 2 (left and right).</p><pre>.circle{<br>  position:absolute;<br>  left:4cm;<br>  top:6cm;<br>  width:20cm;<br>  height:20cm;<br>  border-radius:100%;<br>  background-color:rgb(249,177,73);<br>}</pre><p>You can try the code directly on the <a href="https://printcss.live/JAPdRqbGyO">PrintCSS Playground</a> or view it on <a href="https://github.com/azettl/printcss.examples/tree/main/HTML%20Examples/Posters/Saturn%2006">GitHub</a>.</p><p>To change from Saturn to Earth, we need to change the footer text, number, and circle color.</p><pre>@bottom-left{<br>  content:&quot;03&quot;;<br>  font-size:64pt;<br>  font-weight:bold;<br>  font-family: &#39;Roboto&#39;, sans-serif;<br>}<br>  <br>@bottom-right{<br>  content:&quot;Earth&quot;;<br>  text-transform:uppercase;<br>  font-size:64pt;<br>  font-weight:bold;<br>  font-family: &#39;Roboto&#39;, sans-serif;<br>}</pre><p>The code for that is also available via <a href="https://github.com/azettl/printcss.examples/tree/main/HTML%20Examples/Posters/Earth%2003">Github</a> and <a href="https://printcss.live/Oy5eVMdEP4">printcss.live</a>. You can <a href="https://youtu.be/xFcu5gEkekk">watch me recreate both of the Posters on YouTube</a> too.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*87OBhqp0bC-ciTZo15EgnQ.png" /><figcaption>The Earth variant of the Poster</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f68e4c904fac" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/printcss-create-planet-posters-f68e4c904fac">PrintCSS: Create Planet Posters</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PrintCSS: Create a Bauhaus Poster with the help of HTML and CSS]]></title>
            <link>https://medium.com/printcss/printcss-create-a-bauhaus-poster-with-the-help-of-html-and-css-d4f97a912b71?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/d4f97a912b71</guid>
            <category><![CDATA[html2pdf]]></category>
            <category><![CDATA[poster-printing]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[bauhaus]]></category>
            <category><![CDATA[poster-design]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Wed, 24 Feb 2021 19:41:40 GMT</pubDate>
            <atom:updated>2021-02-24T19:41:39.958Z</atom:updated>
            <content:encoded><![CDATA[<p>In this article, you will learn how to recreate a Bauhaus Poster from <a href="https://desenio.de/">DESENIO</a> in HTML and CSS, the rendering of the result PDF will be done on <a href="https://printcss.live/">printcss.live</a>. If you prefer watching me how I recreated this poster, have a look at my <a href="https://youtu.be/xFcu5gEkekk">YouTube video</a> covering the same.</p><h3>Bauhaus 1923</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kMrVBuES6ghDlDaRmPwD6g.png" /><figcaption>Resulting PDF Rendered with WeasyPrint</figcaption></figure><p>If you look at the result above you, see that this poster will be relatively easy to recreate with CSS. All you need is a header, three circles in the center, placed on top of each other, and four smaller circles below.</p><p>The first thing to look at is the HTML structure. All you will need are two wrapper divs containing the div elements for the single circles.</p><pre>&lt;div class=&quot;wrapper&quot;&gt;<br>  &lt;div class=&quot;c1&quot;&gt;&lt;/div&gt;<br>  &lt;div class=&quot;c2&quot;&gt;&lt;/div&gt;<br>  &lt;div class=&quot;c3&quot;&gt;&lt;/div&gt;<br>&lt;/div&gt;<br>  <br>&lt;div class=&quot;foot_wrapper&quot;&gt;<br>  &lt;div&gt;&lt;div class=&quot;c1&quot;&gt;&lt;/div&gt;&lt;/div&gt;<br>  &lt;div&gt;&lt;div class=&quot;c2&quot;&gt;&lt;/div&gt;&lt;/div&gt;<br>  &lt;div&gt;&lt;div class=&quot;c3&quot;&gt;&lt;/div&gt;&lt;/div&gt;<br>  &lt;div&gt;&lt;div class=&quot;c4&quot;&gt;&lt;/div&gt;&lt;/div&gt;<br>&lt;/div&gt;</pre><p>The header will be directly set in the CSS code, so there is no need to create any HTML element.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/302/1*cPPe1FBBIzMkP4wzBm09Lg.png" /><figcaption>The result is an empty page with the background color and correct size.</figcaption></figure><p>Now in the CSS, let’s first concentrate on the header. As a font, I chose Catamaran, but you can take any other font too. Next, you should define the poster’s size, background color, and page margins. There will be a bigger margin on the top cause the header needs some space.</p><pre>@import url(https://medium.com/%E2%80%98https://fonts.googleapis.com/css2?family=Catamaran:wght@800;900&amp;display=swap&#39;);</pre><pre>@page{<br> size: 30cm 40cm;<br> background-color:rgb(243,244,239);<br> margin:4cm 2cm 2cm 2cm;<br>}</pre><p>You can add the text for the header in the top left and right page margin boxes. This code belongs inside the @page rule.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/1*0SNx33xdUcUn6ds1G0Ve2w.png" /><figcaption>The page header rendered with WeasyPrint</figcaption></figure><pre>@top-left{<br>  content:&quot;Bauhaus&quot;; <br>  font-family: &#39;Catamaran&#39;, sans-serif;<br>  font-size:48pt;<br>  font-weight:bold;<br>}</pre><pre>@top-right{<br>  content:&quot;1923&quot;;<br>  font-size:24pt;<br>  font-family: &#39;Catamaran&#39;, sans-serif;<br>  font-weight:bold;<br>}</pre><p>If you render the code now, you will see that only the border below the header and the circles are missing.</p><p>The border can be set directly on the body element as the <a href="https://www.w3.org/TR/css-page-3/#margin-boxes">page margin boxes</a> surround the body.</p><pre>body{<br>  border-top:8px solid black;<br>}</pre><p>Before you continue adding the circles, let us define their sizes. As the poster itself has a width of 30 cm and 2 cm of space on each side, the maximum for the outer circle will be 26 cm. This example’s inner circles are each 4 cm smaller than their parent, so 22 cm and 18 cm. For the footer, let us consider a circle size of 4 cm.</p><p>The wrapper for the big circles should also have 2 cm as the top margin, so the circles do not directly start at the body’s border. Additionally, the plan is to position the circles absolute, so you should make the wrapper relative.</p><pre>.wrapper{<br>  margin-top:2cm;<br>  position:relative;<br>}</pre><p>As you can see in the HTML structure above, the big and small circles share the same class names. This is done because they should get the same colors. Only the last small circle has another color, the black from the header. This means defining the background color and border-radius within the c1, c2, c3, and c4 classes and the position we define specific to the surrounding wrapper.</p><p>The CSS for the colors is:</p><pre>.c1{<br>  background-color:rgb(239,152,1);<br>  border-radius:100%;<br>}<br>.c2{<br>  background-color:rgb(235,89,36);<br>  border-radius:100%;<br>}<br>.c3{<br>  background-color:rgb(230,29,42);<br>  border-radius:100%;<br>}<br>.c4{<br>  background-color:black;<br>  border-radius:100%;<br>}</pre><p>Now let us give all the small circles in the footer wrapper their size of 4 cm by 4 cm and render the PDF again.</p><pre>.foot_wrapper .c1,<br>.foot_wrapper .c2,<br>.foot_wrapper .c3,<br>.foot_wrapper .c4{<br>  width:4cm;<br>  height:4cm;<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/296/1*NXSV9i1bLhpM8WaQPrGyEg.png" /><figcaption>The footer circles rendered with WeasyPrint</figcaption></figure><p>As you can see in the PDF screenshot, the circles are below each other and not in one line at the document’s bottom. We will take care of this after the positioning of the big circles.</p><p>The first or outer circle will get the 26 cm as size:</p><pre>.wrapper .c1{<br>  position:absolute;<br>  width:26cm;<br>  height:26cm;<br>}</pre><p>Circles two and three will get their respective size and move from top and left accordingly to fit in the middle of the outer circle.</p><pre>.wrapper .c2{<br>    position:absolute;<br>    top:2cm;<br>    left:2cm;<br>    width:22cm;<br>    height:22cm;<br>}</pre><pre>.wrapper .c3{<br>    position:absolute;<br>    top:4cm;<br>    left:4cm;<br>    width:18cm;<br>    height:18cm;<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/299/1*XTcK-jDxJ8MEwDLPUBNsFg.png" /><figcaption>The big circles added</figcaption></figure><p>The only thing left now is positioning the small circles in a row below the big circle. You can use a flexbox for this and use justify-content to spread the elements equally.</p><pre>.foot_wrapper{<br>  position:relative;<br>  top:28cm;<br>  display:flex;<br>  justify-content: space-between; <br> }</pre><p>The result of the above code will give you the desired PDF. You can directly open this code on the <a href="https://printcss.live/mWZdPwbKgR">PrintCSS playground</a> or view it on <a href="https://github.com/azettl/printcss.examples/tree/main/HTML%20Examples/Posters/Bauhaus%201923">Github</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kMrVBuES6ghDlDaRmPwD6g.png" /><figcaption>The final output.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d4f97a912b71" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/printcss-create-a-bauhaus-poster-with-the-help-of-html-and-css-d4f97a912b71">PrintCSS: Create a Bauhaus Poster with the help of HTML and CSS</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PrintCSS: Create your Certificate PDFs with HTML and CSS]]></title>
            <link>https://medium.com/printcss/printcss-create-your-certificate-pdfs-with-html-and-css-926e7dcf6281?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/926e7dcf6281</guid>
            <category><![CDATA[certificate]]></category>
            <category><![CDATA[website-design]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[html-to-pdf]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Fri, 05 Feb 2021 23:36:25 GMT</pubDate>
            <atom:updated>2021-02-05T23:37:46.202Z</atom:updated>
            <content:encoded><![CDATA[<p>We all know the Certification PDFs you get at many e-learning platforms. Maybe you even need to create one for your own online course or platform; then this article is for you.</p><p>As in all other articles, we will use <a href="https://printcss.live/">printcss.live</a> to create the PDF so that there is no need to install any rendering tool on your machine. Also below example is optimized and tested with <a href="https://weasyprint.org/">WeasyPrint</a>; nevertheless, it also works fine with most other rendering tools on the website.</p><p>The goal is a certificate PDF that looks like this article’s main image, which you see below.</p><figure><img alt="The result certificate PDF rendered with WeasyPrint." src="https://cdn-images-1.medium.com/max/1024/1*7ADj-If8IZUnFsHI7fCLeQ.png" /><figcaption>The result certificate PDF rendered with WeasyPrint.</figcaption></figure><p>Let us start with the HTML structure and then move to the CSS part. For the structure, we will need an area for the pattern which surrounds the content area. As there will be another border inside the pattern area, we will need another div inside the content, which I called ‘inner-content’ in this example. Inside this inner content element, we finally add the text itself, starting with the main heading ‘Certificate’. The sub-heading ‘of Excellence’ and additional information about the participant, course, and date follows the main title.</p><pre>&lt;div class=&quot;border-pattern&quot;&gt;<br> &lt;div class=&quot;content&quot;&gt;<br>  &lt;div class=&quot;inner-content&quot;&gt;<br>   &lt;h1&gt;Certificate&lt;/h1&gt;<br>   &lt;h2&gt;of Excellence&lt;/h2&gt;<br>   &lt;h3&gt;This Certificate Is Proudly Presented To&lt;/h3&gt;<br>   &lt;p&gt;Jane Doe&lt;/p&gt;<br>   &lt;h3&gt;Has Completed&lt;/h3&gt;<br>   &lt;p&gt;PrintCSS Basics Course&lt;/p&gt;<br>   &lt;h3&gt;On&lt;/h3&gt;<br>   &lt;p&gt;Feburary 5, 2021&lt;/p&gt;<br>   &lt;div class=&quot;badge&quot;&gt;<br>   &lt;/div&gt;<br>  &lt;/div&gt;<br> &lt;/div&gt;<br>&lt;/div&gt;</pre><p>Now let us have a look at the CSS code. First, we start with the page size A4 as landscape and the outer border.</p><pre>@page{<br> size:A4 landscape;<br> margin:10mm;<br>}</pre><pre>body{<br> margin:0;<br> padding:0;<br> border:1mm solid #991B1B;<br> height:188mm;<br>}</pre><figure><img alt="HTML and outer border set via CSS as rendered PDF." src="https://cdn-images-1.medium.com/max/734/1*FIQXl72VzoSBN7h3GIGz2g.png" /><figcaption>HTML and outer border set via CSS as rendered PDF.</figcaption></figure><p>We set the body element’s height to 188mm because the A4 page in landscape mode has a height of 210mm, from which we need to subtract the 10mm margin (top + bottom = 20mm) and the border 1mm (again top and bottom = 2mm).</p><p>As the outside border is ready, we can have a look at the pattern now. For the pattern, we will use one of the fantastic SVG patterns from <a href="https://www.heropatterns.com/">heropatterns.com</a>. At the beginning of the article, the result picture shows us that the pattern is above the outside border on the page’s top and bottom. On the left and right, the outer border is visible.</p><p>We position the pattern div absolute, move it in from the left by 4mm, and move it outside the body by setting the top to -6mm. The height and width need to consider the wanted element size. The width is 297mm (A4 size) minus 20mm page margin minus 2mm border from the pattern element minus 8mm from the left and right. The height is 210mm (A4 size) minus 20mm margin minus 2mm border from the pattern element plus 12mm as it should be bigger than the body. Lastly, we set the background color and background image, which is copied from the hero patterns.</p><pre>.border-pattern{<br> position:absolute;<br> left:4mm;<br> top:-6mm;<br> height:200mm;<br> width:267mm;<br> border:1mm solid #991B1B;<br> /* http://www.heropatterns.com/ */<br> background-color: #d6d6e4;<br> background-image: url(https://medium.com/&quot;data:image/svg+xml,%3Csvg%20width=&#39;16&#39;%20height=&#39;16&#39;%20viewBox=&#39;0%200%2016%2016&#39;%20xmlns=&#39;http://www.w3.org/2000/svg&#39;%3E%3Cpath%20d=&#39;M0%200h16v2h-6v6h6v8H8v-6H2v6H0V0zm4%204h2v2H4V4zm8%208h2v2h-2v-2zm-8%200h2v2H4v-2zm8-8h2v2h-2V4z&#39;%20fill=&#39;%23991B1B&#39;%20fill-opacity=&#39;1&#39;%20fill-rule=&#39;evenodd&#39;/%3E%3C/svg%3E&quot;);<br>}</pre><p>The result should look like this, depending on the pattern you choose.</p><figure><img alt="The current status with the hero pattern added to the document." src="https://cdn-images-1.medium.com/max/732/1*H6Xu2EuQQsPtAz1mTNzurw.png" /><figcaption>The current status with the hero pattern added to the document.</figcaption></figure><p>Now we will have to style the content element. Again this needs to be positioned absolute, and as the pattern is right now taking the whole space, this content element defines the size of the surrounding pattern.</p><p>For this example, let’s give the pattern a size of 10mm and close the pattern area with a border of 1mm. Considering the width of the pattern element 267mm, the content’s width would be 267mm minus 20mm (left and right) minus 2mm (for the border). The content’s height would be 200mm minus 20mm (top and bottom) minus 2mm (for the border). As we want to put our content inside this div element, we also set the background color to white.</p><pre>.content{<br> position:absolute;<br> left:10mm;<br> top:10mm;<br> height:178mm;<br> width:245mm;<br> border:1mm solid #991B1B;<br> background:white;<br>}</pre><p>If we render this now, we already see the basic layout of our certificate.</p><figure><img alt="Basic layout result PDF." src="https://cdn-images-1.medium.com/max/732/1*9ib2r04vT5Ayqg7Wb7FfNQ.png" /><figcaption>Basic layout result PDF.</figcaption></figure><p>But if you look at the result image again, there is another border before we can start with the actual content, and that’s why we have the inner content element. Here we set another 1mm border and a 4mm margin to have some white space between the border and the pattern area. For the content itself, we place a padding of 10mm, and as we want the element to take the entire space, we set the height. The height of 148mm is the 178mm (of the content element) - 20mm (padding-top and bottom) - 8mm (margin-top and bottom) - 2mm (border-top and bottom).</p><pre>.inner-content{<br> border:1mm solid #991B1B;<br> margin:4mm;<br> padding:10mm;<br> height:148mm;<br> text-align:center;<br>}</pre><figure><img alt="Last border and basic positioning of the text seen in the result PDF." src="https://cdn-images-1.medium.com/max/735/1*wKegWCrIl0XCn4M7AWqvKA.png" /><figcaption>Last border and basic positioning of the text seen in the result PDF.</figcaption></figure><p>So now all the fancy content surrounding is done.</p><p>The main header is all uppercase, so we use ‘<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform">text-transform</a>’ to achieve this. Additionally, we change the font size and set the margin-bottom to zero, so the subtitle is closer to the header.</p><p>The subtitle gets a padding-bottom of 1mm to keep some space between the text and the border underline below. We use a pseudo-element for the subtitle to add a second underline, again via the border-bottom property.</p><p>The section titles in our example are done with the H3 element and have just some margin adjustments.</p><pre>h1{<br> text-transform:uppercase;<br> font-size:48pt;<br> margin-bottom:0;<br>}</pre><pre>h2{<br> font-size:24pt;<br> margin-top:0;<br> padding-bottom:1mm;<br> display:inline-block;<br> border-bottom:1mm solid #991B1B;<br>}</pre><pre>h2::after{<br> content:&quot;&quot;;<br> display:block;<br> padding-bottom:4mm;<br> border-bottom:1mm solid #991B1B;<br>}</pre><pre>h3{<br> font-size:20pt;<br> margin-bottom:0;<br> margin-top:10mm;<br>}</pre><pre>p{<br> font-size:16pt;<br>}</pre><figure><img alt="Result PDF with styled text and double underline under the subtitle." src="https://cdn-images-1.medium.com/max/732/1*K95Q_eqenlG3qaoMwtugQw.png" /><figcaption>Result PDF with styled text and double underline under the subtitle.</figcaption></figure><p>So what is missing? The badge! Let’s take a badge icon from <a href="https://heroicons.com/">heroicons.com</a> and use a <a href="https://yoksel.github.io/url-encoder/">URL-encoder for SVG</a> to generate the background image code. The badge size should be 40mm by 40mm, and we position it in the right bottom corner.</p><pre>.badge{<br> width:40mm;<br> height:40mm;<br> position:absolute;<br> right:10mm;<br> bottom:10mm;<br> background-image:url(https://medium.com/&quot;data:image/svg+xml,%3Csvg%20xmlns=&#39;http://www.w3.org/2000/svg&#39;%20fill=&#39;none&#39;%20viewBox=&#39;0%200%2024%2024&#39;%20stroke=&#39;currentColor&#39;%3E%3Cpath%20stroke-linecap=&#39;round&#39;%20stroke-linejoin=&#39;round&#39;%20stroke-width=&#39;2&#39;%20d=&#39;M9%2012l2%202%204-4M7.835%204.697a3.42%203.42%200%20001.946-.806%203.42%203.42%200%20014.438%200%203.42%203.42%200%20001.946.806%203.42%203.42%200%20013.138%203.138%203.42%203.42%200%2000.806%201.946%203.42%203.42%200%20010%204.438%203.42%203.42%200%2000-.806%201.946%203.42%203.42%200%2001-3.138%203.138%203.42%203.42%200%2000-1.946.806%203.42%203.42%200%2001-4.438%200%203.42%203.42%200%2000-1.946-.806%203.42%203.42%200%2001-3.138-3.138%203.42%203.42%200%2000-.806-1.946%203.42%203.42%200%20010-4.438%203.42%203.42%200%2000.806-1.946%203.42%203.42%200%20013.138-3.138z&#39;%20/%3E%3C/svg%3E&quot;);<br>}</pre><p>We render the PDF one last time and have our final result! If you want to get the complete code, have a look in my <a href="https://github.com/azettl/printcss.examples/tree/main/HTML%20Examples/Certificate">GitHub repository</a> or directly check it out on <a href="https://printcss.live/l4zbq2dprO">printcss.live</a>!</p><figure><img alt="The final certificate PDF made with HTML &amp; CSS and rendered with WeasyPrint." src="https://cdn-images-1.medium.com/max/731/1*KqnbQFRYqhBWJV2Fu-IqSA.png" /><figcaption>The final certificate PDF made with HTML &amp; CSS and rendered with WeasyPrint.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=926e7dcf6281" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/printcss-create-your-certificate-pdfs-with-html-and-css-926e7dcf6281">PrintCSS: Create your Certificate PDFs with HTML and CSS</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PrintCSS: How to create a Poker Card]]></title>
            <link>https://medium.com/printcss/printcss-how-to-create-a-poker-card-a6c7b3ae34dc?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/a6c7b3ae34dc</guid>
            <category><![CDATA[html2pdf]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[web-to-print]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[poker]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Sun, 31 Jan 2021 22:07:16 GMT</pubDate>
            <atom:updated>2021-10-25T22:22:05.620Z</atom:updated>
            <content:encoded><![CDATA[<p>There are many different things you can do with the help of <a href="https://www.w3.org/TR/css-page-3/">CSS Paged Media</a>. I already covered some use cases in this <a href="https://medium.com/printcss">publication</a>, like <a href="https://medium.com/printcss/printcss-create-a-business-card-pdf-with-html-and-css-846f203597a8">business cards</a>, <a href="https://medium.com/printcss/printcss-recreating-a-ebook-cover-a7941fa0c619">book covers</a>, and <a href="https://medium.com/printcss/printcss-a-basic-cv-example-abb3b39c4aba">CVs</a>. Today I want to show you how to create beautiful poker cards. We will design one standard card and a joker card together. All other cards you can make with the same HTML and CSS by just changing the values.</p><h3>Ace of Spades</h3><p>Let us start with the ace of spades. As HTML, we create two divs for the front and backside. This will be two pages in the result PDF. Both wrapper divs for the pages contain another div with the actual page content. In the front side div, we directly add the content ‘♠’, the back side div will get a lovely pattern from <a href="http://www.heropatterns.com/">Hero Patterns</a>, so all we need in HTML is the empty container.</p><pre>&lt;div class=&quot;front&quot;&gt;<br>   &lt;div class=&quot;content&quot;&gt;♠&lt;/div&gt;<br>&lt;/div&gt; <br>&lt;div class=&quot;back&quot;&gt;<br>   &lt;div class=&quot;design&quot;&gt;&lt;/div&gt;<br>&lt;/div&gt;</pre><p>Now to the more exciting part, the CSS. There are many different sizes for playing cards. In this sample, we will go with 63.5mm x 88.8mm.</p><p>To do so in CSS, we need to use the <a href="https://www.w3.org/TR/css-page-3/#at-page-rule">@page rule</a> and define the size. Additionally, I will also define a <a href="https://www.w3.org/TR/css-page-3/#bleed">bleed</a>, <a href="https://www.w3.org/TR/css-page-3/#marks">crop marks</a>, and margin for the pages. For the HTML body, let us also set padding and margin to zero.</p><pre>@page{<br> size:63.5mm 88.8mm;<br> marks:crop;<br> bleed:5mm;<br> margin:5mm;<br>}</pre><pre>body{<br> padding:0;<br> margin:0;<br>}</pre><p>I will use <a href="https://weasyprint.org/">WeasyPrint</a> on <a href="https://printcss.live/">printcss.live</a> to render the PDF, and if you check the result, we get only one page. So the next thing we need to do is put the front and back div on separate pages by using the <a href="https://www.w3.org/TR/css-page-3/#using-named-pages">named pages</a>.</p><figure><img alt="The current HTML and CSS Code rendered with WeasyPrint on printcss.live" src="https://cdn-images-1.medium.com/max/366/1*NaJ48-JQsje_02z3mBwNzQ.png" /><figcaption>The current HTML and CSS Code rendered with WeasyPrint on printcss.live</figcaption></figure><pre>.front{<br> page: front;<br>}</pre><pre>.back{<br> page: back;<br>}</pre><p>This way, we defined a named page “front” for the div with the class “front” and an own page for the div with the class “back” too.</p><p>If we render the PDF again, we will now see two pages.</p><figure><img alt="2 Pages, thanks to the named pages CSS property." src="https://cdn-images-1.medium.com/max/734/1*iRfLAQQBwWjRQ-Agmv2cPg.png" /><figcaption>2 Pages, thanks to the named pages CSS property.</figcaption></figure><p>Next, let us focus on the pattern on the backside. As mentioned above, I want to use some nice <a href="http://www.heropatterns.com/">Hero Pattern</a> for this. The pattern we will surround by a border to get the typical playing card look.</p><pre>.design{<br> border:1mm solid rgb(188, 11, 6);<br> width:51.5mm;<br> height:76.8mm;<br> background-color: #fdb9b8;<br> background-image: url(https://medium.com/&quot;data:image/svg+xml,%3Csvg%20xmlns=&#39;http://www.w3.org/2000/svg&#39;%20width=&#39;52&#39;%20height=&#39;52&#39;%20viewBox=&#39;0%200%2052%2052&#39;%3E%3Cpath%20fill=&#39;%23bc0b06&#39;%20fill-opacity=&#39;0.97&#39;%20d=&#39;M0%2017.83V0h17.83a3%203%200%200%201-5.66%202H5.9A5%205%200%200%201%202%205.9v6.27a3%203%200%200%201-2%205.66zm0%2018.34a3%203%200%200%201%202%205.66v6.27A5%205%200%200%201%205.9%2052h6.27a3%203%200%200%201%205.66%200H0V36.17zM36.17%2052a3%203%200%200%201%205.66%200h6.27a5%205%200%200%201%203.9-3.9v-6.27a3%203%200%200%201%200-5.66V52H36.17zM0%2031.93v-9.78a5%205%200%200%201%203.8.72l4.43-4.43a3%203%200%201%201%201.42%201.41L5.2%2024.28a5%205%200%200%201%200%205.52l4.44%204.43a3%203%200%201%201-1.42%201.42L3.8%2031.2a5%205%200%200%201-3.8.72zm52-14.1a3%203%200%200%201%200-5.66V5.9A5%205%200%200%201%2048.1%202h-6.27a3%203%200%200%201-5.66-2H52v17.83zm0%2014.1a4.97%204.97%200%200%201-1.72-.72l-4.43%204.44a3%203%200%201%201-1.41-1.42l4.43-4.43a5%205%200%200%201%200-5.52l-4.43-4.43a3%203%200%201%201%201.41-1.41l4.43%204.43c.53-.35%201.12-.6%201.72-.72v9.78zM22.15%200h9.78a5%205%200%200%201-.72%203.8l4.44%204.43a3%203%200%201%201-1.42%201.42L29.8%205.2a5%205%200%200%201-5.52%200l-4.43%204.44a3%203%200%201%201-1.41-1.42l4.43-4.43a5%205%200%200%201-.72-3.8zm0%2052c.13-.6.37-1.19.72-1.72l-4.43-4.43a3%203%200%201%201%201.41-1.41l4.43%204.43a5%205%200%200%201%205.52%200l4.43-4.43a3%203%200%201%201%201.42%201.41l-4.44%204.43c.36.53.6%201.12.72%201.72h-9.78zm9.75-24a5%205%200%200%201-3.9%203.9v6.27a3%203%200%201%201-2%200V31.9a5%205%200%200%201-3.9-3.9h-6.27a3%203%200%201%201%200-2h6.27a5%205%200%200%201%203.9-3.9v-6.27a3%203%200%201%201%202%200v6.27a5%205%200%200%201%203.9%203.9h6.27a3%203%200%201%201%200%202H31.9z&#39;%3E%3C/path%3E%3C/svg%3E&quot;);<br>}</pre><p>You may ask yourself now why 51.5mm width and 76.8mm height if the card dimensions are 63.5mm x 88.8mm.</p><p>First, we set a margin of 5mm in the <a href="https://www.w3.org/TR/css-page-3/#at-page-rule">@page rule</a> so the card will have white space around the pattern. Also, as you see in the code above, the border around the pattern is 1mm. So the width would be 63.5mm - (5mm * 2) - (1mm *2), which results in 51.5mm. The same calculation for the height leaves us with 76.8mm for the back side pattern.</p><figure><img alt="The complete back side of the poker card, rendered with WeasyPrint." src="https://cdn-images-1.medium.com/max/734/1*dy0ac5hPZKut6ZRLJ_O4BA.png" /><figcaption>The complete back side of the poker card, rendered with WeasyPrint.</figcaption></figure><p>Next, let’s look at the front side, we need to have the ♠ in the center. Also, if you look at other playing cards, they have the A for the ace of spades and the ♠ symbol on the top left corner and on the bottom right corner rotated by 180 degree.</p><p>To add these elements, we can make use of the <a href="https://www.w3.org/TR/css-page-3/#margin-boxes">page margin boxes</a>. We will use ‘<a href="https://www.w3.org/TR/css-page-3/#at-ruledef-top-left-corner">@top-left-corner</a>’ for the ‘A’ and ‘<a href="https://www.w3.org/TR/css-page-3/#at-ruledef-left-top">@left-top</a>’ ♠ for the top left corner. Similar to the right bottom corner, here we use ‘<a href="https://www.w3.org/TR/css-page-3/#at-ruledef-bottom-right-corner">@bottom-right-corner</a>’ and ‘<a href="https://www.w3.org/TR/css-page-3/#at-ruledef-right-top">@right-top</a>’.</p><p>To fit all of that information in the <a href="https://www.w3.org/TR/css-page-3/#margin-boxes">page margin boxes</a>, we need to increase their size. In the <a href="https://www.w3.org/TR/css-page-3/#at-page-rule">@page rule</a>, we defined a margin of 5mm so the boxes have a width of 5mm, which will be too small for our content. Gladly we already defined a <a href="https://www.w3.org/TR/css-page-3/#using-named-pages">named page</a> for the front div. This <a href="https://www.w3.org/TR/css-page-3/#using-named-pages">named page</a> will get its own margin now.</p><pre>@page front{<br> margin:15mm;<br>}</pre><p>But that also means that the div with the class ‘content’ needs to be smaller than the back side pattern. The calculation for its size is the same as the one above, just that we have a 15mm instead of 5mm margin now.</p><p>The content ♠ should be centered, so let’s use the div height as line-height and set the CSS property ‘text-align’ to ‘center’.</p><pre>.content{<br> border:1mm solid rgb(188, 11, 6);<br> color:rgb(188, 11, 6);<br> width:31.5mm;<br> height:56.8mm;<br> line-height:56.8mm;<br> text-align:center;<br> font-size:96pt;<br>}</pre><figure><img alt="The result of the current HTML and CSS for the front and back side." src="https://cdn-images-1.medium.com/max/734/1*J7AZU_7mbRITkbPh03PLMQ.png" /><figcaption>The result of the current HTML and CSS for the front and back side.</figcaption></figure><p>As the last step, the <a href="https://www.w3.org/TR/css-page-3/#margin-boxes">page margin boxes</a> are remaining. Let us start with the top left corner of the card. Within the ‘@page front{}’ definition, you should add the following CSS code.</p><pre>color:rgb(188, 11, 6);</pre><pre>@top-left-corner{<br> line-height:15mm;<br> text-align:center;<br> font-size:36pt;<br> content:&quot;A&quot;;<br>}</pre><pre>@left-top{<br> line-height:15mm;<br> text-align:center;<br> font-size:36pt;<br> content:&quot;♠&quot;;<br>}</pre><p>Both boxes get a line-height of 15mm, the text gets aligned in the center. The ‘A’ and ‘♠’ get the font-size 36pt. Also, the content is set directly via CSS.</p><figure><img alt="Result with the top left margin boxes filled." src="https://cdn-images-1.medium.com/max/732/1*V6kFjGRE1xqx2poopEntTw.png" /><figcaption>Result with the top left margin boxes filled.</figcaption></figure><p>The same code is used for the bottom right card corner, too, just that we need to rotate the boxes by 180 degree.</p><pre>@bottom-right-corner{<br> line-height:15mm;<br> text-align:center;<br> font-size:36pt;<br> content:&quot;A&quot;;<br> transform:rotate(180deg);<br>}</pre><pre>@right-top{<br> line-height:15mm;<br> text-align:center;<br> font-size:36pt;<br> content:&quot;♠&quot;;<br> transform:rotate(180deg);<br>}</pre><p>Now you should get a PDF with two pages looking like the following image.</p><figure><img alt="PDF result with all needed margin boxes filled and styled." src="https://cdn-images-1.medium.com/max/731/1*FoWoNnAu1XQbnyBZ1WnuuQ.png" /><figcaption>PDF result with all needed margin boxes filled and styled.</figcaption></figure><p>The full code for the ace of spades card is also available in my <a href="https://github.com/azettl/printcss.examples/tree/main/HTML%20Examples/Playing%20Cards/Poker">PrintCSS GitHub repository</a>.</p><h3>Joker</h3><p>The HTML code for the joker card is 99 percent the same, just the content is different. I chose the 😼 symbol for the joker card.</p><pre>&lt;div class=&quot;front&quot;&gt;<br>   &lt;div class=&quot;content&quot;&gt;😼&lt;/div&gt;<br>&lt;/div&gt; <br>&lt;div class=&quot;back&quot;&gt;<br>   &lt;div class=&quot;design&quot;&gt;&lt;/div&gt;<br>&lt;/div&gt;</pre><p>The back side CSS is also the same as for all cards, so the same <a href="http://www.heropatterns.com/">Hero Pattern</a>. We do not need the border for the front side, and, as the symbol is bigger, we need to adjust the font size. As the border of 1mm is missing, the width and height are both 2mm larger.</p><pre>.content{<br> color:rgb(188, 11, 6);<br> width:33.5mm;<br> height:58.8mm;<br> line-height:56.8mm;<br> text-align:center;<br> font-size:72pt;<br>}</pre><figure><img alt="Current result of the joker card with the page margin boxes still filled with the ace of spades content." src="https://cdn-images-1.medium.com/max/735/1*0zaNacMDejI4Voo8ljFXYQ.png" /><figcaption>Current result of the joker card with the page margin boxes still filled with the ace of spades content.</figcaption></figure><p>In the <a href="https://www.w3.org/TR/css-page-3/#margin-boxes">page margin boxes</a>, instead of putting the numbers 2–10, the face cards J, Q, K, or A for the ace plus the symbol of hearts, diamonds, spades, or clubs, we just write ‘Joker’.</p><p>As the page margin will still be 15mm, each letter of ‘Joker’ should be in a single line. To do so, the CSS for the boxes needs to be adjusted too.</p><pre>@left-middle{<br> line-height:1;<br> text-align:center;<br> font-size:26pt;<br> overflow-wrap: break-word;<br> text-transform: uppercase;<br> content:&quot;Joker&quot;;<br> letter-spacing:1em;<br> margin:2mm;<br>}</pre><pre>@right-middle{<br> line-height:1;<br> text-align:center;<br> font-size:26pt;<br> overflow-wrap: break-word;<br> text-transform: uppercase;<br> content:&quot;Joker&quot;;<br> letter-spacing:1em;<br> transform:rotate(180deg);<br> margin:2mm;<br>}</pre><figure><img alt="The complete Joker card." src="https://cdn-images-1.medium.com/max/733/1*ydCOOS3jDz4VcrrG53ndhA.png" /><figcaption>The complete Joker card.</figcaption></figure><p>Again the full code and result PDF is available in my <a href="https://github.com/azettl/printcss.examples/tree/main/HTML%20Examples/Playing%20Cards/Joker">GitHub repository</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6c7b3ae34dc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/printcss-how-to-create-a-poker-card-a6c7b3ae34dc">PrintCSS: How to create a Poker Card</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PrintCSS: Widows and Orphans]]></title>
            <link>https://medium.com/printcss/printcss-widows-and-orphans-d68a2dd74f7d?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/d68a2dd74f7d</guid>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[web-to-print]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[web-design]]></category>
            <category><![CDATA[html-to-pdf]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Thu, 28 Jan 2021 20:02:25 GMT</pubDate>
            <atom:updated>2021-01-28T20:02:25.494Z</atom:updated>
            <content:encoded><![CDATA[<p>There is the concept of widows and orphans in typography, which describes the line of a paragraph that appears alone. A Orphan is the first line of a paragraph that appears at the bottom of a page. On the other hand, a widow is the last line of a paragraph appearing on the top of a page.</p><figure><img alt="Sample of a widow, rendered with DocRaptor." src="https://cdn-images-1.medium.com/max/525/1*LzJH46ca68sb5nMb13tSfA.png" /></figure><p>Usually, you do not want a single line of a paragraph to be alone on the bottom or top of a page.</p><p>There are the CSS properties ‘<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/widows">widows</a>’ and ‘<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/orphans">orphans</a>’ to take care of such’ lonely’ lines. The integer you are passing as a value to these properties defines the minimum number of lines that can be alone.</p><p>Let’s start with a basic HTML and CSS file and see the result on <a href="https://printcss.live/">printcss.live</a> with <a href="https://docraptor.com/">DocRaptor</a> as the selected rendering tool. Of course, you can render the PDF with the other tools too, but be aware that not all rendering tools support this concept yet.</p><h4>HTML</h4><pre>&lt;div class=&quot;headerLeft&quot;&gt;<br> PrintCSS: Widows and Orphans<br>&lt;/div&gt;<br>&lt;div class=&quot;headerRight&quot;&gt;<br>   A sample document<br>&lt;/div&gt;</pre><pre>&lt;div class=&quot;footerLeft&quot;&gt;<br>   &lt;img src=&quot;<a href="https://printcss.live/img/logo.png">https://printcss.live/img/logo.png</a>&quot; /&gt;<br>&lt;/div&gt;<br>&lt;div class=&quot;footerRight&quot;&gt;<br>    &lt;a href=&quot;<a href="/service/mailto:info@azettl.net">info@azettl.net</a>&quot;&gt;<a href="/service/mailto:info@azettl.net">info@azettl.net</a>&lt;/a&gt;&lt;br /&gt;<br>    &lt;a href=&quot;<a href="https://printcss.live/">https://printcss.live/</a>&quot;&gt;printcss.live&lt;/a&gt;<br>&lt;/div&gt;</pre><pre>&lt;h1&gt;PrintCSS: Widows and Orphans&lt;/h1&gt;<br>&lt;p&gt;There is the concept of widows and orphans in typography, which describes lines of a paragraph that appear alone.&lt;/p&gt;<br>&lt;p&gt;Orphans are the first lines of a paragraph that appear at the bottom of a page. On the other hand, widows are the last lines of a paragraph appearing on the top of a page.&lt;/p&gt;<br>&lt;p&gt;Usually, you do not want a single line of a paragraph to be alone on the bottom or top of a page.&lt;/p&gt;<br>&lt;p&gt;There are the CSS properties &#39;widow&#39; and &#39;orphan&#39; to take care of such&#39; lonely&#39; lines. The integer you are passing as a value to these properties defines the minimum number of lines that can be alone.&lt;/p&gt;<br>&lt;p&gt;Let&#39;s start with a basic HTML and CSS file and see the result on printcss.live with DocRaptor as the selected rendering tool. Of course, you can render the PDF with the other tools too, but be aware that not all rendering tools support this concept yet.&lt;/p&gt;</pre><h4>CSS</h4><pre>@page  {<br>    size: A6;<br>    margin: 20mm;</pre><pre>    @top-left{<br>        content: element(headerLeft);<br>        border-bottom:2px solid #434190;<br>    }</pre><pre>    @top-center{<br>        border-bottom:2px solid #434190;<br>    }</pre><pre>    @top-right{<br>        content: element(headerRight);<br>        border-bottom:2px solid #434190;<br>    }</pre><pre>    @bottom-right {<br>        content: element(footerRight);<br>        border-top:2px solid #434190;<br>    }</pre><pre>    @bottom-center{<br>        content: counter(page) &#39; / &#39; counter(pages);<br>        border-top:2px solid #434190;<br>        font-size:8pt;<br>    }</pre><pre>    @bottom-left{<br>        content: element(footerLeft);<br>        border-top:2px solid #434190;<br>    }<br>}</pre><pre>.headerLeft{<br>    position: running(headerLeft);<br>    font-size:12pt;<br>}</pre><pre>.headerRight{<br>    position: running(headerRight);<br>    font-size:8pt;<br>    font-style: italic;<br>    text-align: right;<br>    color:#667eea;<br>}</pre><pre>.footerLeft{<br>    position: running(footerLeft);<br>}</pre><pre>.footerLeft img{<br>    width:20mm;<br>}</pre><pre>.footerRight{<br>    position: running(footerRight);<br>    text-align: right;<br>    font-size:8pt;<br>}</pre><p>To avoid the widow we see in the screenshot above, you can extend the CSS with the following paragraphs’ style.</p><pre>p{<br>   widows:3;<br>}</pre><p>You can see that all three lines are on the second page now as we defined a minimum of three lines as widows.</p><figure><img alt="CSS property widows rendered with DocRaptor" src="https://cdn-images-1.medium.com/max/517/1*tlhgSuRT7iWHA5vstsZTcA.png" /></figure><p>If you change the properties value to two now you will see that only one line gets moved to the next page and that we actually get an orphan on the first page.</p><pre>p{<br>   widows:2;<br>}</pre><figure><img alt="Sample of an orphan, rendered with DocRaptor" src="https://cdn-images-1.medium.com/max/528/1*M7ZstrTTSBmvTQBuP_X_fg.png" /></figure><p>If you now want neither a single line of a paragraph on the bottom or top of the page, you can define both properties.</p><pre>p{<br>    orphans:2;<br>    widows:2;<br>}</pre><figure><img alt="Widows and Orphans CSS properties set at the same time, PDF sample rendered with DocRaptor" src="https://cdn-images-1.medium.com/max/511/1*JN6XMOvTYaqDZu3BSiRl8w.png" /></figure><p>The complete code and result PDF is also available in <a href="https://github.com/azettl/printcss.examples/tree/main/PrintCSS%20Features/Widows%20and%20Orphans">my GitHub repository</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d68a2dd74f7d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/printcss-widows-and-orphans-d68a2dd74f7d">PrintCSS: Widows and Orphans</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PrintCSS: A basic CV example]]></title>
            <link>https://medium.com/printcss/printcss-a-basic-cv-example-abb3b39c4aba?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/abb3b39c4aba</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[html-to-pdf]]></category>
            <category><![CDATA[cv]]></category>
            <category><![CDATA[web-to-print]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Tue, 05 Jan 2021 16:32:30 GMT</pubDate>
            <atom:updated>2021-01-05T16:32:30.112Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="CV Sample PDF, Skills Section" src="https://cdn-images-1.medium.com/max/805/1*lmTUf2ExR2NNC3FwL5McNA.png" /><figcaption>PDF CV example, Skills section</figcaption></figure><p>In this article you will learn how to create your own CV PDF with HTML, CSS. To render the actual PDF we will use <a href="https://www.pagedjs.org/">PagedJS</a> an open-source tool to create PDF documents from HTML.</p><p>Before we start with the CV, let us think about the structure we want. So in this example we will create a multi-page CV and on each of the pages we will have our main details in a header section.</p><p>After the header there will be a short section for a introduction text. Then following a section for the employment history, the education and further skills.</p><p>For all sections there will be sub-sections for the different jobs or achievements. On the left side we will put the dates and right the content so what we actually did in that time period.</p><h3>The header section</h3><figure><img alt="Header Section Sample" src="https://cdn-images-1.medium.com/max/805/1*IrAvyR1MLRyFlXbZpGzH_g.png" /><figcaption>Header Section Sample</figcaption></figure><p>For the header let us first define the HTML structure. Our heading will be the first and last name in an H1 element. Next we want to put some links to important websites, like our LinkedIn or GitHub Profile. That these links look nice you can include <a href="https://fontawesome.com/">FontAwesome</a> and add a small icon in front of every link. Last we should put more information about ourselves, like the birthdate, phone number and address.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b25dacda283987f0893b80fdcca97739/href">https://medium.com/media/b25dacda283987f0893b80fdcca97739/href</a></iframe><h3>The profile section</h3><p>The profile section or introduction text will be our first section. Here we already define the split of left and right content in the sub-sections. We will use the same code in all following sections. Let’s put the sections title in an H2 element and for the left/right sub-sections we will use a flex layout. To do so you need to set the display property of the element to ‘flex’. The left element should have a minimum width and the right element will take the rest of the space.</p><p>As the right element has paragraphs or further headlines (H3 elements) inside you should set their margin top to 0. This way they start at the same level as the left sides content.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c5706b753f99e6a0d9b16a775515f848/href">https://medium.com/media/c5706b753f99e6a0d9b16a775515f848/href</a></iframe><h3>The other sections</h3><p>All other sections in your CV document will have the same HTML structure and CSS styling. Have a look at the complete sample below to see how these sections are added.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a6f31ced5edf41d9511f90079c02d8a1/href">https://medium.com/media/a6f31ced5edf41d9511f90079c02d8a1/href</a></iframe><p>You can see the complete sample including the <a href="https://github.com/azettl/printcss.examples/blob/main/HTML%20Examples/CVs/Basic/result.pdf">resulting PDF document</a> on <a href="https://github.com/azettl/printcss.examples">my GitHub repository</a> for print CSS samples.</p><p>If you want to try recreating this CV or create your own one you can use <a href="https://printcss.live/">printcss.live</a> to render your PDF. This will save you the time of installing one of the rendering tools on your own dev environment.</p><p>If you want a more detailed explanation of the above sample check the <a href="https://youtu.be/EHRw_cOSs00">Video about the same on YouTube</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=abb3b39c4aba" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/printcss-a-basic-cv-example-abb3b39c4aba">PrintCSS: A basic CV example</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PrintCSS Video: Counter and Cross References]]></title>
            <link>https://medium.com/printcss/printcss-video-counter-and-cross-references-ea6a15fd1aea?source=rss----25c26773acba---4</link>
            <guid isPermaLink="false">https://medium.com/p/ea6a15fd1aea</guid>
            <category><![CDATA[cross-reference]]></category>
            <category><![CDATA[counter]]></category>
            <category><![CDATA[youtube]]></category>
            <category><![CDATA[printcss]]></category>
            <category><![CDATA[css-paged-media]]></category>
            <dc:creator><![CDATA[Andreas Zettl]]></dc:creator>
            <pubDate>Sat, 31 Oct 2020 14:57:49 GMT</pubDate>
            <atom:updated>2020-10-31T14:57:49.455Z</atom:updated>
            <content:encoded><![CDATA[<iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fxk5lgnE1HS8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dxk5lgnE1HS8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fxk5lgnE1HS8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/54a808191d6491286b135924edce6e8c/href">https://medium.com/media/54a808191d6491286b135924edce6e8c/href</a></iframe><p>You will learn how to use counters and nested counters in Print CSS and cross-reference via the target-counter(s) function.</p><p>In the end, I shortly show you <a href="https://www.myscreenbreak.com/">https://www.myscreenbreak.com</a> with which you can convert any news article to a nice PDF.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ea6a15fd1aea" width="1" height="1" alt=""><hr><p><a href="https://medium.com/printcss/printcss-video-counter-and-cross-references-ea6a15fd1aea">PrintCSS Video: Counter and Cross References</a> was originally published in <a href="https://medium.com/printcss">PrintCSS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>