Skip to content

Commit 9d5fe43

Browse files
Copilotpapotte
andcommitted
Enhance CV page with ATS-compatible semantic HTML and print styles
Co-authored-by: papotte <21336477+papotte@users.noreply.github.com>
1 parent 454443e commit 9d5fe43

2 files changed

Lines changed: 139 additions & 22 deletions

File tree

src/pages/cv/index.astro

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const title = `${CONTENT.name}'s CV`;
5656
<Print />
5757
</div>
5858
<div class="a4">
59-
<div class="header">
59+
<header class="header">
6060
<div class="title">
6161
<h1>{CONTENT.name}</h1>
6262
<p>{CONTENT.designation}</p>
@@ -68,17 +68,19 @@ const title = `${CONTENT.name}'s CV`;
6868
contactInfo.map(({ icon, label }) => {
6969
return (
7070
<p class="contact">
71-
{icon && <Icon name={icon} />}
72-
{label}
71+
<span class="icon-wrapper print:hidden" aria-hidden="true">
72+
{icon && <Icon name={icon} />}
73+
</span>
74+
<span class="contact-label">{label}</span>
7375
</p>
7476
);
7577
})
7678
}
7779
</div>
78-
</div>
80+
</header>
7981

80-
<div class="section">
81-
<div class="title"><h3>Work Experience</h3></div>
82+
<section class="section" aria-label="Work Experience">
83+
<div class="title"><h2>Work Experience</h2></div>
8284
{
8385
CONTENT.work.map((job: JobExperience) => {
8486
return (
@@ -102,9 +104,9 @@ const title = `${CONTENT.name}'s CV`;
102104
);
103105
})
104106
}
105-
</div>
106-
<div class="section">
107-
<div class="title"><h3>Education</h3></div>
107+
</section>
108+
<section class="section" aria-label="Education">
109+
<div class="title"><h2>Education</h2></div>
108110
{
109111
CONTENT.education.map((edu: Education) => {
110112
return (
@@ -128,9 +130,9 @@ const title = `${CONTENT.name}'s CV`;
128130
);
129131
})
130132
}
131-
</div>
132-
<div class="section">
133-
<div class="title"><h3>Language Skills</h3></div>
133+
</section>
134+
<section class="section" aria-label="Language Skills">
135+
<div class="title"><h2>Language Skills</h2></div>
134136
{
135137
CONTENT.languages.map((item: Language) => {
136138
return (
@@ -145,9 +147,9 @@ const title = `${CONTENT.name}'s CV`;
145147
);
146148
})
147149
}
148-
</div>
149-
<div class="section">
150-
<div class="title"><h3>IT Skills</h3></div>
150+
</section>
151+
<section class="section" aria-label="IT Skills">
152+
<div class="title"><h2>IT Skills</h2></div>
151153
{
152154
skillList.map(([label, item]) => {
153155
return (
@@ -164,9 +166,9 @@ const title = `${CONTENT.name}'s CV`;
164166
);
165167
})
166168
}
167-
</div>
168-
<div class="section">
169-
<div class="title"><h3>Projects</h3></div>
169+
</section>
170+
<section class="section" aria-label="Projects">
171+
<div class="title"><h2>Projects</h2></div>
170172
{
171173
CONTENT.projects.map((item: Project) => {
172174
return (
@@ -188,9 +190,9 @@ const title = `${CONTENT.name}'s CV`;
188190
);
189191
})
190192
}
191-
</div>
192-
<div class="section">
193-
<div class="title"><h3>Interests</h3></div>
193+
</section>
194+
<section class="section" aria-label="Interests">
195+
<div class="title"><h2>Interests</h2></div>
194196
<div class="block">
195197
<div class="date"></div>
196198
<div class="information">
@@ -203,7 +205,7 @@ const title = `${CONTENT.name}'s CV`;
203205
</div>
204206
</div>
205207
</div>
206-
</div>
208+
</section>
207209
</div>
208210
</div>
209211
</body>

src/styles/cv.scss

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
.header {
1313
@apply mb-10 flex items-end justify-between;
1414

15+
// Print: stack header in single column for better ATS parsing
16+
@media print {
17+
display: flex;
18+
flex-direction: column;
19+
align-items: flex-start;
20+
gap: 0.5rem;
21+
}
22+
1523
h1 {
1624
@apply mb-2;
1725
}
@@ -23,13 +31,36 @@
2331
@apply justify-end text-end;
2432
}
2533

34+
// Print: left-align for better ATS reading order
35+
@media print {
36+
> * {
37+
justify-content: flex-start;
38+
text-align: start;
39+
}
40+
}
41+
2642
p {
2743
@apply flex flex-row gap-1;
2844

2945
svg {
3046
@apply h-4 w-4;
3147
}
3248
}
49+
50+
// Print: ensure contact info is text-only for ATS
51+
.contact {
52+
.icon-wrapper {
53+
@media print {
54+
display: none;
55+
}
56+
}
57+
58+
.contact-label {
59+
@media print {
60+
font-style: normal;
61+
}
62+
}
63+
}
3364
}
3465
}
3566

@@ -46,21 +77,56 @@
4677
content: ' ';
4778
}
4879

80+
> h2,
4981
> h3 {
5082
@apply col-span-5;
5183
}
84+
85+
// Print: simplify section title styling for ATS
86+
@media print {
87+
display: flex;
88+
flex-direction: row;
89+
align-items: baseline;
90+
gap: 0.5rem;
91+
92+
&::before {
93+
width: 40px;
94+
flex-shrink: 0;
95+
}
96+
}
5297
}
5398

5499
> .block {
55100
@apply my-2 grid grid-cols-6 gap-4;
56101

102+
// Print: use single column layout for better ATS parsing
103+
@media print {
104+
display: block;
105+
page-break-inside: avoid;
106+
}
107+
57108
> .date {
58109
@apply col-span-1 text-right;
110+
111+
// Print: inline with information for better reading order
112+
@media print {
113+
display: inline;
114+
font-weight: 600;
115+
116+
&::after {
117+
content: ': ';
118+
}
119+
}
59120
}
60121

61122
> .information {
62123
@apply col-span-5;
63124

125+
// Print: ensure proper display
126+
@media print {
127+
display: inline;
128+
}
129+
64130
> .title {
65131
> span {
66132
&::after {
@@ -81,8 +147,57 @@
81147
display: unset;
82148
}
83149
}
150+
151+
// Print: simplify columns for ATS
152+
@media print {
153+
column-count: 1 !important;
154+
}
84155
}
85156
}
86157
}
87158
}
159+
160+
// Print-specific optimizations for ATS compatibility
161+
@media print {
162+
// Avoid CSS properties that cause rasterization
163+
* {
164+
transform: none !important;
165+
filter: none !important;
166+
backdrop-filter: none !important;
167+
mix-blend-mode: normal !important;
168+
}
169+
170+
// Ensure all text is selectable (not rendered as image)
171+
body,
172+
div,
173+
p,
174+
span,
175+
h1,
176+
h2,
177+
h3,
178+
h4,
179+
h5,
180+
h6,
181+
ul,
182+
li {
183+
-webkit-print-color-adjust: exact;
184+
print-color-adjust: exact;
185+
}
186+
187+
// Hide all SVG icons
188+
svg {
189+
display: none !important;
190+
}
191+
192+
// Optimize page breaks
193+
h1,
194+
h2,
195+
h3 {
196+
page-break-after: avoid;
197+
}
198+
199+
.section {
200+
page-break-inside: avoid;
201+
}
202+
}
88203
}

0 commit comments

Comments
 (0)