@@ -8,7 +8,7 @@ function Highlighter(options = hhDefaultOptions) {
88 options [ key ] = options [ key ] ?? hhDefaultOptions [ key ] ;
99 }
1010
11- this . annotatableContainer , this . annotatableParagraphs ;
11+ this . annotatableContainer , this . relativeAncestorElement , this . annotatableParagraphs ;
1212 let generalStylesheet , appearanceStylesheet , highlightApiStylesheet , selectionStylesheet ;
1313 let annotatableParagraphIds , hyperlinkElements ;
1414 let svgBackground , svgActiveOverlay , selectionHandles ;
@@ -33,6 +33,16 @@ function Highlighter(options = hhDefaultOptions) {
3333 return false ;
3434 }
3535
36+ // Get the closest ancestor element with `position: relative`, or the root element (this is used to calculate the position of selection handles and SVG highlights)
37+ let ancestorElement = this . annotatableContainer ;
38+ while ( ancestorElement ) {
39+ if ( ancestorElement === document . documentElement || window . getComputedStyle ( ancestorElement ) . position === 'relative' ) {
40+ this . relativeAncestorElement = ancestorElement ;
41+ break ;
42+ }
43+ ancestorElement = ancestorElement . parentElement ;
44+ }
45+
3646 // Abort controller can be used to cancel event listeners if the highlighter is removed
3747 controller = new AbortController ;
3848
@@ -50,7 +60,6 @@ function Highlighter(options = hhDefaultOptions) {
5060 document . adoptedStyleSheets . push ( selectionStylesheet ) ;
5161 generalStylesheet . replaceSync ( `
5262 ${ options . containerSelector } {
53- position: relative;
5463 -webkit-tap-highlight-color: transparent;
5564 }
5665 .hh-wrapper-start, .hh-wrapper-end, .hh-selection-handle {
@@ -860,7 +869,7 @@ function Highlighter(options = hhDefaultOptions) {
860869 const selectionRangeRects = selectionRange . getClientRects ( ) ;
861870 const startRect = selectionRangeRects [ 0 ] ;
862871 const endRect = selectionRangeRects [ selectionRangeRects . length - 1 ] ;
863- const annotatableContainerClientRect = this . annotatableContainer . getBoundingClientRect ( ) ;
872+ const relativeAncestorClientRect = this . relativeAncestorElement . getBoundingClientRect ( ) ;
864873 const startNodeIsRtl = window . getComputedStyle ( selectionRange . startContainer . parentElement ) . direction === 'rtl' ;
865874 const endNodeIsRtl = window . getComputedStyle ( selectionRange . endContainer . parentElement ) . direction === 'rtl' ;
866875
@@ -869,14 +878,14 @@ function Highlighter(options = hhDefaultOptions) {
869878 let side ;
870879 if ( selectionHandle . dataset . position === 'start' ) {
871880 side = startNodeIsRtl ? 'right' : 'left' ;
872- selectionHandle . style . left = startRect [ side ] - annotatableContainerClientRect . left + 'px' ;
881+ selectionHandle . style . left = startRect [ side ] - relativeAncestorClientRect . left + 'px' ;
873882 selectionHandle . style . height = startRect . height + 'px' ;
874- selectionHandle . style . top = startRect . top - annotatableContainerClientRect . top + 'px' ;
883+ selectionHandle . style . top = startRect . top - relativeAncestorClientRect . top + 'px' ;
875884 } else {
876885 side = endNodeIsRtl ? 'left' : 'right' ;
877- selectionHandle . style . left = endRect [ side ] - annotatableContainerClientRect . left + 'px' ;
886+ selectionHandle . style . left = endRect [ side ] - relativeAncestorClientRect . left + 'px' ;
878887 selectionHandle . style . height = endRect . height + 'px' ;
879- selectionHandle . style . top = endRect . top - annotatableContainerClientRect . top + 'px' ;
888+ selectionHandle . style . top = endRect . top - relativeAncestorClientRect . top + 'px' ;
880889 }
881890 if ( selectionHandle . dataset . side !== side ) {
882891 selectionHandle . dataset . side = side ;
@@ -1031,16 +1040,16 @@ function Highlighter(options = hhDefaultOptions) {
10311040 return ;
10321041 }
10331042 if ( type === 'svg' && clientRect ) {
1034- const annotatableContainerClientRect = this . annotatableContainer . getBoundingClientRect ( ) ;
1043+ const relativeAncestorClientRect = this . relativeAncestorElement . getBoundingClientRect ( ) ;
10351044 styleTemplate = styleTemplate
1036- . replaceAll ( '{x}' , clientRect . x - annotatableContainerClientRect . x )
1037- . replaceAll ( '{y}' , clientRect . y - annotatableContainerClientRect . y )
1045+ . replaceAll ( '{x}' , clientRect . x - relativeAncestorClientRect . x )
1046+ . replaceAll ( '{y}' , clientRect . y - relativeAncestorClientRect . y )
10381047 . replaceAll ( '{width}' , clientRect . width )
10391048 . replaceAll ( '{height}' , clientRect . height )
1040- . replaceAll ( '{top}' , clientRect . top - annotatableContainerClientRect . top )
1041- . replaceAll ( '{right}' , clientRect . right - annotatableContainerClientRect . right )
1042- . replaceAll ( '{bottom}' , clientRect . bottom - annotatableContainerClientRect . bottom )
1043- . replaceAll ( '{left}' , clientRect . left - annotatableContainerClientRect . left ) ;
1049+ . replaceAll ( '{top}' , clientRect . top - relativeAncestorClientRect . top )
1050+ . replaceAll ( '{right}' , clientRect . right - relativeAncestorClientRect . right )
1051+ . replaceAll ( '{bottom}' , clientRect . bottom - relativeAncestorClientRect . bottom )
1052+ . replaceAll ( '{left}' , clientRect . left - relativeAncestorClientRect . left ) ;
10441053 }
10451054 return styleTemplate ;
10461055 }
0 commit comments