X-Frame-Options is the legacy control and CSP frame-ancestors is its modern successor. Where both are present and disagree, browsers give precedence to frame-ancestors — so a strict CSP can legitimately override a permissive X-Frame-Options, and vice versa. Set them consistently to avoid confusion.
X-Frame-Options only understands DENY and SAMEORIGIN. The old ALLOW-FROM uri value was dropped by modern browsers and is effectively ignored, so a page relying on it is unprotected in current Chrome, Firefox, and Safari. To allow specific external origins to frame you, you must use CSP frame-ancestors, which is the only mechanism that supports an allowlist.
frame-ancestors is not covered by CSP's default-src fallback. If your Content-Security-Policy omits frame-ancestors, the page is framable regardless of how strict the rest of your CSP is — you have to declare frame-ancestors explicitly (e.g. frame-ancestors 'self' or 'none').
Anti-framing headers must be sent on the response for every sensitive page, not just the homepage. A common mistake is setting the header globally but having a CDN, error page, or specific route strip or bypass it — always test the actual sensitive URLs, not just the root domain.