@@ -99,15 +99,15 @@ export const printerService = {
9999 const token = generatePrinterToken ( id ) ;
100100 const url = `${ baseUrl } /printer/${ id } ?token=${ token } ` ;
101101
102- // Step 3: Calculate PDF margins
103- // Some templates require margins to be applied via PDF (they use print:p-0 to remove CSS padding)
104- // Convert from CSS pixels to PDF points (divide by 0.75 since 1pt = 0.75px at 72dpi)
105- let marginX = 0 ;
106- let marginY = 0 ;
102+ // Step 3: Calculate print paddings for templates that disable CSS padding in print mode.
103+ // We render these margins inside the page (not via Puppeteer's PDF margins), so the margin
104+ // area matches the resume background color instead of staying white.
105+ let pagePaddingX = 0 ;
106+ let pagePaddingY = 0 ;
107107
108108 if ( printMarginTemplates . includes ( template ) ) {
109- marginX = Math . round ( data . metadata . page . marginX / 0.75 ) ;
110- marginY = Math . round ( data . metadata . page . marginY / 0.75 ) ;
109+ pagePaddingX = data . metadata . page . marginX ;
110+ pagePaddingY = data . metadata . page . marginY ;
111111 }
112112
113113 let browser : Browser | null = null ;
@@ -135,21 +135,65 @@ export const printerService = {
135135 const isFreeForm = format === "free-form" ;
136136
137137 const contentHeight = await page . evaluate (
138- ( marginY : number , isFreeForm : boolean , minPageHeight : number ) => {
138+ (
139+ pagePaddingX : number ,
140+ pagePaddingY : number ,
141+ isFreeForm : boolean ,
142+ minPageHeight : number ,
143+ backgroundColor : string ,
144+ ) => {
139145 const root = document . documentElement ;
146+ const body = document . body ;
140147 const pageElements = document . querySelectorAll ( "[data-page-index]" ) ;
148+ const pageContentElements = document . querySelectorAll ( ".page-content" ) ;
141149 const container = document . querySelector ( ".resume-preview-container" ) as HTMLElement | null ;
142150
151+ // Ensure PDF margins inherit the resume background color instead of defaulting to white.
152+ root . style . backgroundColor = backgroundColor ;
153+ body . style . backgroundColor = backgroundColor ;
154+ root . style . margin = "0" ;
155+ body . style . margin = "0" ;
156+ root . style . padding = "0" ;
157+ body . style . padding = "0" ;
158+
159+ for ( const el of pageElements ) {
160+ const pageWrapper = el as HTMLElement ;
161+ const pageSurface = pageWrapper . querySelector ( ".page" ) as HTMLElement | null ;
162+
163+ pageWrapper . style . backgroundColor = backgroundColor ;
164+ pageWrapper . style . breakInside = "auto" ;
165+
166+ if ( pageSurface ) pageSurface . style . backgroundColor = backgroundColor ;
167+ }
168+
169+ // Apply print-only margins as padding inside each page's content surface.
170+ if ( pagePaddingX > 0 || pagePaddingY > 0 ) {
171+ for ( const el of pageContentElements ) {
172+ const pageContent = el as HTMLElement ;
173+
174+ pageContent . style . boxSizing = "border-box" ;
175+ // Ensure padding is repeated on every printed fragment when content
176+ // flows across physical PDF pages (not just the first fragment).
177+ pageContent . style . boxDecorationBreak = "clone" ;
178+ pageContent . style . setProperty ( "-webkit-box-decoration-break" , "clone" ) ;
179+ if ( pagePaddingX > 0 ) {
180+ pageContent . style . paddingLeft = `${ pagePaddingX } pt` ;
181+ pageContent . style . paddingRight = `${ pagePaddingX } pt` ;
182+ }
183+ if ( pagePaddingY > 0 ) {
184+ pageContent . style . paddingTop = `${ pagePaddingY } pt` ;
185+ pageContent . style . paddingBottom = `${ pagePaddingY } pt` ;
186+ }
187+ }
188+ }
189+
143190 if ( isFreeForm ) {
144- // For free-form: add visual gaps between pages, then measure total height
145- // Convert marginY from PDF points to CSS pixels (1pt = 0.75px)
146- const marginYAsPixels = marginY * 0.75 ;
147191 const numberOfPages = pageElements . length ;
148192
149193 // Add margin between pages (except the last one)
150194 for ( let i = 0 ; i < numberOfPages - 1 ; i ++ ) {
151195 const pageEl = pageElements [ i ] as HTMLElement ;
152- pageEl . style . marginBottom = `${ marginYAsPixels } px ` ;
196+ if ( pagePaddingY > 0 ) pageEl . style . marginBottom = `${ pagePaddingY } pt ` ;
153197 }
154198
155199 // Now measure the total height (margins are now part of the DOM)
@@ -169,8 +213,8 @@ export const printerService = {
169213 // For A4/Letter
170214 const heightValue = minPageHeight ;
171215
172- // Subtract top + bottom margins from page height
173- const newHeight = `${ heightValue - marginY } px` ;
216+ // Keep page height fixed and let in- page padding (if any) define content bounds.
217+ const newHeight = `${ heightValue } px` ;
174218 if ( container ) container . style . setProperty ( "--page-height" , newHeight ) ;
175219 root . style . setProperty ( "--page-height" , newHeight ) ;
176220
@@ -181,7 +225,10 @@ export const printerService = {
181225 const index = Number . parseInt ( element . getAttribute ( "data-page-index" ) ?? "0" , 10 ) ;
182226
183227 // Force a page break before each page except the first
184- if ( index > 0 ) element . style . breakBefore = "page" ;
228+ if ( index > 0 ) {
229+ element . style . breakBefore = "page" ;
230+ element . style . pageBreakBefore = "always" ;
231+ }
185232
186233 // Allow content within a page to break naturally if it overflows
187234 // (e.g., if a single page has more content than fits on one PDF page)
@@ -190,9 +237,11 @@ export const printerService = {
190237
191238 return null ; // Fixed height from pageDimensionsAsPixels for A4/Letter
192239 } ,
193- marginY ,
240+ pagePaddingX ,
241+ pagePaddingY ,
194242 isFreeForm ,
195243 pageDimensionsAsPixels [ format ] . height ,
244+ data . metadata . design . colors . background ,
196245 ) ;
197246
198247 // Step 6: Generate the PDF with the specified dimensions and margins
@@ -208,9 +257,9 @@ export const printerService = {
208257 printBackground : true , // Includes background colors and images
209258 margin : {
210259 bottom : 0 ,
211- top : marginY ,
212- right : marginX ,
213- left : marginX ,
260+ top : 0 ,
261+ right : 0 ,
262+ left : 0 ,
214263 } ,
215264 } ) ;
216265
0 commit comments