evolved.io logotype

#React #CV #Resume #Print #CSS

Create a Resume with React and tailwindcss

There is no better way to create a pixel perfect, consistent and versioned print document programmatically.

Avatar
Dennis GaidelJuly 11, 2022

During my time as a consultant, I often had to adapt my CV to the role to be filled in the client's company.

My consultancy provided a Word template with a beautiful layout that constantly got into my way: Inexplicable spaces, design elements that suddenly shifted without any identifiable reason and other appalling challenges that cost time to correct.

React and CSS

A resume is usually a one or two page long document that describes a person's professional history, their education and qualifications.

When it comes to formatting, Google lists the following basics:

  • Simple and consistent design, font, sizing, and spacing
  • Use of black or dark, readable ink
  • Exported as a PDF

Consistency can easily be achieved with reusable components that are all based on the same styling rule-set. Instead of copy-pasting the same paragraphs, React components can separate content and design and even apply conditional logic based on the input.

The resume can also be easily localized to export it to different languages / target different markets (e.g. international vs. domestic).

CSS on the other hand provides full control of styling the printable page and its components. It's the technology every frontend/fullstack developer is familiar with and therefore significantly flattens the learning curve.

A small Create React App project comes with automatic previews / live reload out of the box, so that every change is presented immediately.

In the end the resume can be exported to PDF by printing to PDF in the browser.

@media print

CSS provides a media query to adjust the style when printing a document:

@media print {
    ...
}

This is the recommended way to remove elements from a central code block that should be removed for printing such as a navigation bar, paddings, margins and other stylings.

@page

@page modifies some page specific CSS rules (margin, size, page orientation, ...) and supports pseudo classes, such as :first to only target the first page.

It's very limited and not fully supported though (see MDN):

You can't change all CSS properties with @page. You can only change the margins, orphans, widows, and page breaks of the document. Attempts to change any other CSS properties will be ignored.

The following CSS code sets the page size to the normed DINA4 and removes all margins and padding per page. This is different from using a @media print query, which applies to the whole document, potentially spanning across multiple pages:

@page {
    size: A4;
    margin: 0 0 0 0;
    padding: 0 0 0 0;
}

Example

The actual React app displays a single page that is exactly the size of a standardized DINA4 page. It serves as a live preview of what the printed page would look like.

Resume in HTML

There are some elements that are repeated several times on this page, such as each element under "Education", "Experience" as well as each element under "Contacts" or even the icons in the "Tech Stack" category.

Education Component

For example, an "Education" component is defined as follows:

<Education
    school="Lorem University"
    degree="Master of Science (M.Sc.)"
    major="Computer Science"
    timeframe="Oct 2013 &#8212; Sep 2015"
/>

It abstracts all the boilerplate code required to design the section, allowing you to focus on the data / information that needs to be presented.

(Side note: In this case I avoided handling date props by passing the timeframe as a simple string. A date prop would provide more programmatic control though.)

In the end, the implementation for the component could look something like this:

const Education: FC<{
    school: string
    degree?: string
    major?: string
    timeframe?: string
}> = ({ school, degree, major, timeframe }) => (
    <div>
        <Head4>{school}</Head4>
        {degree || major || timeframe ? (
            <div className="mt-0.5">
                {degree ? (
                    <span className="block text-sm">{degree}</span>
                ) : null}
                {major ? <span className="block text-sm">{major}</span> : null}
                {timeframe ? (
                    <span className="block text-sm text-gray-600">
                        {timeframe}
                    </span>
                ) : null}
            </div>
        ) : null}
    </div>
)

The className props only need to be changed once in order to consistently change the styling across all "Education" items.

Once the print preview is open in the browser, it is easy to see that it is an exact copy of the preview displayed in the React app:

Print Preview of HTML Resume

Conclusion

Although it requires some initial investment in setting up the React app, it pays off to implement the resume in React in the long run as it's very easy to achieve the pixel perfect resume style you may be thinking of.