mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 18:23:47 +10:00
428 lines
25 KiB
Plaintext
428 lines
25 KiB
Plaintext
---
|
||
title: "Applying custom styles"
|
||
description: "Write CSS rules that change how your resume PDF looks: pick an element on the page, style it, and learn what the PDF engine supports."
|
||
---
|
||
|
||
Custom styles let you change details the Design controls don't cover, such as the color of one entry, the spacing
|
||
between skills, or a border under every section heading. You write them in a CSS-like language called Semantic CSS,
|
||
and they apply to the PDF: the page preview, PDF downloads, and your public resume. DOCX and Markdown exports
|
||
don't use them.
|
||
|
||
Try the regular **Design** controls first (template, type, color, page and layout). They cover most changes and keep
|
||
working when you switch templates. Reach for custom styles when you want something specific.
|
||
|
||
## Before you start
|
||
|
||
- Custom styles are per resume. Each resume has its own stylesheet.
|
||
- The editor reports fatal stylesheet limits. Unsupported declarations or selectors may still be skipped; the
|
||
engine limitations are listed beside the editor. If you see no change on the page, check those limits. See [When a rule has no effect](#when-a-rule-has-no-effect).
|
||
- Custom styles can't add content, load fonts or images, or change what a section contains. They only restyle what's
|
||
already on the page.
|
||
|
||
## Open the stylesheet editor
|
||
|
||
<Steps>
|
||
<Step title="Switch to Design">
|
||
Open your resume and select **Design** at the top of the editor, or press <kbd>2</kbd> when you're not typing in a
|
||
field.
|
||
</Step>
|
||
<Step title="Open Advanced">
|
||
Select **Advanced** in the row of groups at the top of the Design panel. The Advanced group opens and scrolls into
|
||
view.
|
||
</Step>
|
||
<Step title="Find Custom Styles">
|
||
Scroll to **Custom Styles**, near the end of the Advanced group, just above **Reset design defaults**.
|
||
</Step>
|
||
</Steps>
|
||
|
||
<Frame caption="The Custom Styles editor, at the end of Design → Advanced">
|
||
<img
|
||
src="/images/guides/applying-custom-styles/custom-styles-editor.webp"
|
||
alt="The Custom Styles heading with a toolbar of five icons (undo, redo, copy, format, focus mode), two hint lines, and an empty code editor"
|
||
/>
|
||
</Frame>
|
||
|
||
On a phone, Design opens as a sheet over the page. Select the **Page** tab, then select **Advanced** under the page
|
||
settings.
|
||
|
||
<Note>
|
||
**Reset design defaults** doesn't touch your custom styles. It resets the look (fonts, colors, spacing) and keeps your
|
||
stylesheet, paper size, language, date format and section layout.
|
||
</Note>
|
||
|
||
## Style one section or entry
|
||
|
||
The quickest way to start is to pick the thing you want to change on the page.
|
||
|
||
<Steps>
|
||
<Step title="Click it on the page">
|
||
With the Custom Styles editor open, click the resume header, an entry (for example a job under Experience), or a
|
||
section without entries (such as Summary) on the page.
|
||
</Step>
|
||
<Step title="Type your declarations">
|
||
The editor adds a rule for it at the end of your stylesheet, with a comment naming what you picked, and puts the
|
||
cursor inside the rule. Type the declarations you want, for example `color: #0f766e;`.
|
||
</Step>
|
||
<Step title="Check the page">
|
||
The page updates as you type. While your cursor is inside a rule, everything the rule styles is outlined with a
|
||
dashed line on the page.
|
||
</Step>
|
||
</Steps>
|
||
|
||
<Frame caption="Clicking the University of Washington entry added a rule for it; the dashed outline shows what the rule styles">
|
||
<img
|
||
src="/images/guides/applying-custom-styles/pick-an-entry-on-the-page.webp"
|
||
alt="The stylesheet editor with a rule for the Education entry University of Washington, and the same entry on the page shown in teal inside a dashed outline"
|
||
/>
|
||
</Frame>
|
||
|
||
A picked rule looks like this:
|
||
|
||
```css
|
||
/* Education › University of Washington */
|
||
section[id="education"] item[id="019bef5a-93e4-7746-ad39-48455f6cef9e"] {
|
||
color: #0f766e;
|
||
}
|
||
```
|
||
|
||
If the stylesheet already has a rule with that exact selector, clicking the element moves your cursor into the existing
|
||
rule instead of adding another one.
|
||
|
||
Rules made this way use the entry's ID, so they only affect that one entry in this resume. To style every entry of a
|
||
kind, use the section type instead (see [Target the right part of your resume](#target-the-right-part-of-your-resume)).
|
||
|
||
## Find an entry by name
|
||
|
||
You can also add an entry's selector without clicking the page. Where a selector goes (outside any `{ }`), start
|
||
typing part of the entry's title, such as `Senior`. The suggestions include matching sections and entries, shown as
|
||
"Section › Entry". Choose one to insert its selector.
|
||
|
||
<Frame caption="Typing “Senior” suggests the Senior Game Developer entry; choosing it inserts its selector">
|
||
<img
|
||
src="/images/guides/applying-custom-styles/find-an-entry-by-name.webp"
|
||
alt="Autocomplete suggestions under the word Senior, led by Experience › Senior Game Developer with its section and item selector"
|
||
/>
|
||
</Frame>
|
||
|
||
Autocomplete also suggests element names and attributes in selectors, property names inside a rule, and values after
|
||
a colon, including your own variables and the read-only `--resume-*` variables. Press <kbd>Ctrl</kbd>
|
||
|
||
<kbd>Space</kbd> to open the suggestions without typing.
|
||
|
||
A few more editor helpers:
|
||
|
||
- **Hover** an element name, property or `--resume-*` variable to see a short description.
|
||
- **Color swatches** appear after color values. Click one to pick a color from presets or a custom picker; the value
|
||
in your CSS changes with it.
|
||
- **Search** with <kbd>⌘</kbd> <kbd>F</kbd> (<kbd>Ctrl</kbd> <kbd>F</kbd> on Windows and Linux).
|
||
|
||
## Use the editor toolbar
|
||
|
||
| Button | What it does |
|
||
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| **Undo resume change** / **Redo resume change** | Steps back or forward through your resume's changes. |
|
||
| **Copy stylesheet** | Copies the whole stylesheet to your clipboard. |
|
||
| **Format stylesheet** | Tidies indentation and spacing. |
|
||
| **Open focus mode** | Opens the editor in a larger side panel titled **Semantic CSS stylesheet**. Select **Exit focus mode** or close the panel to go back. |
|
||
|
||
While typing in the stylesheet editor, <kbd>⌘</kbd> <kbd>Z</kbd> and <kbd>⌘</kbd> <kbd>Shift</kbd>
|
||
|
||
<kbd>Z</kbd> use the editor's local text history. The toolbar buttons use your resume's shared history, so they can also
|
||
reverse a template switch or another resume change. See [Undoing changes and version
|
||
history](/guides/undoing-changes-and-version-history).
|
||
|
||
Your stylesheet saves automatically with the rest of the resume, and it's part of every saved version in **History**.
|
||
|
||
## When a rule has no effect
|
||
|
||
Fatal stylesheet errors appear above the editor. For individual rules, the PDF engine applies what it understands and skips the rest: an
|
||
unsupported declaration is skipped on its own, and a rule with an invalid selector is skipped as a whole. If a change
|
||
doesn't show:
|
||
|
||
1. **Check the selector matches something.** Put your cursor inside the rule. If nothing is outlined on the page, the
|
||
selector matches nothing. Check spelling (names are lowercase and case-sensitive), attribute values, and whether
|
||
the current template has that part.
|
||
2. **Check the property is supported** for that element. See the [properties](#properties) and
|
||
[engine limits](#engine-limits) below. For example, `background-color` works on containers such as `section` and
|
||
`header`, but not on text elements such as `field`.
|
||
3. **Simplify.** Reduce the rule to one selector and one declaration, confirm it works, then add more.
|
||
4. **Check the limit message.** More than 128 KB, 1,024 rules, 8,192 declarations, 64 selectors in one rule or four nested media blocks makes the whole stylesheet unusable; the editor reports this.
|
||
|
||
<Warning>
|
||
Check the downloaded PDF before you send or share a resume with custom styles. Page breaks and template-specific
|
||
details can make a rule look different from what you intended.
|
||
</Warning>
|
||
|
||
### Engine limits
|
||
|
||
The PDF engine accepts these without an error but doesn't draw them:
|
||
|
||
- Rotation (`transform: rotate(...)`). The picture's Rotation control is disabled while the PDF engine lacks support.
|
||
- Dashed and dotted borders. They draw as solid lines.
|
||
- Percentages for padding, margin, gaps and font sizes. Percentages work only for `width`, `height`, their `min-` and
|
||
`max-` forms, `flex-basis`, `left` and `right`.
|
||
- `z-index`, `max-lines`, `text-indent`, `vertical-align`, `object-position` and `-resume-min-presence-ahead`.
|
||
|
||
Two text limits apply whether or not you use custom styles: right-to-left lines are laid out left to right and then
|
||
aligned right, and characters outside the basic range, such as most emoji, don't draw.
|
||
|
||
## Copy styles to another resume
|
||
|
||
Section types, element names and field names work in any resume. Rules that use an entry's `id` only match that
|
||
entry, and template parts only exist in their template.
|
||
|
||
1. In the source resume, select **Copy stylesheet**.
|
||
2. In the other resume, open **Design → Advanced → Custom Styles** and paste.
|
||
3. Remove or rewrite rules with `item[id=...]` selectors, and template-part rules for a different template.
|
||
4. Check the page and the downloaded PDF.
|
||
|
||
## Reference
|
||
|
||
### Target the right part of your resume
|
||
|
||
Semantic CSS selectors describe resume content, not a template's internal layout. Element names and attribute names
|
||
are lowercase and case-sensitive.
|
||
|
||
**Resume structure**
|
||
|
||
| Element | Targets | Typical use |
|
||
| ----------------- | ---------------------------------------------------- | ------------------------------------------------------- |
|
||
| `resume` | The whole resume | Scope a rule to one template. |
|
||
| `page` | One PDF page | Set a page size. |
|
||
| `region` | The header, main, sidebar or featured area of a page | Style a layout area. |
|
||
| `header` | The resume header | Style the name and contact area. |
|
||
| `section` | A section | Target a section type or placement. |
|
||
| `section-heading` | A section's title | Change heading type or add a rule under it. |
|
||
| `section-items` | The entries in a section | Adjust entry layout and gaps. |
|
||
| `item` | One entry | Space or keep together a job, project or similar entry. |
|
||
| `item-header` | An entry's top row | Align the title, company, dates or similar details. |
|
||
|
||
**Header and entry content**
|
||
|
||
| Element | Targets |
|
||
| ------------------------------ | --------------------------------------------------- |
|
||
| `picture` | The profile picture. |
|
||
| `name`, `headline` | The name and headline in the header. |
|
||
| `contact-list`, `contact-item` | The contact details in the header. |
|
||
| `combined-text` | A value the template builds from several fields. |
|
||
| `field` | A named field, such as a position, company or date. |
|
||
| `link` | A link. |
|
||
| `icon`, `level` | An icon, or a skill or language level indicator. |
|
||
|
||
**Rich text and lists**
|
||
|
||
| Element | Targets |
|
||
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
|
||
| `rich-text`, `rich-heading`, `blockquote`, `paragraph` | Formatted text blocks in descriptions and the summary. |
|
||
| `list`, `list-item`, `list-marker`, `list-item-content` | A list, one list row, its bullet or number, and its text. |
|
||
| `strong`, `emphasis`, `underline`, `strike`, `code`, `text-span`, `mark` | Inline formatting. |
|
||
| `hard-break`, `horizontal-rule` | A line break or horizontal rule. |
|
||
| `template-part` | A template-specific detail. Always guard it with a template (see below). |
|
||
|
||
### Narrow a selector with attributes
|
||
|
||
| Attribute | Use it with | Example |
|
||
| ------------- | --------------------------------------------------------- | ------------------------------------ |
|
||
| `type` | `section`, `icon` | `section[type="experience"]` |
|
||
| `placement` | `region`, `section` | `region[placement="sidebar"]` |
|
||
| `region` | `region`, `header` | `region[region="featured"]` |
|
||
| `origin` | `section` | `section[origin="main"]` |
|
||
| `part` | `region`, `section`, `contact-item`, `item-header` | `region[part~="sidebar-background"]` |
|
||
| `template` | `resume` | `resume[template="azurill"]` |
|
||
| `name` | `field`, `contact-item`, `combined-text`, `template-part` | `field[name="position"]` |
|
||
| `level` | `rich-heading` | `rich-heading[level="2"]` |
|
||
| `direction` | `list-item-content` | `list-item-content[direction="rtl"]` |
|
||
| `page-number` | `page` | `page[page-number="1"]` |
|
||
| `id` | Any element that has one | `section[id="projects"]` |
|
||
| `role` | Any element with roles | `field[role~="secondary-text"]` |
|
||
|
||
Attribute matchers `=`, `~=`, `^=` and `*=` are supported. `#projects` is shorthand for `[id="projects"]` when the ID
|
||
is a plain word (section IDs such as `experience` are; entry IDs aren't, so use `item[id="..."]`).
|
||
|
||
Selectors can be combined with commas, and with the descendant (space), child (`>`), next-sibling (`+`) and
|
||
later-sibling (`~`) combinators. Supported pseudo-classes: `:root`, `:first-child`, `:last-child`, `:only-child`,
|
||
`:nth-child()`, `:nth-of-type()`, `:is()`, `:where()` and `:not()`. `:nth-of-type` counts elements of the same kind,
|
||
so `item:nth-of-type(1)` is the first entry.
|
||
|
||
```css
|
||
section[type="experience"] > section-heading {
|
||
border-bottom: 1pt solid #0f766e;
|
||
}
|
||
|
||
region[placement="sidebar"] {
|
||
background-color: #f8fafc;
|
||
padding: 18pt;
|
||
}
|
||
|
||
section[type="experience"] item:nth-of-type(1) {
|
||
margin-bottom: 12pt;
|
||
}
|
||
```
|
||
|
||
### Reuse your Design settings
|
||
|
||
Your Design settings are available as read-only `--resume-*` variables. Define your own variables in `:root` and
|
||
reuse the resume's values, so your styles follow when you change a color or size in Design.
|
||
|
||
```css
|
||
:root {
|
||
--accent: var(--resume-primary-color);
|
||
--rule: #cbd5e1;
|
||
}
|
||
|
||
section-heading {
|
||
color: var(--accent);
|
||
border-bottom: 1pt solid var(--rule);
|
||
letter-spacing: 0.4pt;
|
||
}
|
||
```
|
||
|
||
Don't assign a value to a `--resume-*` variable; create your own, such as `--accent`, instead.
|
||
|
||
| Design setting | Read-only variables |
|
||
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| Colors | `--resume-primary-color`, `--resume-text-color`, `--resume-background-color` |
|
||
| Type | `--resume-body-font-size`, `--resume-body-line-height`, `--resume-heading-font-size`, `--resume-heading-line-height` |
|
||
| Page and layout | `--resume-page-gap-x`, `--resume-page-gap-y`, `--resume-page-margin-x`, `--resume-page-margin-y`, `--resume-page-width`, `--resume-page-height`, `--resume-sidebar-width` |
|
||
| Picture | `--resume-picture-size`, `--resume-picture-rotation`, `--resume-picture-aspect-ratio`, `--resume-picture-border-radius`, `--resume-picture-border-width`, `--resume-picture-border-color`, `--resume-picture-shadow-width`, `--resume-picture-shadow-color` |
|
||
|
||
Use `pt` for predictable sizes in a PDF. Lengths also accept `px`, `in`, `mm`, `cm`, `em` and `rem`, and `%` where the
|
||
[engine limits](#engine-limits) allow it. `inherit` and `initial` work as values, and `!important` is respected.
|
||
|
||
### Properties
|
||
|
||
| Goal | Properties |
|
||
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| Text | `color`, `font-size`, `font-style`, `font-weight`, `letter-spacing`, `line-height`, `text-align`, `text-decoration`, `text-transform`, `text-overflow`, `direction` |
|
||
| Spacing and size | `margin`, `padding` (and their side forms), `gap`, `row-gap`, `column-gap`, `width`, `height`, `min-width`, `max-width`, `min-height`, `max-height`, `aspect-ratio` |
|
||
| Layout | `display` (`flex` or `none`), `flex`, `flex-direction`, `flex-wrap`, `justify-content`, `align-items`, `align-self`, `order`, `position`, `top`, `right`, `bottom`, `left`, `overflow` |
|
||
| Look | `background-color`, `border` (and its side, width, style, color and radius forms), `opacity`, `transform`, `transform-origin` |
|
||
| Picture | `object-fit`, `-resume-shadow-color`, `-resume-shadow-width` |
|
||
| Page breaks | `break-before`, `break-inside`, `orphans`, `widows`, `size` (on `page` only) |
|
||
|
||
`background-color` and borders apply to container elements (such as `header`, `section`, `item`, `region`), not to
|
||
text elements. `display: none` hides an element that's already there; to remove content, hide it in **Write** instead,
|
||
so it's also left out of exports.
|
||
|
||
Backgrounds must be flat colors. Gradients such as `linear-gradient(...)` aren't supported:
|
||
|
||
```css
|
||
header {
|
||
background-color: #1e293b;
|
||
}
|
||
```
|
||
|
||
### Style common details
|
||
|
||
List rows, markers and text:
|
||
|
||
```css
|
||
rich-text list-item {
|
||
gap: 4pt;
|
||
}
|
||
|
||
list-marker {
|
||
color: var(--resume-primary-color);
|
||
}
|
||
|
||
list-item-content {
|
||
line-height: 1.35;
|
||
}
|
||
```
|
||
|
||
Space between a skill's level icons (`gap` works too; `row-gap` doesn't change this single row):
|
||
|
||
```css
|
||
section[type="skills"] level {
|
||
column-gap: 4pt;
|
||
}
|
||
```
|
||
|
||
Named fields inside entries:
|
||
|
||
```css
|
||
section[type="experience"] field[name="position"] {
|
||
font-weight: 600;
|
||
}
|
||
|
||
section[type="experience"] field[name="company"] {
|
||
color: var(--resume-primary-color);
|
||
}
|
||
```
|
||
|
||
### Control page breaks and page size
|
||
|
||
Start a section on a new page, keep entries whole, or set a custom page size. Review the downloaded PDF after each
|
||
change.
|
||
|
||
```css
|
||
page {
|
||
size: 210mm 297mm;
|
||
}
|
||
|
||
section[type="projects"] {
|
||
break-before: page;
|
||
}
|
||
|
||
item {
|
||
break-inside: avoid;
|
||
}
|
||
```
|
||
|
||
`size` takes `A4`, `letter`, or a width and height. It applies only to `page` and can't be inside `@media`.
|
||
|
||
`@media` queries use the PDF page's dimensions, not your browser window. Supported features are `width`, `min-width`,
|
||
`max-width`, `height`, `min-height`, `max-height` and `orientation` (`portrait` or `landscape`).
|
||
|
||
```css
|
||
@media (max-width: 600pt) {
|
||
region[placement="sidebar"] {
|
||
padding: 12pt;
|
||
}
|
||
}
|
||
```
|
||
|
||
### Template-specific parts
|
||
|
||
Some templates expose extra details that others don't have. Always guard these rules with `resume[template="..."]`, so
|
||
they don't apply by accident after a template change.
|
||
|
||
```css
|
||
resume[template="azurill"] template-part[name="timeline-line"] {
|
||
background-color: #94a3b8;
|
||
}
|
||
```
|
||
|
||
| Template | Selectors |
|
||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| Azurill | `template-part[name="timeline-content"]`, `template-part[name="timeline-dot"]`, `template-part[name="timeline-line"]`, `template-part[name="timeline-marker"]` |
|
||
| Bronzor | `section[part~="interleaved-section-row"]` |
|
||
| Chikorita | `template-part[name="contact-row-primary"]`, `template-part[name="contact-row-secondary"]` |
|
||
| Ditgar | `template-part[name="featured-summary"]`, `item-header[part~="item-header-border"]`, `region[part~="sidebar-background"]` |
|
||
| Ditto | `template-part[name="contact-offset"]`, `template-part[name="header-band"]`, `template-part[name="picture-anchor"]` |
|
||
| Gengar | `template-part[name="featured-summary"]`, `region[part~="sidebar-background"]` |
|
||
| Glalie | `template-part[name="sidebar-background"]` |
|
||
| Leafish | `template-part[name="header-body"]`, `template-part[name="header-contact-band"]`, `template-part[name="header-intro"]` |
|
||
| Meowth | `template-part[name="education-grade-row"]`, `template-part[name="inline-item-header-leading"]`, `template-part[name="inline-item-header-middle"]`, `template-part[name="inline-item-header-trailing"]` |
|
||
| Pikachu | `template-part[name="header-divider"]` |
|
||
| Rhyhorn | `template-part[name="contact-item-content"]`, `contact-item[part~="contact-item-last"]` |
|
||
| Scizor | `template-part[name="header-name-rule"]` |
|
||
|
||
Kakuna, Lapras and Onyx have no template-specific parts.
|
||
|
||
Every template also has `template-part[name="item-header-row"]`: the row with the title and date in Awards,
|
||
Certifications, Projects and Publications entries. It doesn't need a template guard.
|
||
|
||
### Not supported
|
||
|
||
Classes, pseudo-elements (`::before`, `::after`), CSS Grid, `@import`, `@font-face` and other at-rules except
|
||
`@media`, `url()` and any external file, gradients, general box shadows, filters, animations and transitions. Use the
|
||
Design controls for fonts, the picture and broader layout changes.
|
||
|
||
## Related guides
|
||
|
||
- [Choosing a template](/guides/choosing-a-template): a different template may get you most of the way without CSS.
|
||
- [Customizing typography](/guides/customizing-typography): fonts, sizes and line height from Design.
|
||
- [Arranging the layout](/guides/arranging-the-layout): columns, sidebar and page breaks without CSS.
|
||
- [Undoing changes and version history](/guides/undoing-changes-and-version-history): get back to a stylesheet that worked.
|