@@ -98,16 +98,18 @@ export const createParagraphDecorationLayers = (
9898 // Both real between (showBetweenBorder) and nil/none between (suppressBottomBorder)
9999 // need gap extension to keep left/right borders continuous through the spacing gap.
100100 const gapExtension = betweenInfo ?. showBetweenBorder || betweenInfo ?. suppressBottomBorder ? betweenInfo ! . gapBelow : 0 ;
101- const totalBottomExpansion = gapExtension + space . bottom ;
102- const bottomValue = totalBottomExpansion > 0 ? `-${ totalBottomExpansion } px` : '0px' ;
103- const topValue = space . top > 0 ? `-${ space . top } px` : '0px' ;
104101
105- const baseStyles = {
102+ // Border widths for each rendered side. With box-sizing: border-box, CSS borders are
103+ // drawn INSIDE the element. To position the border's inner edge at `space` distance
104+ // from the text, the border layer must be expanded by space + borderWidth.
105+ // The shading layer only needs space (it has no CSS borders).
106+ const bw = computeRenderedBorderWidths ( attrs . borders , betweenInfo ) ;
107+
108+ const shadingBottom = gapExtension + space . bottom ;
109+ const borderBottom = gapExtension + space . bottom + bw . bottom ;
110+
111+ const commonStyles = {
106112 position : 'absolute' ,
107- top : topValue ,
108- bottom : bottomValue ,
109- left : `${ borderBox . leftInset - space . left } px` ,
110- width : `${ borderBox . width + space . left + space . right } px` ,
111113 pointerEvents : 'none' ,
112114 boxSizing : 'border-box' ,
113115 } as const ;
@@ -116,22 +118,51 @@ export const createParagraphDecorationLayers = (
116118 if ( attrs . shading ) {
117119 shadingLayer = doc . createElement ( 'div' ) ;
118120 shadingLayer . classList . add ( 'superdoc-paragraph-shading' ) ;
119- Object . assign ( shadingLayer . style , baseStyles ) ;
121+ Object . assign ( shadingLayer . style , commonStyles ) ;
122+ shadingLayer . style . top = space . top > 0 ? `-${ space . top } px` : '0px' ;
123+ shadingLayer . style . bottom = shadingBottom > 0 ? `-${ shadingBottom } px` : '0px' ;
124+ shadingLayer . style . left = `${ borderBox . leftInset - space . left } px` ;
125+ shadingLayer . style . width = `${ borderBox . width + space . left + space . right } px` ;
120126 applyParagraphShadingStyles ( shadingLayer , attrs . shading ) ;
121127 }
122128
123129 let borderLayer : HTMLElement | undefined ;
124130 if ( attrs . borders ) {
125131 borderLayer = doc . createElement ( 'div' ) ;
126132 borderLayer . classList . add ( 'superdoc-paragraph-border' ) ;
127- Object . assign ( borderLayer . style , baseStyles ) ;
133+ Object . assign ( borderLayer . style , commonStyles ) ;
134+ borderLayer . style . top = space . top + bw . top > 0 ? `-${ space . top + bw . top } px` : '0px' ;
135+ borderLayer . style . bottom = borderBottom > 0 ? `-${ borderBottom } px` : '0px' ;
136+ borderLayer . style . left = `${ borderBox . leftInset - space . left - bw . left } px` ;
137+ borderLayer . style . width = `${ borderBox . width + space . left + bw . left + space . right + bw . right } px` ;
128138 borderLayer . style . zIndex = '1' ;
129139 applyParagraphBorderStyles ( borderLayer , attrs . borders , betweenInfo ) ;
130140 }
131141
132142 return { shadingLayer, borderLayer } ;
133143} ;
134144
145+ /**
146+ * Computes the rendered CSS border widths per side, accounting for suppressed sides.
147+ * Used to expand the border layer so the inner edge is at the correct `space` offset.
148+ */
149+ const computeRenderedBorderWidths = (
150+ borders ?: ParagraphBorders ,
151+ betweenInfo ?: BetweenBorderInfo ,
152+ ) : { top : number ; bottom : number ; left : number ; right : number } => {
153+ if ( ! borders ) return { top : 0 , bottom : 0 , left : 0 , right : 0 } ;
154+ const suppressTop = betweenInfo ?. suppressTopBorder ?? false ;
155+ const suppressBottom = betweenInfo ?. suppressBottomBorder ?? false ;
156+ const showBetween = betweenInfo ?. showBetweenBorder ?? false ;
157+
158+ return {
159+ top : ! suppressTop ? ( borders . top ?. width ?? 0 ) : 0 ,
160+ bottom : showBetween ? ( borders . between ?. width ?? 0 ) : ! suppressBottom ? ( borders . bottom ?. width ?? 0 ) : 0 ,
161+ left : borders . left ?. width ?? 0 ,
162+ right : borders . right ?. width ?? 0 ,
163+ } ;
164+ } ;
165+
135166// βββ Border CSS application ββββββββββββββββββββββββββββββββββββββββ
136167
137168type CssBorderSide = 'top' | 'right' | 'bottom' | 'left' ;
0 commit comments