@@ -36,6 +36,13 @@ export class Content implements ComponentInterface {
3636 private resizeTimeout : ReturnType < typeof setTimeout > | null = null ;
3737 private inheritedAttributes : Attributes = { } ;
3838
39+ /**
40+ * Track whether this content has sibling header/footer elements.
41+ * When absent, we need to apply safe-area padding directly.
42+ */
43+ private hasHeader = false ;
44+ private hasFooter = false ;
45+
3946 private tabsElement : HTMLElement | null = null ;
4047 private tabsLoadCallback ?: ( ) => void ;
4148
@@ -134,6 +141,9 @@ export class Content implements ComponentInterface {
134141 connectedCallback ( ) {
135142 this . isMainContent = this . el . closest ( 'ion-menu, ion-popover, ion-modal' ) === null ;
136143
144+ // Detect sibling header/footer for safe-area handling
145+ this . detectSiblingElements ( ) ;
146+
137147 /**
138148 * The fullscreen content offsets need to be
139149 * computed after the tab bar has loaded. Since
@@ -170,6 +180,27 @@ export class Content implements ComponentInterface {
170180 }
171181 }
172182
183+ /**
184+ * Detects sibling ion-header and ion-footer elements.
185+ * When these are absent, content needs to handle safe-area padding directly.
186+ */
187+ private detectSiblingElements ( ) {
188+ // Check parent element for sibling header/footer.
189+ const parent = this . el . parentElement ;
190+ if ( parent ) {
191+ this . hasHeader = parent . querySelector ( ':scope > ion-header' ) !== null ;
192+ this . hasFooter = parent . querySelector ( ':scope > ion-footer' ) !== null ;
193+ }
194+
195+ // If no footer found, check if we're inside ion-tabs which has ion-tab-bar
196+ if ( ! this . hasFooter ) {
197+ const tabs = this . el . closest ( 'ion-tabs' ) ;
198+ if ( tabs ) {
199+ this . hasFooter = tabs . querySelector ( ':scope > ion-tab-bar' ) !== null ;
200+ }
201+ }
202+ }
203+
173204 disconnectedCallback ( ) {
174205 this . onScrollEnd ( ) ;
175206
@@ -449,7 +480,7 @@ export class Content implements ComponentInterface {
449480 }
450481
451482 render ( ) {
452- const { fixedSlotPlacement, inheritedAttributes, isMainContent, scrollX, scrollY, el } = this ;
483+ const { fixedSlotPlacement, hasFooter , hasHeader , inheritedAttributes, isMainContent, scrollX, scrollY, el } = this ;
453484 const rtl = isRTL ( el ) ? 'rtl' : 'ltr' ;
454485 const mode = getIonMode ( this ) ;
455486 const forceOverscroll = this . shouldForceOverscroll ( ) ;
@@ -465,6 +496,8 @@ export class Content implements ComponentInterface {
465496 'content-sizing' : hostContext ( 'ion-popover' , this . el ) ,
466497 overscroll : forceOverscroll ,
467498 [ `content-${ rtl } ` ] : true ,
499+ 'safe-area-top' : isMainContent && ! hasHeader ,
500+ 'safe-area-bottom' : isMainContent && ! hasFooter ,
468501 } ) }
469502 style = { {
470503 '--offset-top' : `${ this . cTop } px` ,
0 commit comments