Skip to content

Fix popups anchored to body instead of viewport due to CSS filter containing block#4

Draft
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-popup-display-issues
Draft

Fix popups anchored to body instead of viewport due to CSS filter containing block#4
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-popup-display-issues

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 14, 2026

Popups always rendered at the top of the page and scrolled away with the content instead of staying fixed to the viewport. Opening a popup while scrolled down made it unreachable.

Root cause

body had animation: backgroundPulse whose keyframes applied filter: saturate() brightness(). Per CSS spec, any element with an active filter creates a new containing block for position: fixed descendants — overriding position: fixed !important on the overlay divs and anchoring them to the body's coordinate space instead of the viewport.

Changes

  • src/styles.css — Strip animation from body; move it to a body::before pseudo-element (position: fixed; inset: 0; z-index: -1; pointer-events: none). Pseudo-elements are not DOM ancestors of the popup nodes, so their filter cannot affect the popups' containing block.
/* Before — filter on body breaks position:fixed for all descendants */
body { animation: backgroundPulse 18s ease-in-out infinite; }

/* After — animation lives on a pseudo-element, body stays filter-free */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  animation: backgroundPulse 18s ease-in-out infinite;
}
  • schedule-list.component.html — Move movie-popup-overlay outside .container so both popups sit at the component root, away from any element that could inadvertently become a containing block. Wire (click) handlers to dedicated methods.

  • schedule-list.component.ts — Add openMoviePopup/closeMoviePopup and openSchedulePopup/closeSchedulePopup methods that toggle document.body.style.overflow = 'hidden' to block background scroll while a popup is open. Add ngOnDestroy to guarantee overflow is restored on navigation/component teardown.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • fonts.googleapis.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node node_modules/.bin/ng build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

…f body

The root cause was that `body` had `animation: backgroundPulse` which applied
CSS `filter` at every keyframe. Per the CSS spec, any element with an active
`filter` property creates a new containing block for all `position: fixed`
descendants. As a result, the popup overlays (`.movie-popup-overlay`,
`.schedule-popup-overlay`) were anchored to the top of the scrolling `body`
instead of the viewport — they appeared correctly when at the top of the page
but were hidden/unreachable after scrolling down.

Fixes:
1. styles.css – remove `animation: backgroundPulse` from `body`; add a
   `body::before` pseudo-element (`position:fixed; inset:0; z-index:-1;
   pointer-events:none`) that carries the same animation. A pseudo-element is
   not an ancestor of the popup overlays, so it never affects their
   containing block.

2. schedule-list.component.html – move `movie-popup-overlay` outside the
   `.container` div (same level as the already-correct `schedule-popup-overlay`)
   and wire all open/close calls to the new component methods.

3. schedule-list.component.ts – add `openMoviePopup/closeMoviePopup` and
   `openSchedulePopup/closeSchedulePopup` methods that toggle
   `document.body.style.overflow = 'hidden'` so the background page does not
   scroll while a popup is visible. `ngOnDestroy` guarantees the overflow is
   restored if navigation occurs with a popup still open.

Agent-Logs-Url: https://github.com/Programmercito/horarios-cine/sessions/3c0406f0-2704-4794-8f9a-7890bc3e6827

Co-authored-by: Programmercito <4504287+Programmercito@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix popup display issues in the app Fix popups anchored to body instead of viewport due to CSS filter containing block Apr 14, 2026
Copilot AI requested a review from Programmercito April 14, 2026 15:25
@Programmercito Programmercito requested a review from Copilot April 14, 2026 15:27
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes popup overlays incorrectly anchoring to the page (scrolling away) by removing filter-driven animation from body (which creates a containing block for position: fixed) and restructuring popup placement/handlers to keep overlays viewport-fixed and prevent background scrolling while open.

Changes:

  • Move backgroundPulse animation off body onto body::before to avoid creating a containing block for fixed-position overlays.
  • Relocate popup overlay markup outside the .container and route overlay clicks through dedicated close methods.
  • Add open/close popup methods plus ngOnDestroy cleanup to lock/unlock body scrolling via document.body.style.overflow.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/styles.css Moves filter animation off body to prevent fixed overlays being positioned relative to the body.
src/app/schedule-list/schedule-list.component.html Moves popup overlays to the component root and wires overlay clicks to close handlers.
src/app/schedule-list/schedule-list.component.ts Adds popup open/close methods with body scroll locking and ensures cleanup on destroy.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/styles.css
Comment on lines +108 to 115
body::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
animation: backgroundPulse 18s ease-in-out infinite;
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

body::before only sets content/positioning and animates filter, but it has no background (and no rendered content), so the backgroundPulse animation will have no visible effect. If you want to keep the ambient pulse, move the body background (gradient + radial background-image) onto the pseudo-element (or set an explicit background on body::before) and make the body background transparent, so the filter animation affects visible pixels without impacting position: fixed descendants.

Copilot uses AI. Check for mistakes.
Comment on lines +270 to 290
closeMoviePopup() {
this.showMoviePopup = false;
document.body.style.overflow = '';
}

// Schedule popup method
showScheduleDetails(schedule: any, movieTitle: string) {
this.currentSchedule = schedule;
this.currentMovieTitle = movieTitle;
this.openSchedulePopup();
}

openSchedulePopup() {
this.showSchedulePopup = true;
document.body.style.overflow = 'hidden';
}

closeSchedulePopup() {
this.showSchedulePopup = false;
document.body.style.overflow = '';
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closeMoviePopup() and closeSchedulePopup() unconditionally clear document.body.style.overflow. Since showMoviePopup and showSchedulePopup are independent flags, it’s possible for both popups to be open (or to become open in the future); closing one would re-enable background scrolling while the other overlay is still displayed. Consider centralizing the scroll-lock logic (e.g., a helper that sets overflow based on showMoviePopup || showSchedulePopup, or a reference-counted lock) so scroll remains disabled as long as any popup is open.

Copilot uses AI. Check for mistakes.
Comment on lines +265 to +268
openMoviePopup() {
this.showMoviePopup = true;
document.body.style.overflow = 'hidden';
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directly touching document.body makes this component harder to test and incompatible with non-DOM runtimes (e.g., SSR) if introduced later. Prefer injecting DOCUMENT (from @angular/common) and/or using Renderer2 to toggle a CSS class on the body for scroll locking, instead of setting inline styles via the global document reference.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Los popups de la app están fallando

3 participants